[PATCH net] net: lan966x: don't disable hardirqs in fdma tx clear path
From: Daniel Machon
Date: Mon Oct 26 2026 - 09:55:22 EST
lan966x_fdma_tx_clear_buf() runs from the NAPI poll and frees the
buffers of completed tx DCBs with napi_consume_skb(),
page_pool_recycle_direct() and xdp_return_frame_bulk(), under
lan966x->tx_lock.
Before this patch, the lock is taken with spin_lock_irqsave(), so the
buffers are freed with hardirqs disabled. RX skbs are marked for
page_pool recycling, so when such an skb is forwarded back out and its
tx completion frees it here, the free path reaches __page_pool_put_page(),
which warns via lockdep_assert_no_hardirq().
Take tx_lock with a plain spin_lock(), as the other tx_lock users,
lan966x_port_xmit() and lan966x_fdma_xmit_xdpf(), already do.
tx_clear_buf() runs from the NAPI poll, so disabling hardirqs there is
not needed.
Found with lockdep enabled (CONFIG_PROVE_LOCKING), which the assert
depends on. Reproduced on a lan9668 board by redirecting received frames
out of another port with tc mirred.
Fixes: 11871aba1974 ("net: lan96x: Use page_pool API")
Signed-off-by: Daniel Machon <daniel.machon@xxxxxxxxxxxxx>
---
drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
index a7940eca5df31..a92bd0590b460 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
@@ -336,14 +336,13 @@ static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight)
struct lan966x_tx_dcb_buf *dcb_buf;
struct fdma *fdma = &tx->fdma;
struct xdp_frame_bulk bq;
- unsigned long flags;
bool clear = false;
struct fdma_db *db;
int i;
xdp_frame_bulk_init(&bq);
- spin_lock_irqsave(&lan966x->tx_lock, flags);
+ spin_lock(&lan966x->tx_lock);
for (i = 0; i < fdma->n_dcbs; ++i) {
dcb_buf = &tx->dcbs_buf[i];
@@ -388,7 +387,7 @@ static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight)
if (clear)
lan966x_fdma_wakeup_netdev(lan966x);
- spin_unlock_irqrestore(&lan966x->tx_lock, flags);
+ spin_unlock(&lan966x->tx_lock);
}
static int lan966x_fdma_rx_check_frame(struct lan966x_rx *rx, u64 *src_port)
---
base-commit: 6430fb7f1cc4e329e386521b7b208df443de92f2
change-id: 20261023-lan966x-fdma-tx-clear-hardirq-43724a086d0d
Best regards,
--
Daniel Machon <daniel.machon@xxxxxxxxxxxxx>