[PATCH net-next v4 1/3] net: ethernet: mtk_eth_soc: reset RX DMA
From: Sandeep Haemoon
Date: Mon Nov 09 2026 - 21:55:54 EST
mtk_poll_rx() keeps a single dma_addr_t across the whole loop and only
refreshes it when a replacement buffer was mapped for the descriptor
being processed. The paths that jump straight to release_desc (no
netdev for the source port, MTK_RESETTING set, or a refill allocation
failure) then hand the descriptor back with the high address bits of the
buffer mapped for the previous descriptor, while the low bits in rxd1
still belong to the buffer the descriptor actually holds.
With MTK_36BIT_DMA and DRAM above 4 GiB the hardware then DMAs the next
frame to an address that is neither buffer, and the driver passes the
stale contents of the untouched buffer up the stack.
Reset dma_addr to DMA_MAPPING_ERROR at the start of every iteration, so
a descriptor that is released without a new mapping keeps its own high
address bits.
Fixes: 2d75891ebc09 ("net: ethernet: mtk_eth_soc: support 36-bit DMA addressing on MT7988")
Signed-off-by: Sandeep Haemoon <sandeeph@xxxxxxxxxxx>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ad0fdc413..a46cf5441 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2210,7 +2210,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
u8 *data, *new_data;
struct mtk_rx_dma_v2 *rxd, trxd;
int done = 0, bytes = 0;
- dma_addr_t dma_addr = DMA_MAPPING_ERROR;
+ dma_addr_t dma_addr;
int ppe_idx = 0;
while (done < budget) {
@@ -2219,6 +2219,12 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
u32 hash, reason;
int mac = 0;
+ /* The release paths below hand the descriptor back with the
+ * buffer it still holds, so only overwrite its address when
+ * a new buffer was actually mapped for it.
+ */
+ dma_addr = DMA_MAPPING_ERROR;
+
ring = mtk_get_rx_ring(eth);
if (unlikely(!ring))
goto rx_done;
--
2.53.0