Commit 844f63f5 authored by David S. Miller's avatar David S. Miller

Merge branch 'nfp-AF_XDP-zero-copy'

Simon Horman says:

====================
Add AF_XDP zero-copy support for NFP

Niklas Söderlund says:

This series adds AF_XDP zero-copy support for the NFP driver. The series
is based on previous work done by Jakub Kicinski.

Patch 1/5 and 2/5 prepares the driver for AF_XDP support by refactoring
functions that will act differently once AF_XDP is active or not making
the driver easier to read and by preparing some functions to be reused
outside the local file scope. Patch 3/5 and 4/5 prepares the driver for
dealing the UMEM while finally patch 5/5 adds AF_XDP support.

Based on work by Jakub Kicinski.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 34fe804e 6402528b
...@@ -31,6 +31,7 @@ nfp-objs := \ ...@@ -31,6 +31,7 @@ nfp-objs := \
nfp_net_main.o \ nfp_net_main.o \
nfp_net_repr.o \ nfp_net_repr.o \
nfp_net_sriov.o \ nfp_net_sriov.o \
nfp_net_xsk.o \
nfp_netvf_main.o \ nfp_netvf_main.o \
nfp_port.o \ nfp_port.o \
nfp_shared_buf.o \ nfp_shared_buf.o \
......
...@@ -109,6 +109,7 @@ struct nfp_eth_table_port; ...@@ -109,6 +109,7 @@ struct nfp_eth_table_port;
struct nfp_net; struct nfp_net;
struct nfp_net_r_vector; struct nfp_net_r_vector;
struct nfp_port; struct nfp_port;
struct xsk_buff_pool;
/* Convenience macro for wrapping descriptor index on ring size */ /* Convenience macro for wrapping descriptor index on ring size */
#define D_IDX(ring, idx) ((idx) & ((ring)->cnt - 1)) #define D_IDX(ring, idx) ((idx) & ((ring)->cnt - 1))
...@@ -170,11 +171,14 @@ struct nfp_net_tx_desc { ...@@ -170,11 +171,14 @@ struct nfp_net_tx_desc {
* struct nfp_net_tx_buf - software TX buffer descriptor * struct nfp_net_tx_buf - software TX buffer descriptor
* @skb: normal ring, sk_buff associated with this buffer * @skb: normal ring, sk_buff associated with this buffer
* @frag: XDP ring, page frag associated with this buffer * @frag: XDP ring, page frag associated with this buffer
* @xdp: XSK buffer pool handle (for AF_XDP)
* @dma_addr: DMA mapping address of the buffer * @dma_addr: DMA mapping address of the buffer
* @fidx: Fragment index (-1 for the head and [0..nr_frags-1] for frags) * @fidx: Fragment index (-1 for the head and [0..nr_frags-1] for frags)
* @pkt_cnt: Number of packets to be produced out of the skb associated * @pkt_cnt: Number of packets to be produced out of the skb associated
* with this buffer (valid only on the head's buffer). * with this buffer (valid only on the head's buffer).
* Will be 1 for all non-TSO packets. * Will be 1 for all non-TSO packets.
* @is_xsk_tx: Flag if buffer is a RX buffer after a XDP_TX action and not a
* buffer from the TX queue (for AF_XDP).
* @real_len: Number of bytes which to be produced out of the skb (valid only * @real_len: Number of bytes which to be produced out of the skb (valid only
* on the head's buffer). Equal to skb->len for non-TSO packets. * on the head's buffer). Equal to skb->len for non-TSO packets.
*/ */
...@@ -182,10 +186,18 @@ struct nfp_net_tx_buf { ...@@ -182,10 +186,18 @@ struct nfp_net_tx_buf {
union { union {
struct sk_buff *skb; struct sk_buff *skb;
void *frag; void *frag;
struct xdp_buff *xdp;
}; };
dma_addr_t dma_addr; dma_addr_t dma_addr;
union {
struct {
short int fidx; short int fidx;
u16 pkt_cnt; u16 pkt_cnt;
};
struct {
bool is_xsk_tx;
};
};
u32 real_len; u32 real_len;
}; };
...@@ -314,6 +326,16 @@ struct nfp_net_rx_buf { ...@@ -314,6 +326,16 @@ struct nfp_net_rx_buf {
dma_addr_t dma_addr; dma_addr_t dma_addr;
}; };
/**
* struct nfp_net_xsk_rx_buf - software RX XSK buffer descriptor
* @dma_addr: DMA mapping address of the buffer
* @xdp: XSK buffer pool handle (for AF_XDP)
*/
struct nfp_net_xsk_rx_buf {
dma_addr_t dma_addr;
struct xdp_buff *xdp;
};
/** /**
* struct nfp_net_rx_ring - RX ring structure * struct nfp_net_rx_ring - RX ring structure
* @r_vec: Back pointer to ring vector structure * @r_vec: Back pointer to ring vector structure
...@@ -324,6 +346,7 @@ struct nfp_net_rx_buf { ...@@ -324,6 +346,7 @@ struct nfp_net_rx_buf {
* @fl_qcidx: Queue Controller Peripheral (QCP) queue index for the freelist * @fl_qcidx: Queue Controller Peripheral (QCP) queue index for the freelist
* @qcp_fl: Pointer to base of the QCP freelist queue * @qcp_fl: Pointer to base of the QCP freelist queue
* @rxbufs: Array of transmitted FL/RX buffers * @rxbufs: Array of transmitted FL/RX buffers
* @xsk_rxbufs: Array of transmitted FL/RX buffers (for AF_XDP)
* @rxds: Virtual address of FL/RX ring in host memory * @rxds: Virtual address of FL/RX ring in host memory
* @xdp_rxq: RX-ring info avail for XDP * @xdp_rxq: RX-ring info avail for XDP
* @dma: DMA address of the FL/RX ring * @dma: DMA address of the FL/RX ring
...@@ -342,6 +365,7 @@ struct nfp_net_rx_ring { ...@@ -342,6 +365,7 @@ struct nfp_net_rx_ring {
u8 __iomem *qcp_fl; u8 __iomem *qcp_fl;
struct nfp_net_rx_buf *rxbufs; struct nfp_net_rx_buf *rxbufs;
struct nfp_net_xsk_rx_buf *xsk_rxbufs;
struct nfp_net_rx_desc *rxds; struct nfp_net_rx_desc *rxds;
struct xdp_rxq_info xdp_rxq; struct xdp_rxq_info xdp_rxq;
...@@ -360,6 +384,7 @@ struct nfp_net_rx_ring { ...@@ -360,6 +384,7 @@ struct nfp_net_rx_ring {
* @tx_ring: Pointer to TX ring * @tx_ring: Pointer to TX ring
* @rx_ring: Pointer to RX ring * @rx_ring: Pointer to RX ring
* @xdp_ring: Pointer to an extra TX ring for XDP * @xdp_ring: Pointer to an extra TX ring for XDP
* @xsk_pool: XSK buffer pool active on vector queue pair (for AF_XDP)
* @irq_entry: MSI-X table entry (use for talking to the device) * @irq_entry: MSI-X table entry (use for talking to the device)
* @event_ctr: Number of interrupt * @event_ctr: Number of interrupt
* @rx_dim: Dynamic interrupt moderation structure for RX * @rx_dim: Dynamic interrupt moderation structure for RX
...@@ -431,6 +456,7 @@ struct nfp_net_r_vector { ...@@ -431,6 +456,7 @@ struct nfp_net_r_vector {
u64 rx_replace_buf_alloc_fail; u64 rx_replace_buf_alloc_fail;
struct nfp_net_tx_ring *xdp_ring; struct nfp_net_tx_ring *xdp_ring;
struct xsk_buff_pool *xsk_pool;
struct u64_stats_sync tx_sync; struct u64_stats_sync tx_sync;
u64 tx_pkts; u64 tx_pkts;
...@@ -501,6 +527,7 @@ struct nfp_stat_pair { ...@@ -501,6 +527,7 @@ struct nfp_stat_pair {
* @num_stack_tx_rings: Number of TX rings used by the stack (not XDP) * @num_stack_tx_rings: Number of TX rings used by the stack (not XDP)
* @num_rx_rings: Currently configured number of RX rings * @num_rx_rings: Currently configured number of RX rings
* @mtu: Device MTU * @mtu: Device MTU
* @xsk_pools: XSK buffer pools, @max_r_vecs in size (for AF_XDP).
*/ */
struct nfp_net_dp { struct nfp_net_dp {
struct device *dev; struct device *dev;
...@@ -537,6 +564,8 @@ struct nfp_net_dp { ...@@ -537,6 +564,8 @@ struct nfp_net_dp {
unsigned int num_rx_rings; unsigned int num_rx_rings;
unsigned int mtu; unsigned int mtu;
struct xsk_buff_pool **xsk_pools;
}; };
/** /**
...@@ -965,6 +994,7 @@ int nfp_net_mbox_reconfig_and_unlock(struct nfp_net *nn, u32 mbox_cmd); ...@@ -965,6 +994,7 @@ int nfp_net_mbox_reconfig_and_unlock(struct nfp_net *nn, u32 mbox_cmd);
void nfp_net_mbox_reconfig_post(struct nfp_net *nn, u32 update); void nfp_net_mbox_reconfig_post(struct nfp_net *nn, u32 update);
int nfp_net_mbox_reconfig_wait_posted(struct nfp_net *nn); int nfp_net_mbox_reconfig_wait_posted(struct nfp_net *nn);
void nfp_net_irq_unmask(struct nfp_net *nn, unsigned int entry_nr);
unsigned int unsigned int
nfp_net_irqs_alloc(struct pci_dev *pdev, struct msix_entry *irq_entries, nfp_net_irqs_alloc(struct pci_dev *pdev, struct msix_entry *irq_entries,
unsigned int min_irqs, unsigned int want_irqs); unsigned int min_irqs, unsigned int want_irqs);
...@@ -973,6 +1003,19 @@ void ...@@ -973,6 +1003,19 @@ void
nfp_net_irqs_assign(struct nfp_net *nn, struct msix_entry *irq_entries, nfp_net_irqs_assign(struct nfp_net *nn, struct msix_entry *irq_entries,
unsigned int n); unsigned int n);
void nfp_net_tx_xmit_more_flush(struct nfp_net_tx_ring *tx_ring);
void nfp_net_tx_complete(struct nfp_net_tx_ring *tx_ring, int budget);
bool
nfp_net_parse_meta(struct net_device *netdev, struct nfp_meta_parsed *meta,
void *data, void *pkt, unsigned int pkt_len, int meta_len);
void nfp_net_rx_csum(const struct nfp_net_dp *dp,
struct nfp_net_r_vector *r_vec,
const struct nfp_net_rx_desc *rxd,
const struct nfp_meta_parsed *meta,
struct sk_buff *skb);
struct nfp_net_dp *nfp_net_clone_dp(struct nfp_net *nn); struct nfp_net_dp *nfp_net_clone_dp(struct nfp_net *nn);
int nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_dp *new, int nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_dp *new,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
......
...@@ -42,6 +42,7 @@ static int nfp_rx_q_show(struct seq_file *file, void *data) ...@@ -42,6 +42,7 @@ static int nfp_rx_q_show(struct seq_file *file, void *data)
seq_printf(file, "%04d: 0x%08x 0x%08x", i, seq_printf(file, "%04d: 0x%08x 0x%08x", i,
rxd->vals[0], rxd->vals[1]); rxd->vals[0], rxd->vals[1]);
if (!r_vec->xsk_pool) {
frag = READ_ONCE(rx_ring->rxbufs[i].frag); frag = READ_ONCE(rx_ring->rxbufs[i].frag);
if (frag) if (frag)
seq_printf(file, " frag=%p", frag); seq_printf(file, " frag=%p", frag);
...@@ -49,6 +50,11 @@ static int nfp_rx_q_show(struct seq_file *file, void *data) ...@@ -49,6 +50,11 @@ static int nfp_rx_q_show(struct seq_file *file, void *data)
if (rx_ring->rxbufs[i].dma_addr) if (rx_ring->rxbufs[i].dma_addr)
seq_printf(file, " dma_addr=%pad", seq_printf(file, " dma_addr=%pad",
&rx_ring->rxbufs[i].dma_addr); &rx_ring->rxbufs[i].dma_addr);
} else {
if (rx_ring->xsk_rxbufs[i].dma_addr)
seq_printf(file, " dma_addr=%pad",
&rx_ring->xsk_rxbufs[i].dma_addr);
}
if (i == rx_ring->rd_p % rxd_cnt) if (i == rx_ring->rd_p % rxd_cnt)
seq_puts(file, " H_RD "); seq_puts(file, " H_RD ");
...@@ -103,20 +109,23 @@ static int nfp_tx_q_show(struct seq_file *file, void *data) ...@@ -103,20 +109,23 @@ static int nfp_tx_q_show(struct seq_file *file, void *data)
tx_ring->rd_p, tx_ring->wr_p, d_rd_p, d_wr_p); tx_ring->rd_p, tx_ring->wr_p, d_rd_p, d_wr_p);
for (i = 0; i < txd_cnt; i++) { for (i = 0; i < txd_cnt; i++) {
struct xdp_buff *xdp;
struct sk_buff *skb;
txd = &tx_ring->txds[i]; txd = &tx_ring->txds[i];
seq_printf(file, "%04d: 0x%08x 0x%08x 0x%08x 0x%08x", i, seq_printf(file, "%04d: 0x%08x 0x%08x 0x%08x 0x%08x", i,
txd->vals[0], txd->vals[1], txd->vals[0], txd->vals[1],
txd->vals[2], txd->vals[3]); txd->vals[2], txd->vals[3]);
if (tx_ring == r_vec->tx_ring) { if (!tx_ring->is_xdp) {
struct sk_buff *skb = READ_ONCE(tx_ring->txbufs[i].skb); skb = READ_ONCE(tx_ring->txbufs[i].skb);
if (skb) if (skb)
seq_printf(file, " skb->head=%p skb->data=%p", seq_printf(file, " skb->head=%p skb->data=%p",
skb->head, skb->data); skb->head, skb->data);
} else { } else {
seq_printf(file, " frag=%p", xdp = READ_ONCE(tx_ring->txbufs[i].xdp);
READ_ONCE(tx_ring->txbufs[i].frag)); if (xdp)
seq_printf(file, " xdp->data=%p", xdp->data);
} }
if (tx_ring->txbufs[i].dma_addr) if (tx_ring->txbufs[i].dma_addr)
......
This diff is collapsed.
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/* Copyright (C) 2018 Netronome Systems, Inc */
/* Copyright (C) 2021 Corigine, Inc */
#ifndef _NFP_XSK_H_
#define _NFP_XSK_H_
#include <net/xdp_sock_drv.h>
#define NFP_NET_XSK_TX_BATCH 16 /* XSK TX transmission batch size. */
static inline bool nfp_net_has_xsk_pool_slow(struct nfp_net_dp *dp,
unsigned int qid)
{
return dp->xdp_prog && dp->xsk_pools[qid];
}
int nfp_net_xsk_setup_pool(struct net_device *netdev, struct xsk_buff_pool *pool,
u16 queue_id);
void nfp_net_xsk_tx_bufs_free(struct nfp_net_tx_ring *tx_ring);
void nfp_net_xsk_rx_bufs_free(struct nfp_net_rx_ring *rx_ring);
void nfp_net_xsk_rx_ring_fill_freelist(struct nfp_net_rx_ring *rx_ring);
int nfp_net_xsk_wakeup(struct net_device *netdev, u32 queue_id, u32 flags);
int nfp_net_xsk_poll(struct napi_struct *napi, int budget);
#endif /* _NFP_XSK_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment