From: Sagi Maimon <maimon.sagi@gmail.com>
To: netdev@vger.kernel.org
Cc: radhey.shyam.pandey@amd.com, michal.simek@amd.com,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, daniel@iogearbox.net,
jacob.e.keller@intel.com, joe@dama.to, suraj.gupta2@amd.com,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Sagi Maimon <maimon.sagi@gmail.com>
Subject: [PATCH net v2] net: axienet: free outstanding TX buffers in axienet_dma_bd_release()
Date: Wed, 30 Sep 2026 16:38:51 +0300 [thread overview]
Message-ID: <20260930133851.663023-1-maimon.sagi@gmail.com> (raw)
axienet_dma_bd_release() walks the RX ring to unmap and free every
receive buffer before releasing it, but frees the TX descriptor ring
with dma_free_coherent() alone. Any descriptor that
axienet_free_tx_chain() had not yet reclaimed still holds its skb and
its streaming DMA mapping, and both are lost.
axienet_stop() disables TX NAPI and stops the DMA engine before calling
it, so nothing reclaims those descriptors afterwards. Bringing the
interface down while frames are in flight therefore leaks up to
lp->tx_bd_num skbs and mappings each time.
Walk the TX ring the way axienet_dma_err_handler() already does: unmap
every descriptor whose cntrl is still set - axienet_free_tx_chain()
clears it on reclaim - and free any skb still attached, as a drop since
it was never transmitted. This relies on axienet_stop() having stopped
the DMA engine first, as the RX walk in the same function already does.
tx_bd_v is NULL when axienet_dma_bd_init() did not get as far as
allocating it: axienet_open() does not check the result of the reset
that runs it. dma_free_coherent() accepts that, so skip the walk then
too, and drop the comment claiming the ring is always allocated. On
the axienet_dma_bd_init() error path the TX ring has just been
allocated zeroed, so the walk does nothing.
This was reported by the Sashiko AI review bot.
Tested on an AXI Ethernet MAC behind a PCIe endpoint: traffic passes,
and after each of ten down/up cycles and five module reloads, all made
with traffic running and each running axienet_dma_bd_release(), traffic
resumes and nothing is logged. The leak itself was not measured.
Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Assisted-by: LLM sparse
Signed-off-by: Sagi Maimon <maimon.sagi@gmail.com>
---
Notes:
Changes in v2:
- Skip the TX walk when tx_bd_v is NULL, which axienet_open() allows
when the reset fails; v1 would have dereferenced it where the old
dma_free_coherent() did not (Sashiko). Drop the comment that claimed
the ring is always allocated.
- Free the skbs with dev_kfree_skb_any(), so they count as drops as in
axienet_dma_err_handler(), rather than as consumed (Sashiko).
- Say that the walk relies on axienet_stop() stopping the DMA engine
first, rather than stating it as a guarantee (Sashiko).
- Kept Jacob's Reviewed-by, as the changes are small; please say if
that is not OK.
- The hardware test is v1's. The changes do not touch the path it
exercised other than how the freed skbs are accounted.
- v1: https://lore.kernel.org/netdev/20260927081034.350422-1-maimon.sagi@gmail.com/
.../net/ethernet/xilinx/xilinx_axienet_main.c | 23 ++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 1722b7038f34..8bf27e20e103 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -186,7 +186,28 @@ static void axienet_dma_bd_release(struct net_device *ndev)
int i;
struct axienet_local *lp = netdev_priv(ndev);
- /* If we end up here, tx_bd_v must have been DMA allocated. */
+ /* tx_bd_v is NULL if axienet_dma_bd_init() did not get as far as
+ * allocating it; dma_free_coherent() below accepts that.
+ */
+ for (i = 0; lp->tx_bd_v && i < lp->tx_bd_num; i++) {
+ struct axidma_bd *cur_p = &lp->tx_bd_v[i];
+
+ /* axienet_free_tx_chain() clears cntrl when it reclaims a
+ * descriptor, so a non-zero value means the mapping is live.
+ */
+ if (cur_p->cntrl) {
+ dma_addr_t addr = desc_get_phys_addr(lp, cur_p);
+
+ dma_unmap_single(lp->dev, addr,
+ (cur_p->cntrl &
+ XAXIDMA_BD_CTRL_LENGTH_MASK),
+ DMA_TO_DEVICE);
+ }
+ /* never transmitted, so account it as a drop */
+ if (cur_p->skb)
+ dev_kfree_skb_any(cur_p->skb);
+ }
+
dma_free_coherent(lp->dev,
sizeof(*lp->tx_bd_v) * lp->tx_bd_num,
lp->tx_bd_v,
base-commit: a7bfaba4823e3c165bb2004c74eff7c096672bc7
--
2.47.0
reply other threads:[~2026-09-30 13:39 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260930133851.663023-1-maimon.sagi@gmail.com \
--to=maimon.sagi@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jacob.e.keller@intel.com \
--cc=joe@dama.to \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michal.simek@amd.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=radhey.shyam.pandey@amd.com \
--cc=suraj.gupta2@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®