diff options
Diffstat (limited to 'drivers/net/ethernet/netronome')
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/bpf/main.c | 55 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/bpf/main.h | 8 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/nfp_net_repr.c | 15 | 
3 files changed, 58 insertions, 20 deletions
| diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c index e379b78e86ef..13190aa09faf 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c @@ -82,10 +82,33 @@ static const char *nfp_bpf_extra_cap(struct nfp_app *app, struct nfp_net *nn)  	return nfp_net_ebpf_capable(nn) ? "BPF" : "";  } +static int +nfp_bpf_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, unsigned int id) +{ +	int err; + +	nn->app_priv = kzalloc(sizeof(struct nfp_bpf_vnic), GFP_KERNEL); +	if (!nn->app_priv) +		return -ENOMEM; + +	err = nfp_app_nic_vnic_alloc(app, nn, id); +	if (err) +		goto err_free_priv; + +	return 0; +err_free_priv: +	kfree(nn->app_priv); +	return err; +} +  static void nfp_bpf_vnic_free(struct nfp_app *app, struct nfp_net *nn)  { +	struct nfp_bpf_vnic *bv = nn->app_priv; +  	if (nn->dp.bpf_offload_xdp)  		nfp_bpf_xdp_offload(app, nn, NULL); +	WARN_ON(bv->tc_prog); +	kfree(bv);  }  static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type, @@ -93,6 +116,9 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,  {  	struct tc_cls_bpf_offload *cls_bpf = type_data;  	struct nfp_net *nn = cb_priv; +	struct bpf_prog *oldprog; +	struct nfp_bpf_vnic *bv; +	int err;  	if (type != TC_SETUP_CLSBPF ||  	    !tc_can_offload(nn->dp.netdev) || @@ -100,8 +126,6 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,  	    cls_bpf->common.protocol != htons(ETH_P_ALL) ||  	    cls_bpf->common.chain_index)  		return -EOPNOTSUPP; -	if (nn->dp.bpf_offload_xdp) -		return -EBUSY;  	/* Only support TC direct action */  	if (!cls_bpf->exts_integrated || @@ -110,16 +134,25 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,  		return -EOPNOTSUPP;  	} -	switch (cls_bpf->command) { -	case TC_CLSBPF_REPLACE: -		return nfp_net_bpf_offload(nn, cls_bpf->prog, true); -	case TC_CLSBPF_ADD: -		return nfp_net_bpf_offload(nn, cls_bpf->prog, false); -	case TC_CLSBPF_DESTROY: -		return nfp_net_bpf_offload(nn, NULL, true); -	default: +	if (cls_bpf->command != TC_CLSBPF_OFFLOAD)  		return -EOPNOTSUPP; + +	bv = nn->app_priv; +	oldprog = cls_bpf->oldprog; + +	/* Don't remove if oldprog doesn't match driver's state */ +	if (bv->tc_prog != oldprog) { +		oldprog = NULL; +		if (!cls_bpf->prog) +			return 0;  	} + +	err = nfp_net_bpf_offload(nn, cls_bpf->prog, oldprog); +	if (err) +		return err; + +	bv->tc_prog = cls_bpf->prog; +	return 0;  }  static int nfp_bpf_setup_tc_block(struct net_device *netdev, @@ -167,7 +200,7 @@ const struct nfp_app_type app_bpf = {  	.extra_cap	= nfp_bpf_extra_cap, -	.vnic_alloc	= nfp_app_nic_vnic_alloc, +	.vnic_alloc	= nfp_bpf_vnic_alloc,  	.vnic_free	= nfp_bpf_vnic_free,  	.setup_tc	= nfp_bpf_setup_tc, diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h index 082a15f6dfb5..57b6043177a3 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.h +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h @@ -172,6 +172,14 @@ struct nfp_prog {  	struct list_head insns;  }; +/** + * struct nfp_bpf_vnic - per-vNIC BPF priv structure + * @tc_prog:	currently loaded cls_bpf program + */ +struct nfp_bpf_vnic { +	struct bpf_prog *tc_prog; +}; +  int nfp_bpf_jit(struct nfp_prog *prog);  extern const struct bpf_ext_analyzer_ops nfp_bpf_analyzer_ops; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c index 924a05e05da0..78b36c67c232 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c @@ -84,16 +84,13 @@ nfp_repr_phy_port_get_stats64(struct nfp_port *port,  {  	u8 __iomem *mem = port->eth_stats; -	/* TX and RX stats are flipped as we are returning the stats as seen -	 * at the switch port corresponding to the phys port. -	 */ -	stats->tx_packets = readq(mem + NFP_MAC_STATS_RX_FRAMES_RECEIVED_OK); -	stats->tx_bytes = readq(mem + NFP_MAC_STATS_RX_IN_OCTETS); -	stats->tx_dropped = readq(mem + NFP_MAC_STATS_RX_IN_ERRORS); +	stats->tx_packets = readq(mem + NFP_MAC_STATS_TX_FRAMES_TRANSMITTED_OK); +	stats->tx_bytes = readq(mem + NFP_MAC_STATS_TX_OUT_OCTETS); +	stats->tx_dropped = readq(mem + NFP_MAC_STATS_TX_OUT_ERRORS); -	stats->rx_packets = readq(mem + NFP_MAC_STATS_TX_FRAMES_TRANSMITTED_OK); -	stats->rx_bytes = readq(mem + NFP_MAC_STATS_TX_OUT_OCTETS); -	stats->rx_dropped = readq(mem + NFP_MAC_STATS_TX_OUT_ERRORS); +	stats->rx_packets = readq(mem + NFP_MAC_STATS_RX_FRAMES_RECEIVED_OK); +	stats->rx_bytes = readq(mem + NFP_MAC_STATS_RX_IN_OCTETS); +	stats->rx_dropped = readq(mem + NFP_MAC_STATS_RX_IN_ERRORS);  }  static void |