Skip to content

Commit c20bbf3

Browse files
committed
net: macb: flush PCIe posted write after TSTART doorbell
macb_start_xmit() and macb_tx_restart() kick transmission by OR-ing MACB_BIT(TSTART) into NCR. On PCIe-attached macb instances (BCM2712 + RP1 PCIe south bridge on Raspberry Pi 5 is the setup we have in front of us), writes to NCR are posted PCIe writes: they are not guaranteed to reach the device before the issuing CPU returns. An existing source-level comment at the TSTART site acknowledges that such writes can be lost under some conditions: /* TSTART write might get dropped, so make the IRQ retrigger * a buffer read */ and arms a recovery handshake via queue->tx_pending / queue->txubr_pending that runs on the next TCOMP interrupt. That recovery path depends on a subsequent TCOMP actually firing. If the TSTART write never reaches the MAC, no TX begins, no TCOMP completion arrives, and the ring remains quiescent without any kernel-visible indication. Add a read-back of NCR after each TSTART write in macb_start_xmit() and macb_tx_restart(). The read is an architected PCIe read barrier for earlier posted writes on the same path; it ensures the doorbell has reached the MAC before the functions return. The existing tx_pending / txubr_pending handshake is left in place unchanged -- it remains the correct recovery for any other reason the MAC could silently fail to start TX. We do not have direct hardware evidence that TSTART is being lost on the RP1 path. This patch is one of a three-patch series ("candidate fixes for silent TX stall on BCM2712/RP1"); see the cover letter for context. We have verified it compiles and applies cleanly; runtime verification is pending. Link: cilium/cilium#43198 Link: https://bugs.launchpad.net/ubuntu/+source/linux-raspi/+bug/2133877 Signed-off-by: Lukasz Raczylo <lukasz@raczylo.com>
1 parent 216bde1 commit c20bbf3

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

drivers/net/ethernet/cadence/macb_main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,13 @@ static void macb_tx_restart(struct macb_queue *queue)
19491949

19501950
spin_lock(&bp->lock);
19511951
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
1952+
/*
1953+
* Flush the PCIe posted-write queue so the TSTART doorbell
1954+
* reliably reaches the MAC. Without this, the write can sit
1955+
* in the fabric and the MAC never advances, causing a silent
1956+
* TX stall.
1957+
*/
1958+
(void)macb_readl(bp, NCR);
19521959
spin_unlock(&bp->lock);
19531960

19541961
out_tx_ptr_unlock:
@@ -2630,6 +2637,11 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
26302637
queue->tx_pending = 1;
26312638

26322639
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
2640+
/*
2641+
* Flush the PCIe posted-write queue; see the comment in
2642+
* macb_tx_restart() for the reasoning.
2643+
*/
2644+
(void)macb_readl(bp, NCR);
26332645
spin_unlock(&bp->lock);
26342646

26352647
if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)

0 commit comments

Comments
 (0)