* dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers @ 2026-08-12 14:50 Giuseppe Nespolino 2026-08-12 15:02 ` Giuseppe Nespolino 0 siblings, 1 reply; 5+ messages in thread From: Giuseppe Nespolino @ 2026-08-12 14:50 UTC (permalink / raw) To: Yao Zi; +Cc: netdev, linux-kernel Hi Yao, On a Slimbook EVO15-A8 (YT6801, 1f0a:6801, kernel 7.0.0-28 Ubuntu) enp2s0 stops receiving after a long s2idle. 18-25 minutes reproduces it; 5s and 30s cycles never did. Link comes up at 1Gbps and the resume path logs nothing unusual. Measured while broken: - MAC is receiving: mmc_rx_framecount_gb climbing, mmc_rx_fifo_overflow 2585. netdev rx_packets and the rx-0 MSI-X count frozen. - MSIX_PBA (BAR0+0x1300) = 0, so the device isn't asserting anything. - CH0_STATUS = 0x4c5: RI/RBU/TI/TBU latched, NIS and AIS clear, with NIE/AIE set in CH0_INTR_ENA (0xd041). - All 512 RX descriptors in writeback format with sane lengths (64-1518), OWN=0. The DMA received them; nothing ever consumed them. Event bits latch and clear fine (W1C works, MGMT_INT_CTRL0 tracks it as a mirror), but the summary stage never asserts and no MSI-X is generated. RBU, the full ring and the FIFO overflow are all downstream of that. Ruled out with data: ASPM/remapping (PBA=0, MSI-X table intact, zero IOMMU faults), wrapper registers lost across D3 (all identical to a healthy baseline), unarmed ring, and MGMT_INT_CTRL0 needing an ack (status field is read-only). What recovers it: toggling SYS_RESET (0x152c bit31) plus motorcomm_init(), then ip link down/up. down/up alone does not - rings get rebuilt, IRQs re-requested, packets land in memory, still zero interrupts. I haven't yet isolated the reset from motorcomm_init(). Which brings me to the question, since you know the chip: does clearing OOB_WOL_CTRL_DIS actually disarm an OOB WOL engine that already armed, or does that need the SYS_RESET? Your comment says OOB WOL blocks DMA interrupt delivery, which is exactly the symptom, and stmmac_pci_plat_suspend() enables PCI wake unconditionally even with WoL off - it is off here. I have a candidate fix (do the full motorcomm_reset() in motorcomm_resume() instead of only deasserting the MDIO/PHY reset) and I'm happy to send it, but if OOB WOL is the mechanism the right patch is probably narrower. Caveat: I validated reset + full open, not reset + the stmmac_resume path, so a patched module still needs testing. Happy to run any experiment on this hardware. Giuseppe ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers 2026-08-12 14:50 dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers Giuseppe Nespolino @ 2026-08-12 15:02 ` Giuseppe Nespolino 2026-08-12 21:14 ` Yao Zi 0 siblings, 1 reply; 5+ messages in thread From: Giuseppe Nespolino @ 2026-08-12 15:02 UTC (permalink / raw) To: Yao Zi; +Cc: netdev, linux-kernel Answering my own question, since it turned out to be testable without a suspend at all. On a healthy interface, writing 0 to OOB_WOL_CTRL (BAR0+0x1010) - clearing the DIS bit, i.e. enabling OOB WOL - kills RX within a second: OOB=1 (healthy) ping 0% loss, rx-0 irq +39, rx_packets +49 OOB=0 ping 100% loss, rx-0 irq +0, rx_packets +0 OOB=1 again ping 100% loss, rx-0 irq +0, rx_packets +0 SYS_RESET + init + ip link down/up ping 0% loss, rx-0 irq +35, rx_packets +41 So the DIS bit is one-way: writing it back reads 1 but does not disarm an engine that already armed. Only the SYS_RESET recovers. That's a one-writel reproducer of the symptom, no suspend needed. It also explains why nothing driver-side helps after resume: motorcomm_init() writes OOB_WOL_CTRL_DIS, the register reads 1, and it's a no-op because the engine is already armed. Only the probe's motorcomm_reset() tears it down. Possible trigger: stmmac_pci_plat_suspend() calls pci_wake_from_d3(pdev, true) unconditionally, even when WoL is off. Caveat, because the two states are not identical: with OOB WOL enabled by hand, CH0_STATUS reads 0x0 - fully quiesced, no events latched. In the natural post-resume failure it was 0x4c5 with RI/RBU latched and packets still landing in memory (RX descriptor OWN count dropping 512 -> 467). So this proves OOB WOL blocks interrupt delivery and that the DIS bit is irreversible, but not yet that OOB WOL is what arms across s2idle. I'll check whether the engine is armed on the next natural occurrence. Given this, the fix is probably narrower than what I suggested: either don't enable PCI wake when WoL is off, or disarm OOB WOL properly on resume - and if a reset is the only way to disarm it, that at least gives the reset a documented reason. Tell me which direction you prefer and I'll send a patch. Giuseppe Il giorno mer 12 ago 2026 alle ore 16:50 Giuseppe Nespolino <g.nespolino@gmail.com> ha scritto: > > Hi Yao, > > On a Slimbook EVO15-A8 (YT6801, 1f0a:6801, kernel 7.0.0-28 Ubuntu) > enp2s0 stops receiving after a long s2idle. 18-25 minutes reproduces > it; 5s and 30s cycles never did. > Link comes up at 1Gbps and the resume path logs nothing unusual. > > Measured while broken: > > - MAC is receiving: mmc_rx_framecount_gb climbing, > mmc_rx_fifo_overflow 2585. netdev rx_packets and the rx-0 MSI-X count > frozen. > - MSIX_PBA (BAR0+0x1300) = 0, so the device isn't asserting anything. > - CH0_STATUS = 0x4c5: RI/RBU/TI/TBU latched, NIS and AIS clear, with > NIE/AIE set in CH0_INTR_ENA (0xd041). > - All 512 RX descriptors in writeback format with sane lengths > (64-1518), OWN=0. The DMA received them; nothing ever consumed them. > > Event bits latch and clear fine (W1C works, MGMT_INT_CTRL0 tracks it > as a mirror), but the summary stage never asserts and no MSI-X is > generated. RBU, the full ring and the FIFO overflow are all downstream > of that. > > Ruled out with data: ASPM/remapping (PBA=0, MSI-X table intact, zero > IOMMU faults), wrapper registers lost across D3 (all identical to a > healthy baseline), unarmed ring, and MGMT_INT_CTRL0 needing an ack > (status field is read-only). > > What recovers it: toggling SYS_RESET (0x152c bit31) plus > motorcomm_init(), then ip link down/up. down/up alone does not - rings > get rebuilt, IRQs re-requested, packets land in memory, still zero > interrupts. I haven't yet isolated the reset from motorcomm_init(). > > Which brings me to the question, since you know the chip: does > clearing OOB_WOL_CTRL_DIS actually disarm an OOB WOL engine that > already armed, or does that need the SYS_RESET? Your comment says OOB > WOL blocks DMA interrupt > delivery, which is exactly the symptom, and stmmac_pci_plat_suspend() > enables PCI wake unconditionally even with WoL off - it is off here. > > I have a candidate fix (do the full motorcomm_reset() in > motorcomm_resume() instead of only deasserting the MDIO/PHY reset) and > I'm happy to send it, but if OOB WOL is the mechanism the right patch > is probably narrower. Caveat: I validated reset + full open, not reset > + the stmmac_resume path, so a patched module still needs testing. > > Happy to run any experiment on this hardware. > > Giuseppe ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers 2026-08-12 15:02 ` Giuseppe Nespolino @ 2026-08-12 21:14 ` Yao Zi 2026-08-13 9:12 ` Giuseppe Nespolino 0 siblings, 1 reply; 5+ messages in thread From: Yao Zi @ 2026-08-12 21:14 UTC (permalink / raw) To: Giuseppe Nespolino, Yao Zi; +Cc: netdev, linux-kernel On Wed, Aug 12, 2026 at 05:02:49PM +0200, Giuseppe Nespolino wrote: > Answering my own question, since it turned out to be testable without a > suspend at all. > > On a healthy interface, writing 0 to OOB_WOL_CTRL (BAR0+0x1010) - clearing > the DIS bit, i.e. enabling OOB WOL - kills RX within a second: > > OOB=1 (healthy) ping 0% loss, rx-0 irq +39, > rx_packets +49 > OOB=0 ping 100% loss, rx-0 irq +0, > rx_packets +0 > OOB=1 again ping 100% loss, rx-0 irq +0, > rx_packets +0 > SYS_RESET + init + ip link down/up ping 0% loss, rx-0 irq +35, > rx_packets +41 > > So the DIS bit is one-way: writing it back reads 1 but does not disarm an > engine that already armed. Only the SYS_RESET recovers. That's a one-writel > reproducer of the symptom, no suspend needed. This is quite unexpected. I found enabling OOB_WOL_CTRL blocks DMA interrupts because it's the default state after resetting, without clearing it, the MAC is non-operational. > It also explains why nothing driver-side helps after resume: > motorcomm_init() writes OOB_WOL_CTRL_DIS, the register reads 1, and it's a > no-op because the engine is already armed. Only the probe's > motorcomm_reset() tears it down. This makes sense. > Possible trigger: stmmac_pci_plat_suspend() calls > pci_wake_from_d3(pdev, true) unconditionally, even when WoL is off. Have you tested the idea? We always call pci_wake_from_d3(pdev, true) but from your description, broken RX only happens after s2idle is active for some time, right? > Caveat, because the two states are not identical: with OOB WOL enabled by > hand, CH0_STATUS reads 0x0 - fully quiesced, no events latched. In the > natural post-resume failure it was 0x4c5 with RI/RBU latched and packets > still landing in memory (RX descriptor OWN count dropping 512 -> 467). So > this proves OOB WOL blocks interrupt delivery and that the DIS bit is > irreversible, but not yet that OOB WOL is what arms across s2idle. I'll > check whether the engine is armed on the next natural occurrence. From my own testing, with OOB WOL enabled, both DMA TX and RX interrupts aren't delivered. So TX behavior when RX is broken might indicate what has happened. > Given this, the fix is probably narrower than what I suggested: either > don't enable PCI wake when WoL is off, or disarm OOB WOL properly on > resume - and if a reset is the only way to disarm it, that at least gives > the reset a documented reason. Tell me which direction you prefer and > I'll send a patch. I prefer the later, even disabling PCI wake works, we'll probably re-visit this when adding WoL support. Sadly I took a brief look across vendor's driver, and think there's no other way to disarm the OOB WOL. Performing a SYS_RESET might be okay since the stmmac core restores necessary hardware states. Anyway, please try figuring out state of the DIS bit when the problem occurs before sending the patch, which would be a strong reason to perform a reset in the resume hook. Best regards, Yao Zi > Giuseppe > > Il giorno mer 12 ago 2026 alle ore 16:50 Giuseppe Nespolino > <g.nespolino@gmail.com> ha scritto: > > > > Hi Yao, > > > > On a Slimbook EVO15-A8 (YT6801, 1f0a:6801, kernel 7.0.0-28 Ubuntu) > > enp2s0 stops receiving after a long s2idle. 18-25 minutes reproduces > > it; 5s and 30s cycles never did. > > Link comes up at 1Gbps and the resume path logs nothing unusual. > > > > Measured while broken: > > > > - MAC is receiving: mmc_rx_framecount_gb climbing, > > mmc_rx_fifo_overflow 2585. netdev rx_packets and the rx-0 MSI-X count > > frozen. > > - MSIX_PBA (BAR0+0x1300) = 0, so the device isn't asserting anything. > > - CH0_STATUS = 0x4c5: RI/RBU/TI/TBU latched, NIS and AIS clear, with > > NIE/AIE set in CH0_INTR_ENA (0xd041). > > - All 512 RX descriptors in writeback format with sane lengths > > (64-1518), OWN=0. The DMA received them; nothing ever consumed them. > > > > Event bits latch and clear fine (W1C works, MGMT_INT_CTRL0 tracks it > > as a mirror), but the summary stage never asserts and no MSI-X is > > generated. RBU, the full ring and the FIFO overflow are all downstream > > of that. > > > > Ruled out with data: ASPM/remapping (PBA=0, MSI-X table intact, zero > > IOMMU faults), wrapper registers lost across D3 (all identical to a > > healthy baseline), unarmed ring, and MGMT_INT_CTRL0 needing an ack > > (status field is read-only). > > > > What recovers it: toggling SYS_RESET (0x152c bit31) plus > > motorcomm_init(), then ip link down/up. down/up alone does not - rings > > get rebuilt, IRQs re-requested, packets land in memory, still zero > > interrupts. I haven't yet isolated the reset from motorcomm_init(). > > > > Which brings me to the question, since you know the chip: does > > clearing OOB_WOL_CTRL_DIS actually disarm an OOB WOL engine that > > already armed, or does that need the SYS_RESET? Your comment says OOB > > WOL blocks DMA interrupt > > delivery, which is exactly the symptom, and stmmac_pci_plat_suspend() > > enables PCI wake unconditionally even with WoL off - it is off here. > > > > I have a candidate fix (do the full motorcomm_reset() in > > motorcomm_resume() instead of only deasserting the MDIO/PHY reset) and > > I'm happy to send it, but if OOB WOL is the mechanism the right patch > > is probably narrower. Caveat: I validated reset + full open, not reset > > + the stmmac_resume path, so a patched module still needs testing. > > > > Happy to run any experiment on this hardware. > > > > Giuseppe ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers 2026-08-12 21:14 ` Yao Zi @ 2026-08-13 9:12 ` Giuseppe Nespolino 2026-08-13 14:34 ` Giuseppe Nespolino 0 siblings, 1 reply; 5+ messages in thread From: Giuseppe Nespolino @ 2026-08-13 9:12 UTC (permalink / raw) To: Yao Zi; +Cc: netdev, linux-kernel On Wed, Aug 12, 2026 at 09:14:56PM +0000, Yao Zi wrote: > This is quite unexpected. I found enabling OOB_WOL_CTRL blocks DMA > interrupts because it's the default state after resetting, without > clearing it, the MAC is non-operational. That fits what I see, and it explains the asymmetry: the write only takes effect in the window right after a reset. On an already-armed engine, writing the DIS bit back does nothing, which is exactly what I measured. > Have you tested the idea? We always call pci_wake_from_d3(pdev, true) but > from your description, broken RX only happens after s2idle is active for > some time, right? Right, and it's a fair objection; the wake is armed on every suspend, so it can't be what distinguishes a 30s cycle from an 18min one. I built and loaded that change here but haven't been through a long suspend with it yet, so I have no result either way yet. > From my own testing, with OOB WOL enabled, both DMA TX and RX interrupts > aren't delivered. So TX behavior when RX is broken might indicate what > has happened. I can't answer that from what I captured: between my two snapshots no frames were transmitted (mmc_tx_framecount_gb stayed at 98), so the frozen tx-0 vector count proves nothing. Worth noting that TX packets do leave the interface while RX is broken, but that is expected even with TX interrupts dead, since stmmac cleans the ring from the coalescing hrtimer. I've instrumented for it. Next occurrence I'll force TX traffic and report the tx-0 vector delta. > Anyway, please try figuring out state of the DIS bit when the problem > occurs before sending the patch, which would be a strong reason to > perform a reset in the resume hook. Already captured, from the last natural occurrence (s2idle 14:43 -> 15:01, 18 minutes, on AC): OOB_WOL_CTRL (BAR0+0x1010) while broken: 0x00000001 OOB_WOL_CTRL healthy baseline: 0x00000001 Identical, and motorcomm_init() had already run at resume and written that same value. So there is no software-visible state left to correct: the register claims DIS is set while interrupts are not being delivered, and nothing short of the reset recovers it. I'll send the reset-in-resume patch. One design question bef you want motorcomm_reset() followed by the eFuse settle delay and motorcomm_init(), i.e. the probe sequence minus the MAC addr would you rather keep resume lighter than that? One disclosure, per Documentation/process/generated-content.rst: this investigation was done with an AI coding assistant. It drove the register-level diagnosis and the experiment design; the measurements are all from this machine and I ran and verified them myself. Thanks, Giuseppe ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers 2026-08-13 9:12 ` Giuseppe Nespolino @ 2026-08-13 14:34 ` Giuseppe Nespolino 0 siblings, 0 replies; 5+ messages in thread From: Giuseppe Nespolino @ 2026-08-13 14:34 UTC (permalink / raw) To: Yao Zi; +Cc: netdev, linux-kernel DISCLAIMER: most of what I write in this message comes from AI-driven analysis, even though I manually tested the steps. Follow-up, with the TX measurement I owed you, and a correction to something I implied earlier. TX first. The bug reproduced again today; I forced 20 raw Ethernet frames out (AF_PACKET, EtherType 0x88b5, so no configuration change and no dependency on a working RX): mmc_tx_framecount_gb +20 frames really went out netdev tx_packets +20 tx-0 vector +0 rx-0 vector +0 TX interrupts aren't delivered either, matching what you saw with OOB WOL enabled. Register signature identical to the previous occurrence: OOB_WOL_CTRL 0x1, MGMT_INT_CTRL0 0x11, MSI-X vector 0 unmasked, and all 512 RX descriptors written back with plausible lengths and OWN clear. Now the correction: the failure is intermittent, and I had been assuming it was deterministic for long suspends. With the pci_wake_from_d3() change loaded I went through three long s2idle cycles and only the third broke: 13h52m lease 6s after resume fine 27min lease 7s after resume fine 31min no lease broken The longest one was fine, so duration isn't a monotonic predictor either. With n=3 I can't distinguish a partial effect of that change from plain stochastic behaviour, so I'm claiming nothing for it - dropping it as a fix, and happy to send it separately as a cleanup if you want it. On the isolation I'd left open: motorcomm_init() on its own does not recover the controller, not even followed by a full ip link down/up (tx-0 +0, rx-0 +0 throughout). The SYS_RESET is the necessary part. But the reset alone isn't sufficient either, which answers the design question I asked you, so you needn't. Right after the SYS_RESET: MGMT_INT_CTRL0 0x003f0000 mask field 0x3f, every source masked INT_MODERATION 0x00000000 reset + OOB_WOL_CTRL alone left interrupts dead; adding the MGMT_INT_CTRL0 = 0 unmask and INT_MODERATION recovered it immediately (tx-0 +16, rx-0 +220, DHCP completed). So the reset has to be followed by the motorcomm_init() that resume already calls - it can neither replace it nor be trimmed. What I can't separate is whether the OOB WOL clear or the unmask is the load-bearing half, since the reset does both. That makes the patch motorcomm_reset() plus the eFuse settle delay, inserted before the existing motorcomm_init() call in motorcomm_resume(). Given the intermittency, waiting for natural occurrences is a poor way to validate it. Instead I'll inject the fault deterministically: arm OOB WOL by hand with the one writel, then suspend and resume, and check whether the patched resume hook brings it back. On the current driver it stays dead, so that gives a clean result per cycle instead of a coin flip. I'll keep counting natural cycles in the background too. Giuseppe ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-13 14:34 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-08-12 14:50 dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers Giuseppe Nespolino 2026-08-12 15:02 ` Giuseppe Nespolino 2026-08-12 21:14 ` Yao Zi 2026-08-13 9:12 ` Giuseppe Nespolino 2026-08-13 14:34 ` Giuseppe Nespolino
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®