Re: dwmac-motorcomm: RX dies after long s2idle, only wrapper SYS_RESET recovers

From: Giuseppe Nespolino

Date: Thu Aug 13 2026 - 05:15:01 EST


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