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

From: Giuseppe Nespolino

Date: Wed Nov 04 2026 - 11:52:03 EST


Answers are inline

Il giorno dom 30 ago 2026 alle ore 21:24 Yao Zi <me@xxxxxxxx> ha scritto:
>
> Hi Giuseppe,
>
> Sorry for the late reply.
>

No worries.

[ CUT ]

> Sorry for not making me clear. I mean the state of OOB_WOL_CTRL right
> before motorcomm_resume() sets it would help, which would prove whether
> it's the case that some firmware or internal hardware logic
> automatically arms OOL WOL after suspend.

Sorry for the long silence, I struggled a bit to recollect data.

I built dwmac-motorcomm with a dev_info() dumping the wrapper registers
at four points: entry of the suspend callback, entry of
motorcomm_resume(), right after stmmac_pci_plat_resume() (i.e. just
before motorcomm_deassert_mdio_phy_reset() and motorcomm_init()), and
after motorcomm_init(). Ubuntu 7.0.0-42, real s2idle, four cycles in the
same boot: three came back fine, the fourth (31 minutes) broke RX.

OOB_WOL_CTRL MGMT_INT_CTRL0 INT_MODERATION EPHY_CTRL
suspend entry 0x00000001 0x00000000 0x00c800c8 0x00000075
resume entry 0x00000000 0x003f0000 0x00000000 0x00000001
before init 0x00000000 0x003f0000 0x00000000 0x00000001
after init 0x00000001 0x00000000 0x00c800c8 0x00000001

PMCSR already reads D0 at resume entry; SYS_RESET reads 0x80000001 at
all four points.

So yes, OOB WOL is armed when motorcomm_resume() runs, but on every
resume, not only the failing one: the whole wrapper comes back with what
look like its post-reset defaults (0x003f0000 is exactly what I read
right after a SYS_RESET in August). An earlier pm_test=devices cycle left
these registers intact, so the state loss only happens in a real s2idle.

The failing cycle is byte-identical to the three good ones at all four
points, including after init: the DIS write lands and the masks are
cleared, yet interrupts stay dead (MGMT_INT_CTRL0 then latches 0x11,
mmc_rx_framecount_gb grows while rx-0/tx-0 don't). So these registers
don't tell a good resume from a bad one.
That matches another result I owe you: on 1 Oct I put a naturally broken
controller through a second 60s s2idle before recovering it, and that
resume did not fix it, whereas the same resume does recover a controller
where I armed OOB WOL by hand on a healthy link. So the natural failure
doesn't look like "OOB WOL left armed"; something the resume path
doesn't touch stays wedged, and only SYS_RESET clears it.

I think that still argues for the patch: the device comes out of s2idle
in a reset-like state nobody commanded, and resume never performs the
explicit reset + init sequence that probe does. I'll send it as you
suggested, with the usleep_range() folded into motorcomm_reset(). With a
single natural failure captured so far I can't claim more than that it
recovers the stuck state; I'll keep the instrumented module loaded and
report back.

As before, the analysis was done with an AI assistant; all numbers come
from this machine.

Thanks,
Giuseppe