Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ecd63a02 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

nfp: add XDP support in the driver



Add XDP support.  Separate stack's and XDP's TX rings logically.
Add functions for handling XDP_TX and cleanup of XDP's TX rings.
For XDP allocate all RX buffers as separate pages and map them
with DMA_BIDIRECTIONAL.

Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 68f929ff
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -171,7 +171,10 @@ struct nfp_net_tx_desc {
 *		on the head's buffer). Equal to skb->len for non-TSO packets.
 */
struct nfp_net_tx_buf {
	union {
		struct sk_buff *skb;
		void *frag;
	};
	dma_addr_t dma_addr;
	short int fidx;
	u16 pkt_cnt;
@@ -341,6 +344,7 @@ struct nfp_net_rx_ring {
 * @napi:           NAPI structure for this ring vec
 * @tx_ring:        Pointer to TX ring
 * @rx_ring:        Pointer to RX ring
 * @xdp_ring:	    Pointer to an extra TX ring for XDP
 * @irq_idx:        Index into MSI-X table
 * @rx_sync:	    Seqlock for atomic updates of RX stats
 * @rx_pkts:        Number of received packets
@@ -384,6 +388,8 @@ struct nfp_net_r_vector {
	u64 hw_csum_rx_inner_ok;
	u64 hw_csum_rx_error;

	struct nfp_net_tx_ring *xdp_ring;

	struct u64_stats_sync tx_sync;
	u64 tx_pkts;
	u64 tx_bytes;
@@ -432,6 +438,7 @@ struct nfp_stat_pair {
 * @ctrl:               Local copy of the control register/word.
 * @fl_bufsz:           Currently configured size of the freelist buffers
 * @rx_offset:		Offset in the RX buffers where packet data starts
 * @xdp_prog:		Installed XDP program
 * @cpp:                Pointer to the CPP handle
 * @nfp_dev_cpp:        Pointer to the NFP Device handle
 * @ctrl_area:          Pointer to the CPP area for the control BAR
@@ -451,6 +458,7 @@ struct nfp_stat_pair {
 * @max_tx_rings:       Maximum number of TX rings supported by the Firmware
 * @max_rx_rings:       Maximum number of RX rings supported by the Firmware
 * @num_tx_rings:       Currently configured number of TX rings
 * @num_stack_tx_rings:	Number of TX rings used by the stack (not XDP)
 * @num_rx_rings:       Currently configured number of RX rings
 * @txd_cnt:            Size of the TX ring in number of descriptors
 * @rxd_cnt:            Size of the RX ring in number of descriptors
@@ -500,6 +508,8 @@ struct nfp_net {

	u32 rx_offset;

	struct bpf_prog *xdp_prog;

	struct nfp_net_tx_ring *tx_rings;
	struct nfp_net_rx_ring *rx_rings;

@@ -532,6 +542,7 @@ struct nfp_net {
	unsigned int max_rx_rings;

	unsigned int num_tx_rings;
	unsigned int num_stack_tx_rings;
	unsigned int num_rx_rings;

	int stride_tx;
@@ -779,8 +790,8 @@ void nfp_net_coalesce_write_cfg(struct nfp_net *nn);
int nfp_net_irqs_alloc(struct nfp_net *nn);
void nfp_net_irqs_disable(struct nfp_net *nn);
int
nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_ring_set *rx,
		      struct nfp_net_ring_set *tx);
nfp_net_ring_reconfig(struct nfp_net *nn, struct bpf_prog **xdp_prog,
		      struct nfp_net_ring_set *rx, struct nfp_net_ring_set *tx);

#ifdef CONFIG_NFP_NET_DEBUG
void nfp_net_debugfs_create(void);
+389 −85

File changed.

Preview size limit exceeded, changes collapsed.

+29 −8
Original line number Diff line number Diff line
@@ -114,6 +114,16 @@ static const struct file_operations nfp_rx_q_fops = {
	.llseek = seq_lseek
};

static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f);

static const struct file_operations nfp_tx_q_fops = {
	.owner = THIS_MODULE,
	.open = nfp_net_debugfs_tx_q_open,
	.release = single_release,
	.read = seq_read,
	.llseek = seq_lseek
};

static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)
{
	struct nfp_net_r_vector *r_vec = file->private;
@@ -126,10 +136,13 @@ static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)

	rtnl_lock();

	if (!r_vec->nfp_net || !r_vec->tx_ring)
	if (debugfs_real_fops(file->file) == &nfp_tx_q_fops)
		tx_ring = r_vec->tx_ring;
	else
		tx_ring = r_vec->xdp_ring;
	if (!r_vec->nfp_net || !tx_ring)
		goto out;
	nn = r_vec->nfp_net;
	tx_ring = r_vec->tx_ring;
	if (!netif_running(nn->netdev))
		goto out;

@@ -148,9 +161,14 @@ static int nfp_net_debugfs_tx_q_read(struct seq_file *file, void *data)
			   txd->vals[2], txd->vals[3]);

		skb = READ_ONCE(tx_ring->txbufs[i].skb);
		if (skb)
		if (skb) {
			if (tx_ring == r_vec->tx_ring)
				seq_printf(file, " skb->head=%p skb->data=%p",
					   skb->head, skb->data);
			else
				seq_printf(file, " frag=%p", skb);
		}

		if (tx_ring->txbufs[i].dma_addr)
			seq_printf(file, " dma_addr=%pad",
				   &tx_ring->txbufs[i].dma_addr);
@@ -176,7 +194,7 @@ static int nfp_net_debugfs_tx_q_open(struct inode *inode, struct file *f)
	return single_open(f, nfp_net_debugfs_tx_q_read, inode->i_private);
}

static const struct file_operations nfp_tx_q_fops = {
static const struct file_operations nfp_xdp_q_fops = {
	.owner = THIS_MODULE,
	.open = nfp_net_debugfs_tx_q_open,
	.release = single_release,
@@ -186,7 +204,7 @@ static const struct file_operations nfp_tx_q_fops = {

void nfp_net_debugfs_adapter_add(struct nfp_net *nn)
{
	struct dentry *queues, *tx, *rx;
	struct dentry *queues, *tx, *rx, *xdp;
	char int_name[16];
	int i;

@@ -204,13 +222,16 @@ void nfp_net_debugfs_adapter_add(struct nfp_net *nn)

	rx = debugfs_create_dir("rx", queues);
	tx = debugfs_create_dir("tx", queues);
	if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx))
	xdp = debugfs_create_dir("xdp", queues);
	if (IS_ERR_OR_NULL(rx) || IS_ERR_OR_NULL(tx) || IS_ERR_OR_NULL(xdp))
		return;

	for (i = 0; i < min(nn->max_rx_rings, nn->max_r_vecs); i++) {
		sprintf(int_name, "%d", i);
		debugfs_create_file(int_name, S_IRUSR, rx,
				    &nn->r_vecs[i], &nfp_rx_q_fops);
		debugfs_create_file(int_name, S_IRUSR, xdp,
				    &nn->r_vecs[i], &nfp_xdp_q_fops);
	}

	for (i = 0; i < min(nn->max_tx_rings, nn->max_r_vecs); i++) {
+17 −5
Original line number Diff line number Diff line
@@ -176,7 +176,8 @@ static int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt)
	if (nn->txd_cnt != txd_cnt)
		reconfig_tx = &tx;

	return nfp_net_ring_reconfig(nn, reconfig_rx, reconfig_tx);
	return nfp_net_ring_reconfig(nn, &nn->xdp_prog,
				     reconfig_rx, reconfig_tx);
}

static int nfp_net_set_ringparam(struct net_device *netdev,
@@ -639,14 +640,19 @@ static void nfp_net_get_channels(struct net_device *netdev,
				 struct ethtool_channels *channel)
{
	struct nfp_net *nn = netdev_priv(netdev);
	unsigned int num_tx_rings;

	num_tx_rings = nn->num_tx_rings;
	if (nn->xdp_prog)
		num_tx_rings -= nn->num_rx_rings;

	channel->max_rx = min(nn->max_rx_rings, nn->max_r_vecs);
	channel->max_tx = min(nn->max_tx_rings, nn->max_r_vecs);
	channel->max_combined = min(channel->max_rx, channel->max_tx);
	channel->max_other = NFP_NET_NON_Q_VECTORS;
	channel->combined_count = min(nn->num_rx_rings, nn->num_tx_rings);
	channel->combined_count = min(nn->num_rx_rings, num_tx_rings);
	channel->rx_count = nn->num_rx_rings - channel->combined_count;
	channel->tx_count = nn->num_tx_rings - channel->combined_count;
	channel->tx_count = num_tx_rings - channel->combined_count;
	channel->other_count = NFP_NET_NON_Q_VECTORS;
}

@@ -666,10 +672,16 @@ static int nfp_net_set_num_rings(struct nfp_net *nn, unsigned int total_rx,

	if (nn->num_rx_rings != total_rx)
		reconfig_rx = &rx;
	if (nn->num_tx_rings != total_tx)
	if (nn->num_stack_tx_rings != total_tx ||
	    (nn->xdp_prog && reconfig_rx))
		reconfig_tx = &tx;

	return nfp_net_ring_reconfig(nn, reconfig_rx, reconfig_tx);
	/* nfp_net_check_config() will catch tx.n_rings > nn->max_tx_rings */
	if (nn->xdp_prog)
		tx.n_rings += total_rx;

	return nfp_net_ring_reconfig(nn, &nn->xdp_prog,
				     reconfig_rx, reconfig_tx);
}

static int nfp_net_set_channels(struct net_device *netdev,