Skip to content

Commit

Permalink
xsk: i40e: ice: ixgbe: mlx5: Pass buffer pool to driver instead of umem
Browse files Browse the repository at this point in the history
Replace the explicit umem reference passed to the driver in AF_XDP
zero-copy mode with the buffer pool instead. This in preparation for
extending the functionality of the zero-copy mode so that umems can be
shared between queues on the same netdev and also between netdevs. In
this commit, only an umem reference has been added to the buffer pool
struct. But later commits will add other entities to it. These are
going to be entities that are different between different queue ids
and netdevs even though the umem is shared between them.

Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Björn Töpel <bjorn.topel@intel.com>
Link: https://lore.kernel.org/bpf/1598603189-32145-2-git-send-email-magnus.karlsson@intel.com
  • Loading branch information
Magnus Karlsson authored and Daniel Borkmann committed Aug 31, 2020
1 parent 29523c5 commit 1742b3d
Show file tree
Hide file tree
Showing 40 changed files with 413 additions and 398 deletions.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/i40e/i40e_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1967,7 +1967,7 @@ static int i40e_set_ringparam(struct net_device *netdev,
(new_rx_count == vsi->rx_rings[0]->count))
return 0;

/* If there is a AF_XDP UMEM attached to any of Rx rings,
/* If there is a AF_XDP page pool attached to any of Rx rings,
* disallow changing the number of descriptors -- regardless
* if the netdev is running or not.
*/
Expand Down
29 changes: 15 additions & 14 deletions drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3122,12 +3122,12 @@ static void i40e_config_xps_tx_ring(struct i40e_ring *ring)
}

/**
* i40e_xsk_umem - Retrieve the AF_XDP ZC if XDP and ZC is enabled
* i40e_xsk_pool - Retrieve the AF_XDP buffer pool if XDP and ZC is enabled
* @ring: The Tx or Rx ring
*
* Returns the UMEM or NULL.
* Returns the AF_XDP buffer pool or NULL.
**/
static struct xdp_umem *i40e_xsk_umem(struct i40e_ring *ring)
static struct xsk_buff_pool *i40e_xsk_pool(struct i40e_ring *ring)
{
bool xdp_on = i40e_enabled_xdp_vsi(ring->vsi);
int qid = ring->queue_index;
Expand All @@ -3138,7 +3138,7 @@ static struct xdp_umem *i40e_xsk_umem(struct i40e_ring *ring)
if (!xdp_on || !test_bit(qid, ring->vsi->af_xdp_zc_qps))
return NULL;

return xdp_get_umem_from_qid(ring->vsi->netdev, qid);
return xdp_get_xsk_pool_from_qid(ring->vsi->netdev, qid);
}

/**
Expand All @@ -3157,7 +3157,7 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
u32 qtx_ctl = 0;

if (ring_is_xdp(ring))
ring->xsk_umem = i40e_xsk_umem(ring);
ring->xsk_pool = i40e_xsk_pool(ring);

/* some ATR related tx ring init */
if (vsi->back->flags & I40E_FLAG_FD_ATR_ENABLED) {
Expand Down Expand Up @@ -3280,12 +3280,13 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);

kfree(ring->rx_bi);
ring->xsk_umem = i40e_xsk_umem(ring);
if (ring->xsk_umem) {
ring->xsk_pool = i40e_xsk_pool(ring);
if (ring->xsk_pool) {
ret = i40e_alloc_rx_bi_zc(ring);
if (ret)
return ret;
ring->rx_buf_len = xsk_umem_get_rx_frame_size(ring->xsk_umem);
ring->rx_buf_len =
xsk_umem_get_rx_frame_size(ring->xsk_pool->umem);
/* For AF_XDP ZC, we disallow packets to span on
* multiple buffers, thus letting us skip that
* handling in the fast-path.
Expand Down Expand Up @@ -3368,8 +3369,8 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
ring->tail = hw->hw_addr + I40E_QRX_TAIL(pf_q);
writel(0, ring->tail);

if (ring->xsk_umem) {
xsk_buff_set_rxq_info(ring->xsk_umem, &ring->xdp_rxq);
if (ring->xsk_pool) {
xsk_buff_set_rxq_info(ring->xsk_pool->umem, &ring->xdp_rxq);
ok = i40e_alloc_rx_buffers_zc(ring, I40E_DESC_UNUSED(ring));
} else {
ok = !i40e_alloc_rx_buffers(ring, I40E_DESC_UNUSED(ring));
Expand All @@ -3380,7 +3381,7 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
*/
dev_info(&vsi->back->pdev->dev,
"Failed to allocate some buffers on %sRx ring %d (pf_q %d)\n",
ring->xsk_umem ? "UMEM enabled " : "",
ring->xsk_pool ? "AF_XDP ZC enabled " : "",
ring->queue_index, pf_q);
}

Expand Down Expand Up @@ -12644,7 +12645,7 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi,
*/
if (need_reset && prog)
for (i = 0; i < vsi->num_queue_pairs; i++)
if (vsi->xdp_rings[i]->xsk_umem)
if (vsi->xdp_rings[i]->xsk_pool)
(void)i40e_xsk_wakeup(vsi->netdev, i,
XDP_WAKEUP_RX);

Expand Down Expand Up @@ -12923,8 +12924,8 @@ static int i40e_xdp(struct net_device *dev,
switch (xdp->command) {
case XDP_SETUP_PROG:
return i40e_xdp_setup(vsi, xdp->prog);
case XDP_SETUP_XSK_UMEM:
return i40e_xsk_umem_setup(vsi, xdp->xsk.umem,
case XDP_SETUP_XSK_POOL:
return i40e_xsk_pool_setup(vsi, xdp->xsk.pool,
xdp->xsk.queue_id);
default:
return -EINVAL;
Expand Down
10 changes: 5 additions & 5 deletions drivers/net/ethernet/intel/i40e/i40e_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ void i40e_clean_tx_ring(struct i40e_ring *tx_ring)
unsigned long bi_size;
u16 i;

if (ring_is_xdp(tx_ring) && tx_ring->xsk_umem) {
if (ring_is_xdp(tx_ring) && tx_ring->xsk_pool) {
i40e_xsk_clean_tx_ring(tx_ring);
} else {
/* ring already cleared, nothing to do */
Expand Down Expand Up @@ -1335,7 +1335,7 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring)
rx_ring->skb = NULL;
}

if (rx_ring->xsk_umem) {
if (rx_ring->xsk_pool) {
i40e_xsk_clean_rx_ring(rx_ring);
goto skip_free;
}
Expand Down Expand Up @@ -1369,7 +1369,7 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring)
}

skip_free:
if (rx_ring->xsk_umem)
if (rx_ring->xsk_pool)
i40e_clear_rx_bi_zc(rx_ring);
else
i40e_clear_rx_bi(rx_ring);
Expand Down Expand Up @@ -2579,7 +2579,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
* budget and be more aggressive about cleaning up the Tx descriptors.
*/
i40e_for_each_ring(ring, q_vector->tx) {
bool wd = ring->xsk_umem ?
bool wd = ring->xsk_pool ?
i40e_clean_xdp_tx_irq(vsi, ring) :
i40e_clean_tx_irq(vsi, ring, budget);

Expand Down Expand Up @@ -2607,7 +2607,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
budget_per_ring = budget;

i40e_for_each_ring(ring, q_vector->rx) {
int cleaned = ring->xsk_umem ?
int cleaned = ring->xsk_pool ?
i40e_clean_rx_irq_zc(ring, budget_per_ring) :
i40e_clean_rx_irq(ring, budget_per_ring);

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/i40e/i40e_txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ struct i40e_ring {

struct i40e_channel *ch;
struct xdp_rxq_info xdp_rxq;
struct xdp_umem *xsk_umem;
struct xsk_buff_pool *xsk_pool;
} ____cacheline_internodealigned_in_smp;

static inline bool ring_uses_build_skb(struct i40e_ring *ring)
Expand Down
81 changes: 44 additions & 37 deletions drivers/net/ethernet/intel/i40e/i40e_xsk.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ static struct xdp_buff **i40e_rx_bi(struct i40e_ring *rx_ring, u32 idx)
}

/**
* i40e_xsk_umem_enable - Enable/associate a UMEM to a certain ring/qid
* i40e_xsk_pool_enable - Enable/associate an AF_XDP buffer pool to a
* certain ring/qid
* @vsi: Current VSI
* @umem: UMEM
* @qid: Rx ring to associate UMEM to
* @pool: buffer pool
* @qid: Rx ring to associate buffer pool with
*
* Returns 0 on success, <0 on failure
**/
static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
static int i40e_xsk_pool_enable(struct i40e_vsi *vsi,
struct xsk_buff_pool *pool,
u16 qid)
{
struct net_device *netdev = vsi->netdev;
Expand All @@ -53,7 +55,8 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
qid >= netdev->real_num_tx_queues)
return -EINVAL;

err = xsk_buff_dma_map(umem, &vsi->back->pdev->dev, I40E_RX_DMA_ATTR);
err = xsk_buff_dma_map(pool->umem, &vsi->back->pdev->dev,
I40E_RX_DMA_ATTR);
if (err)
return err;

Expand All @@ -80,21 +83,22 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
}

/**
* i40e_xsk_umem_disable - Disassociate a UMEM from a certain ring/qid
* i40e_xsk_pool_disable - Disassociate an AF_XDP buffer pool from a
* certain ring/qid
* @vsi: Current VSI
* @qid: Rx ring to associate UMEM to
* @qid: Rx ring to associate buffer pool with
*
* Returns 0 on success, <0 on failure
**/
static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid)
static int i40e_xsk_pool_disable(struct i40e_vsi *vsi, u16 qid)
{
struct net_device *netdev = vsi->netdev;
struct xdp_umem *umem;
struct xsk_buff_pool *pool;
bool if_running;
int err;

umem = xdp_get_umem_from_qid(netdev, qid);
if (!umem)
pool = xdp_get_xsk_pool_from_qid(netdev, qid);
if (!pool)
return -EINVAL;

if_running = netif_running(vsi->netdev) && i40e_enabled_xdp_vsi(vsi);
Expand All @@ -106,7 +110,7 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid)
}

clear_bit(qid, vsi->af_xdp_zc_qps);
xsk_buff_dma_unmap(umem, I40E_RX_DMA_ATTR);
xsk_buff_dma_unmap(pool->umem, I40E_RX_DMA_ATTR);

if (if_running) {
err = i40e_queue_pair_enable(vsi, qid);
Expand All @@ -118,20 +122,21 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid)
}

/**
* i40e_xsk_umem_setup - Enable/disassociate a UMEM to/from a ring/qid
* i40e_xsk_pool_setup - Enable/disassociate an AF_XDP buffer pool to/from
* a ring/qid
* @vsi: Current VSI
* @umem: UMEM to enable/associate to a ring, or NULL to disable
* @qid: Rx ring to (dis)associate UMEM (from)to
* @pool: Buffer pool to enable/associate to a ring, or NULL to disable
* @qid: Rx ring to (dis)associate buffer pool (from)to
*
* This function enables or disables a UMEM to a certain ring.
* This function enables or disables a buffer pool to a certain ring.
*
* Returns 0 on success, <0 on failure
**/
int i40e_xsk_umem_setup(struct i40e_vsi *vsi, struct xdp_umem *umem,
int i40e_xsk_pool_setup(struct i40e_vsi *vsi, struct xsk_buff_pool *pool,
u16 qid)
{
return umem ? i40e_xsk_umem_enable(vsi, umem, qid) :
i40e_xsk_umem_disable(vsi, qid);
return pool ? i40e_xsk_pool_enable(vsi, pool, qid) :
i40e_xsk_pool_disable(vsi, qid);
}

/**
Expand Down Expand Up @@ -191,7 +196,7 @@ bool i40e_alloc_rx_buffers_zc(struct i40e_ring *rx_ring, u16 count)
rx_desc = I40E_RX_DESC(rx_ring, ntu);
bi = i40e_rx_bi(rx_ring, ntu);
do {
xdp = xsk_buff_alloc(rx_ring->xsk_umem);
xdp = xsk_buff_alloc(rx_ring->xsk_pool->umem);
if (!xdp) {
ok = false;
goto no_buffers;
Expand Down Expand Up @@ -358,11 +363,11 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
i40e_finalize_xdp_rx(rx_ring, xdp_xmit);
i40e_update_rx_stats(rx_ring, total_rx_bytes, total_rx_packets);

if (xsk_umem_uses_need_wakeup(rx_ring->xsk_umem)) {
if (xsk_umem_uses_need_wakeup(rx_ring->xsk_pool->umem)) {
if (failure || rx_ring->next_to_clean == rx_ring->next_to_use)
xsk_set_rx_need_wakeup(rx_ring->xsk_umem);
xsk_set_rx_need_wakeup(rx_ring->xsk_pool->umem);
else
xsk_clear_rx_need_wakeup(rx_ring->xsk_umem);
xsk_clear_rx_need_wakeup(rx_ring->xsk_pool->umem);

return (int)total_rx_packets;
}
Expand All @@ -385,11 +390,12 @@ static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget)
dma_addr_t dma;

while (budget-- > 0) {
if (!xsk_umem_consume_tx(xdp_ring->xsk_umem, &desc))
if (!xsk_umem_consume_tx(xdp_ring->xsk_pool->umem, &desc))
break;

dma = xsk_buff_raw_get_dma(xdp_ring->xsk_umem, desc.addr);
xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_umem, dma,
dma = xsk_buff_raw_get_dma(xdp_ring->xsk_pool->umem,
desc.addr);
xsk_buff_raw_dma_sync_for_device(xdp_ring->xsk_pool->umem, dma,
desc.len);

tx_bi = &xdp_ring->tx_bi[xdp_ring->next_to_use];
Expand All @@ -416,7 +422,7 @@ static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget)
I40E_TXD_QW1_CMD_SHIFT);
i40e_xdp_ring_update_tail(xdp_ring);

xsk_umem_consume_tx_done(xdp_ring->xsk_umem);
xsk_umem_consume_tx_done(xdp_ring->xsk_pool->umem);
i40e_update_tx_stats(xdp_ring, sent_frames, total_bytes);
}

Expand Down Expand Up @@ -448,7 +454,7 @@ static void i40e_clean_xdp_tx_buffer(struct i40e_ring *tx_ring,
**/
bool i40e_clean_xdp_tx_irq(struct i40e_vsi *vsi, struct i40e_ring *tx_ring)
{
struct xdp_umem *umem = tx_ring->xsk_umem;
struct xsk_buff_pool *bp = tx_ring->xsk_pool;
u32 i, completed_frames, xsk_frames = 0;
u32 head_idx = i40e_get_head(tx_ring);
struct i40e_tx_buffer *tx_bi;
Expand Down Expand Up @@ -488,13 +494,13 @@ bool i40e_clean_xdp_tx_irq(struct i40e_vsi *vsi, struct i40e_ring *tx_ring)
tx_ring->next_to_clean -= tx_ring->count;

if (xsk_frames)
xsk_umem_complete_tx(umem, xsk_frames);
xsk_umem_complete_tx(bp->umem, xsk_frames);

i40e_arm_wb(tx_ring, vsi, completed_frames);

out_xmit:
if (xsk_umem_uses_need_wakeup(tx_ring->xsk_umem))
xsk_set_tx_need_wakeup(tx_ring->xsk_umem);
if (xsk_umem_uses_need_wakeup(tx_ring->xsk_pool->umem))
xsk_set_tx_need_wakeup(tx_ring->xsk_pool->umem);

return i40e_xmit_zc(tx_ring, I40E_DESC_UNUSED(tx_ring));
}
Expand Down Expand Up @@ -526,7 +532,7 @@ int i40e_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
if (queue_id >= vsi->num_queue_pairs)
return -ENXIO;

if (!vsi->xdp_rings[queue_id]->xsk_umem)
if (!vsi->xdp_rings[queue_id]->xsk_pool)
return -ENXIO;

ring = vsi->xdp_rings[queue_id];
Expand Down Expand Up @@ -565,7 +571,7 @@ void i40e_xsk_clean_rx_ring(struct i40e_ring *rx_ring)
void i40e_xsk_clean_tx_ring(struct i40e_ring *tx_ring)
{
u16 ntc = tx_ring->next_to_clean, ntu = tx_ring->next_to_use;
struct xdp_umem *umem = tx_ring->xsk_umem;
struct xsk_buff_pool *bp = tx_ring->xsk_pool;
struct i40e_tx_buffer *tx_bi;
u32 xsk_frames = 0;

Expand All @@ -585,22 +591,23 @@ void i40e_xsk_clean_tx_ring(struct i40e_ring *tx_ring)
}

if (xsk_frames)
xsk_umem_complete_tx(umem, xsk_frames);
xsk_umem_complete_tx(bp->umem, xsk_frames);
}

/**
* i40e_xsk_any_rx_ring_enabled - Checks if Rx rings have AF_XDP UMEM attached
* i40e_xsk_any_rx_ring_enabled - Checks if Rx rings have an AF_XDP
* buffer pool attached
* @vsi: vsi
*
* Returns true if any of the Rx rings has an AF_XDP UMEM attached
* Returns true if any of the Rx rings has an AF_XDP buffer pool attached
**/
bool i40e_xsk_any_rx_ring_enabled(struct i40e_vsi *vsi)
{
struct net_device *netdev = vsi->netdev;
int i;

for (i = 0; i < vsi->num_queue_pairs; i++) {
if (xdp_get_umem_from_qid(netdev, i))
if (xdp_get_xsk_pool_from_qid(netdev, i))
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/intel/i40e/i40e_xsk.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
#define _I40E_XSK_H_

struct i40e_vsi;
struct xdp_umem;
struct xsk_buff_pool;
struct zero_copy_allocator;

int i40e_queue_pair_disable(struct i40e_vsi *vsi, int queue_pair);
int i40e_queue_pair_enable(struct i40e_vsi *vsi, int queue_pair);
int i40e_xsk_umem_setup(struct i40e_vsi *vsi, struct xdp_umem *umem,
int i40e_xsk_pool_setup(struct i40e_vsi *vsi, struct xsk_buff_pool *pool,
u16 qid);
bool i40e_alloc_rx_buffers_zc(struct i40e_ring *rx_ring, u16 cleaned_count);
int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget);
Expand Down
Loading

0 comments on commit 1742b3d

Please sign in to comment.