Netdev List
 help / color / mirror / Atom feed
* [PATCH net v2 0/4] net: mvpp2: fix XDP RX buffer handling
@ 2026-06-02 16:46 Til Kaiser
  2026-06-02 16:46 ` [PATCH net v2 1/4] net: mvpp2: sync RX data at the hardware packet offset Til Kaiser
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Til Kaiser @ 2026-06-02 16:46 UTC (permalink / raw)
  To: Marcin Wojtas, Russell King
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Matteo Croce, Sven Auhagen, Lorenzo Bianconi, netdev, bpf,
	linux-kernel, Til Kaiser

This is v2 of the earlier XDP_PASS fix. The XDP_PASS change is retained,
and the series now also fixes related RX/XDP buffer handling issues found
during review.

---
v1: https://lore.kernel.org/all/20260524122334.1730451-1-mail@tk154.de/

Changes in v2:
- Fixed RX DMA sync range to account for RX headroom.
- Limited XDP frame size to the actual RX buffer size.
- Fixed refill error paths so retired buffers are not returned to BM.

Til Kaiser (4):
  net: mvpp2: sync RX data at the hardware packet offset
  net: mvpp2: limit XDP frame size to the RX buffer
  net: mvpp2: do not return retired RX buffers to BM
  net: mvpp2: build skb from XDP-adjusted data on XDP_PASS

 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 38 ++++++++++++-------
 1 file changed, 25 insertions(+), 13 deletions(-)

-- 
2.54.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH net v2 1/4] net: mvpp2: sync RX data at the hardware packet offset
  2026-06-02 16:46 [PATCH net v2 0/4] net: mvpp2: fix XDP RX buffer handling Til Kaiser
@ 2026-06-02 16:46 ` Til Kaiser
  2026-06-02 16:46 ` [PATCH net v2 2/4] net: mvpp2: limit XDP frame size to the RX buffer Til Kaiser
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Til Kaiser @ 2026-06-02 16:46 UTC (permalink / raw)
  To: Marcin Wojtas, Russell King
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Matteo Croce, Sven Auhagen, Lorenzo Bianconi, netdev, bpf,
	linux-kernel, Til Kaiser

mvpp2 programs the RX queue packet offset, so hardware writes received
data at dma_addr + MVPP2_SKB_HEADROOM. The current CPU sync starts at
dma_addr and only covers rx_bytes + MVPP2_MH_SIZE bytes, which syncs the
unused headroom and misses the same number of bytes at the packet tail.

On non-coherent DMA systems this can leave the CPU reading stale cache
contents for the end of the received frame.

Use dma_sync_single_range_for_cpu() with MVPP2_SKB_HEADROOM as the range
offset so the sync covers the Marvell header and packet data actually
written by hardware.

Fixes: e1921168bbd4 ("mvpp2: sync only the received frame")
Signed-off-by: Til Kaiser <mail@tk154.de>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index f442b874bb59..92a701f4fe3f 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -3946,9 +3946,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_bytes + MVPP2_MH_SIZE,
+					      dma_dir);
 
 		/* Buffer header not supported */
 		if (rx_status & MVPP2_RXD_BUF_HDR)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net v2 2/4] net: mvpp2: limit XDP frame size to the RX buffer
  2026-06-02 16:46 [PATCH net v2 0/4] net: mvpp2: fix XDP RX buffer handling Til Kaiser
  2026-06-02 16:46 ` [PATCH net v2 1/4] net: mvpp2: sync RX data at the hardware packet offset Til Kaiser
@ 2026-06-02 16:46 ` Til Kaiser
  2026-06-02 16:46 ` [PATCH net v2 3/4] net: mvpp2: do not return retired RX buffers to BM Til Kaiser
  2026-06-02 16:46 ` [PATCH net v2 4/4] net: mvpp2: build skb from XDP-adjusted data on XDP_PASS Til Kaiser
  3 siblings, 0 replies; 5+ messages in thread
From: Til Kaiser @ 2026-06-02 16:46 UTC (permalink / raw)
  To: Marcin Wojtas, Russell King
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Matteo Croce, Sven Auhagen, Lorenzo Bianconi, netdev, bpf,
	linux-kernel, Til Kaiser

mvpp2 has short and long BM pools, and short pool buffers can be smaller
than PAGE_SIZE. The XDP path nevertheless initializes every xdp_buff with
PAGE_SIZE as frame size.

XDP helpers use frame_sz to validate tail growth and to derive the hard
end of the data area. Advertising PAGE_SIZE for short buffers can let
bpf_xdp_adjust_tail() grow a packet past the real allocation, corrupting
memory or later tripping skb tailroom checks.

Initialize the XDP buffer with bm_pool->frag_size so XDP tailroom matches
the actual buffer backing the packet.

Fixes: 07dd0a7aae7f ("mvpp2: add basic XDP support")
Signed-off-by: Til Kaiser <mail@tk154.de>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 92a701f4fe3f..3372ed27cc8d 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -3979,7 +3979,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);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net v2 3/4] net: mvpp2: do not return retired RX buffers to BM
  2026-06-02 16:46 [PATCH net v2 0/4] net: mvpp2: fix XDP RX buffer handling Til Kaiser
  2026-06-02 16:46 ` [PATCH net v2 1/4] net: mvpp2: sync RX data at the hardware packet offset Til Kaiser
  2026-06-02 16:46 ` [PATCH net v2 2/4] net: mvpp2: limit XDP frame size to the RX buffer Til Kaiser
@ 2026-06-02 16:46 ` Til Kaiser
  2026-06-02 16:46 ` [PATCH net v2 4/4] net: mvpp2: build skb from XDP-adjusted data on XDP_PASS Til Kaiser
  3 siblings, 0 replies; 5+ messages in thread
From: Til Kaiser @ 2026-06-02 16:46 UTC (permalink / raw)
  To: Marcin Wojtas, Russell King
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Matteo Croce, Sven Auhagen, Lorenzo Bianconi, netdev, bpf,
	linux-kernel, Til Kaiser

The RX refill failure path jumps to err_drop_frame, which returns the
descriptor buffer to the hardware BM pool. That is only valid while the
driver still owns the buffer.

After a non-PASS XDP verdict, mvpp2_run_xdp() may already have recycled,
redirected, or queued the page for XDP_TX. After build_skb(), freeing the
skb on refill failure also retires the data buffer. Returning either of
those buffers to BM lets hardware DMA into memory that is no longer owned
by the RX ring.

Split the error handling so buffers are returned to BM only while still
owned by the driver. Once XDP or an skb owns the buffer, only account the
RX error. Mark page-pool skbs for recycle before they can be freed on the
refill failure path, and unmap non-page-pool buffers before freeing them.

Fixes: 07dd0a7aae7f ("mvpp2: add basic XDP support")
Fixes: d6526926de73 ("net: mvpp2: fix memory leak in mvpp2_rx")
Signed-off-by: Til Kaiser <mail@tk154.de>
---
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 20 ++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 3372ed27cc8d..397aa5ca4992 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -3991,7 +3991,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 				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;
+					goto err_drop_frame_retired;
 				}
 
 				ps.rx_packets++;
@@ -4010,6 +4010,8 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 			netdev_warn(port->dev, "skb build failed\n");
 			goto err_drop_frame;
 		}
+		if (pp)
+			skb_mark_for_recycle(skb);
 
 		/* If we have RX hardware timestamping enabled, grab the
 		 * timestamp from the queue and convert.
@@ -4023,13 +4025,16 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 		err = mvpp2_rx_refill(port, bm_pool, pp, pool);
 		if (err) {
 			netdev_err(port->dev, "failed to refill BM pools\n");
+			if (!pp)
+				dma_unmap_single_attrs(dev->dev.parent, dma_addr,
+						       bm_pool->buf_size,
+						       DMA_FROM_DEVICE,
+						       DMA_ATTR_SKIP_CPU_SYNC);
 			dev_kfree_skb_any(skb);
-			goto err_drop_frame;
+			goto err_drop_frame_retired;
 		}
 
-		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);
@@ -4048,13 +4053,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)
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net v2 4/4] net: mvpp2: build skb from XDP-adjusted data on XDP_PASS
  2026-06-02 16:46 [PATCH net v2 0/4] net: mvpp2: fix XDP RX buffer handling Til Kaiser
                   ` (2 preceding siblings ...)
  2026-06-02 16:46 ` [PATCH net v2 3/4] net: mvpp2: do not return retired RX buffers to BM Til Kaiser
@ 2026-06-02 16:46 ` Til Kaiser
  3 siblings, 0 replies; 5+ messages in thread
From: Til Kaiser @ 2026-06-02 16:46 UTC (permalink / raw)
  To: Marcin Wojtas, Russell King
  Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Matteo Croce, Sven Auhagen, Lorenzo Bianconi, netdev, bpf,
	linux-kernel, Til Kaiser

When an XDP program uses bpf_xdp_adjust_head() or bpf_xdp_adjust_tail()
and then returns XDP_PASS, mvpp2 still builds the skb from fixed offsets
derived from the original RX descriptor. Packet geometry changes made by
the XDP program are therefore discarded before the skb reaches the stack.

Update rx_offset and rx_bytes from xdp.data and xdp.data_end for
XDP_PASS. This makes skb_reserve() and skb_put() reflect the packet seen
by XDP, and makes RX byte accounting for XDP_PASS follow the length of the
skb passed to the network stack.

Non-PASS verdicts continue to account the descriptor length because no skb
is passed up in those cases.

Fixes: 07dd0a7aae7f ("mvpp2: add basic XDP support")
Signed-off-by: Til Kaiser <mail@tk154.de>
---
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 397aa5ca4992..844f433975ed 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -3920,7 +3920,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 		unsigned int frag_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,7 @@ 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_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) >>
@@ -3999,6 +4000,10 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
 				continue;
 			}
 
+			/* 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;
 		}
 
@@ -4042,7 +4047,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);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-06-02 16:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-02 16:46 [PATCH net v2 0/4] net: mvpp2: fix XDP RX buffer handling Til Kaiser
2026-06-02 16:46 ` [PATCH net v2 1/4] net: mvpp2: sync RX data at the hardware packet offset Til Kaiser
2026-06-02 16:46 ` [PATCH net v2 2/4] net: mvpp2: limit XDP frame size to the RX buffer Til Kaiser
2026-06-02 16:46 ` [PATCH net v2 3/4] net: mvpp2: do not return retired RX buffers to BM Til Kaiser
2026-06-02 16:46 ` [PATCH net v2 4/4] net: mvpp2: build skb from XDP-adjusted data on XDP_PASS Til Kaiser

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox