[PATCH net v2] net: sparx5: fix tx DCB index drift in fdma xmit
flat view
WARM1d
From: Daniel Machon <daniel.machon@microchip.com>
Date: 2026-10-21 14:05:23
Also in:
linux-arm-kernel, lkml
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
sparx5_fdma_xmit() advances dcb_index before checking that the FDMA is
done with the DCB, and does not undo the advance when the check fails.
Before commit f4aa7e361ae2 ("net: sparx5: use FDMA library for adding
DCB's in the tx path") the next DCB was always the one after last_dcb.
Since then dcb_index drifts one DCB further away from last_dcb on every
failed transmit.
While the ring is full, this drops frames even though completed DCBs
sit behind dcb_index. After a run of failures, dcb_index can also land
on last_dcb itself. Re-adding last_dcb loses the frame, because the
FDMA has already passed the tail of the chain, and that DCB is never
completed again.
Fix this by making dcb_index the next DCB to use, and advancing it only
after the DCB has been added, as the rx path does. dcb_index and
last_dcb now only move together, so dcb_index always points at the DCB
after last_dcb.
The issue was found by an AI code review agent. It was reproduced on a
sparx5 PCB135 board with a modified kernel that forces 63 consecutive
transmit failures. Afterwards, about 1 in 64 frames is lost for good.
With the fix, the same test loses no frames.
Fixes: f4aa7e361ae2 ("net: sparx5: use FDMA library for adding DCB's in the tx path")
Signed-off-by: Daniel Machon <daniel.machon@microchip.com>
---
Changes in v2:
- Advance dcb_index only after the DCB has been added, instead of
rejecting last_dcb. This fixes the drift itself (AI review).
- Reword the subject and commit message to match.
- Link to v1: https://lore.kernel.org/r/20261020-sparx5-fdma-last-dcb-v1-1-fb9a956196dd@microchip.com (local)
---
drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
index dbe86f937b21..15ec9b053824 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c@@ -217,7 +217,6 @@ int sparx5_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb, struct fdma *fdma = &tx->fdma; void *virt_addr; - fdma_dcb_advance(fdma); if (!fdma_db_is_done(fdma_db_get(fdma, fdma->dcb_index, 0))) return -EINVAL;
@@ -235,6 +234,8 @@ int sparx5_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb, FDMA_DCB_STATUS_BLOCKO(0) | FDMA_DCB_STATUS_BLOCKL(skb->len + IFH_LEN * 4 + 4)); + fdma_dcb_advance(fdma); + sparx5_fdma_reload(sparx5, fdma); return NETDEV_TX_OK;
--- base-commit: 07bd391eb9572e74f073c49acef327611234f9bb change-id: 20261019-sparx5-fdma-last-dcb-e2e8491b7d86 Best regards, -- Daniel Machon [off-list ref]