mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Merge branch 'net-mvpp2-fix-xdp-rx-buffer-handling'
Til Kaiser says: ==================== net: mvpp2: fix XDP RX buffer handling This is v5 of the earlier XDP_PASS fix. The XDP_PASS change is retained, and the series also fixes related RX/XDP buffer handling issues found during review. Tested with tools/testing/selftests/drivers/net/xdp.py on mvpp2 hardware. ==================== Link: https://patch.msgid.link/20260607134943.21996-1-mail@tk154.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
b59873c9c4
|
|
@ -3917,10 +3917,10 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
struct mvpp2_bm_pool *bm_pool;
|
||||
struct page_pool *pp = NULL;
|
||||
struct sk_buff *skb;
|
||||
unsigned int frag_size;
|
||||
unsigned int frag_size, rx_sync_size;
|
||||
dma_addr_t dma_addr;
|
||||
phys_addr_t phys_addr;
|
||||
int pool, rx_bytes, err, ret;
|
||||
int pool, rx_bytes, rx_offset, err, ret;
|
||||
struct page *page;
|
||||
void *data;
|
||||
|
||||
|
|
@ -3933,6 +3933,8 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
rx_status = mvpp2_rxdesc_status_get(port, rx_desc);
|
||||
rx_bytes = mvpp2_rxdesc_size_get(port, rx_desc);
|
||||
rx_bytes -= MVPP2_MH_SIZE;
|
||||
rx_sync_size = rx_bytes + MVPP2_MH_SIZE;
|
||||
rx_offset = MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM;
|
||||
dma_addr = mvpp2_rxdesc_dma_addr_get(port, rx_desc);
|
||||
|
||||
pool = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >>
|
||||
|
|
@ -3946,9 +3948,10 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
dma_dir = DMA_FROM_DEVICE;
|
||||
}
|
||||
|
||||
dma_sync_single_for_cpu(dev->dev.parent, dma_addr,
|
||||
rx_bytes + MVPP2_MH_SIZE,
|
||||
dma_dir);
|
||||
dma_sync_single_range_for_cpu(dev->dev.parent, dma_addr,
|
||||
MVPP2_SKB_HEADROOM,
|
||||
rx_sync_size,
|
||||
dma_dir);
|
||||
|
||||
/* Buffer header not supported */
|
||||
if (rx_status & MVPP2_RXD_BUF_HDR)
|
||||
|
|
@ -3970,6 +3973,12 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
else
|
||||
frag_size = bm_pool->frag_size;
|
||||
|
||||
err = mvpp2_rx_refill(port, bm_pool, pp, pool);
|
||||
if (err) {
|
||||
netdev_err(port->dev, "failed to refill BM pools\n");
|
||||
goto err_drop_frame;
|
||||
}
|
||||
|
||||
if (xdp_prog) {
|
||||
struct xdp_rxq_info *xdp_rxq;
|
||||
|
||||
|
|
@ -3978,7 +3987,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
else
|
||||
xdp_rxq = &rxq->xdp_rxq_long;
|
||||
|
||||
xdp_init_buff(&xdp, PAGE_SIZE, xdp_rxq);
|
||||
xdp_init_buff(&xdp, bm_pool->frag_size, xdp_rxq);
|
||||
xdp_prepare_buff(&xdp, data,
|
||||
MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM,
|
||||
rx_bytes, true);
|
||||
|
|
@ -3987,17 +3996,19 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
|
||||
if (ret) {
|
||||
xdp_ret |= ret;
|
||||
err = mvpp2_rx_refill(port, bm_pool, pp, pool);
|
||||
if (err) {
|
||||
netdev_err(port->dev, "failed to refill BM pools\n");
|
||||
goto err_drop_frame;
|
||||
}
|
||||
|
||||
ps.rx_packets++;
|
||||
ps.rx_bytes += rx_bytes;
|
||||
continue;
|
||||
}
|
||||
|
||||
rx_sync_size = max_t(unsigned int, rx_sync_size,
|
||||
xdp.data_end - xdp.data_hard_start -
|
||||
MVPP2_SKB_HEADROOM);
|
||||
|
||||
/* Update offset and length to reflect any XDP adjustments. */
|
||||
rx_offset = xdp.data - data;
|
||||
rx_bytes = xdp.data_end - xdp.data;
|
||||
|
||||
metasize = xdp.data - xdp.data_meta;
|
||||
}
|
||||
|
||||
|
|
@ -4007,8 +4018,20 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
skb = slab_build_skb(data);
|
||||
if (!skb) {
|
||||
netdev_warn(port->dev, "skb build failed\n");
|
||||
goto err_drop_frame;
|
||||
if (pp) {
|
||||
page_pool_put_page(pp, virt_to_head_page(data),
|
||||
rx_sync_size, true);
|
||||
} else {
|
||||
dma_unmap_single_attrs(dev->dev.parent, dma_addr,
|
||||
bm_pool->buf_size,
|
||||
DMA_FROM_DEVICE,
|
||||
DMA_ATTR_SKIP_CPU_SYNC);
|
||||
mvpp2_frag_free(bm_pool, pp, data);
|
||||
}
|
||||
goto err_drop_frame_retired;
|
||||
}
|
||||
if (pp)
|
||||
skb_mark_for_recycle(skb);
|
||||
|
||||
/* If we have RX hardware timestamping enabled, grab the
|
||||
* timestamp from the queue and convert.
|
||||
|
|
@ -4019,16 +4042,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
skb_hwtstamps(skb));
|
||||
}
|
||||
|
||||
err = mvpp2_rx_refill(port, bm_pool, pp, pool);
|
||||
if (err) {
|
||||
netdev_err(port->dev, "failed to refill BM pools\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
goto err_drop_frame;
|
||||
}
|
||||
|
||||
if (pp)
|
||||
skb_mark_for_recycle(skb);
|
||||
else
|
||||
if (!pp)
|
||||
dma_unmap_single_attrs(dev->dev.parent, dma_addr,
|
||||
bm_pool->buf_size, DMA_FROM_DEVICE,
|
||||
DMA_ATTR_SKIP_CPU_SYNC);
|
||||
|
|
@ -4036,7 +4050,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
ps.rx_packets++;
|
||||
ps.rx_bytes += rx_bytes;
|
||||
|
||||
skb_reserve(skb, MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM);
|
||||
skb_reserve(skb, rx_offset);
|
||||
skb_put(skb, rx_bytes);
|
||||
if (metasize)
|
||||
skb_metadata_set(skb, metasize);
|
||||
|
|
@ -4047,13 +4061,14 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
|
|||
continue;
|
||||
|
||||
err_drop_frame:
|
||||
dev->stats.rx_errors++;
|
||||
mvpp2_rx_error(port, rx_desc);
|
||||
/* Return the buffer to the pool */
|
||||
if (rx_status & MVPP2_RXD_BUF_HDR)
|
||||
mvpp2_buff_hdr_pool_put(port, rx_desc, pool, rx_status);
|
||||
else
|
||||
mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
|
||||
err_drop_frame_retired:
|
||||
dev->stats.rx_errors++;
|
||||
mvpp2_rx_error(port, rx_desc);
|
||||
}
|
||||
|
||||
if (xdp_ret & MVPP2_XDP_REDIR)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user