From 0000000000000000000000000000000000000002 Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Fri, 24 Apr 2026 00:00:00 +0000 Subject: [PATCH 2/3] net: macb: re-check ISR after IER re-enable in macb_tx_poll macb_tx_poll() runs with TCOMP masked, drains the TX ring, then calls napi_complete_done() and re-enables TCOMP via IER. An existing comment in the function notes: /* Packet completions only seem to propagate to raise * interrupts when interrupts are enabled at the time, so if * packets were sent while interrupts were disabled, * they will not cause another interrupt to be generated when * interrupts are re-enabled. */ and mitigates this by calling macb_tx_complete_pending() to look for a completed descriptor whose TX_USED bit the hardware has DMA'd but whose completion we processed without ever seeing an interrupt for. macb_tx_complete_pending() only inspects driver-visible ring state (descriptor->ctrl, after rmb()). On PCIe-attached parts (BCM2712 + RP1 on Raspberry Pi 5 in particular) the descriptor DMA write that sets TX_USED can still be in flight in the PCIe fabric when we check. The read-memory-barrier synchronises the CPU view of earlier CPU writes, but does not force the peripheral's in-flight DMA to retire. In that window the check returns false, napi exits, the IER re-enable does not re-fire (the quirk above), and the queue stalls silently. Re-check the hardware's own ISR state as well. Reading a MAC register after IER re-enable serves two purposes: (1) It drains any in-flight PCIe DMA writes of descriptor state, so a subsequent macb_tx_complete_pending() sees an accurate view of TX_USED. (2) It directly observes whether the hardware currently has a pending TCOMP signal, catching the case the existing driver comment describes (completions raised while masked, not re-fired). If either path indicates pending work, schedule NAPI again. Combined with the PCIe posted-write flush in patch 1/3, this closes the observed silent-TX-stall path on BCM2712/RP1 reported at the links below. Link: https://github.com/cilium/cilium/issues/43198 Link: https://bugs.launchpad.net/ubuntu/+source/linux-raspi/+bug/2133877 Signed-off-by: Lukasz Raczylo --- drivers/net/ethernet/cadence/macb_main.c | 25 +++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -2000,17 +2000,25 @@ if (work_done < budget && napi_complete_done(napi, work_done)) { queue_writel(queue, IER, MACB_BIT(TCOMP)); - /* Packet completions only seem to propagate to raise - * interrupts when interrupts are enabled at the time, so if - * packets were sent while interrupts were disabled, - * they will not cause another interrupt to be generated when - * interrupts are re-enabled. - * Check for this case here to avoid losing a wakeup. This can - * potentially race with the interrupt handler doing the same - * actions if an interrupt is raised just after enabling them, - * but this should be harmless. + /* + * TCOMP events that fire while the interrupt is masked do + * not re-fire when IER is re-enabled. Catch this two ways + * to avoid losing a wakeup: + * + * (1) Read ISR -- catches completions the hardware flagged + * but that we did not see as an interrupt. The MMIO + * read doubles as a PCIe read barrier, flushing any + * in-flight descriptor TX_USED DMA writes into memory. + * (2) macb_tx_complete_pending() inspects the ring after + * that flush, catching a descriptor whose TX_USED is + * now visible as a result of the barrier. + * + * This can race with the interrupt handler taking the same + * path if an interrupt fires just after the IER write; + * rescheduling NAPI in that case is harmless. */ - if (macb_tx_complete_pending(queue)) { + if ((queue_readl(queue, ISR) & MACB_BIT(TCOMP)) || + macb_tx_complete_pending(queue)) { queue_writel(queue, IDR, MACB_BIT(TCOMP)); if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) queue_writel(queue, ISR, MACB_BIT(TCOMP)); -- 2.44.0