Re: dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers
Giuseppe Nespolino <[email protected]>
| Newsgroups | gmane.linux.network,gmane.linux.kernel |
|---|---|
| Message-ID | <CAKx9m6Myf7St+czv3i82dK2fs2WyAcx+B6r_zT1tLPs97SH3tg@mail.gmail.com> |
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