* [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC
@ 2026-09-30 19:28 Igor Velkov via B4 Relay
2026-10-01 12:40 ` Andrew Lunn
2026-10-04 20:13 ` netdev-bot+sashiko
0 siblings, 2 replies; 6+ messages in thread
From: Igor Velkov via B4 Relay @ 2026-09-30 19:28 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Russell King, Maxime Coquelin, Alexandre Torgue, netdev,
linux-stm32, linux-arm-kernel, linux-kernel, Igor Velkov
From: Igor Velkov <iav@iav.lv>
stmmac_resume() resets the MAC in stmmac_hw_setup(). On dwmac1000 the
reset clears the interrupt mask, and all core interrupts stay unmasked
until dwmac1000_core_init() writes it again. A link change in that
window raises an RGMII interrupt, and no handler clears it since
commit 2e2c878a3141 ("net: stmmac: remove SGMII/RGMII/SMII interrupt handling").
The line storms:
dwmac_dma_interrupt: unexpected status 04000000
The message repeats every few milliseconds and the network stays down
until a power cycle or a watchdog reset. A register dump at the first
message on ODROID-HC4 showed the pending link change with a zero mask:
core int_status 00000001 int_mask 00000000 pmt 00000000 rgsmiiis 0000000d
Disable the interrupt line for the whole resume and enable it again on
every exit path. The line is IRQF_SHARED, so leave it enabled during
suspend, where another user of the line may wake the system.
Wake-on-LAN resume on two boards:
- ODROID-HC4 (dwmac-meson8b, 7.2): the storm on resume, none in 5
resumes with this patch.
- Helios64 (dwmac-rk, 7.3-rc5): the storm in 2 of 3 resumes, none in
26 resumes with this patch.
Assisted-by: LLM
Signed-off-by: Igor Velkov <iav@iav.lv>
---
Ported to net-next, where stmmac_resume() gained error labels. Tested
on hardware with 7.2 and 7.3-rc5; build-tested on net-next.
---
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 24 ++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3ad9252bf6ae..6e0415538327 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -8356,16 +8356,26 @@ int stmmac_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
+ bool irq_off;
int ret;
+ /* Resume resets the MAC, leaving every core interrupt unmasked until
+ * the mask is written again: a link change in that window would storm.
+ */
+ irq_off = netif_running(ndev);
+ if (irq_off)
+ disable_irq(ndev->irq);
+
if (priv->plat->resume) {
ret = priv->plat->resume(dev, priv->plat->bsp_priv);
if (ret)
- return ret;
+ goto out;
}
- if (!netif_running(ndev))
- return 0;
+ if (!netif_running(ndev)) {
+ ret = 0;
+ goto out;
+ }
/* Power Down bit, into the PM register, is cleared
* automatically as soon as a magic packet or a Wake-up frame
@@ -8388,7 +8398,7 @@ int stmmac_resume(struct device *dev)
if (!(priv->plat->flags & STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP)) {
ret = stmmac_legacy_serdes_power_up(priv);
if (ret < 0)
- return ret;
+ goto out;
}
rtnl_lock();
@@ -8442,7 +8452,8 @@ int stmmac_resume(struct device *dev)
netif_device_attach(ndev);
- return 0;
+ ret = 0;
+ goto out;
error_stop_dma:
stmmac_stop_all_dma(priv);
@@ -8451,6 +8462,9 @@ int stmmac_resume(struct device *dev)
stmmac_legacy_serdes_power_down(priv);
mutex_unlock(&priv->lock);
rtnl_unlock();
+out:
+ if (irq_off)
+ enable_irq(ndev->irq);
return ret;
}
---
base-commit: 47a1446725732cd3996edf607e8739334bbf4d78
change-id: 20260930-stmmac-irq-shut-03bac57ae0bb
Best regards,
--
Igor Velkov <iav@iav.lv>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC
2026-09-30 19:28 [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC Igor Velkov via B4 Relay
@ 2026-10-01 12:40 ` Andrew Lunn
2026-10-02 4:36 ` Igor Velkov
2026-10-04 20:13 ` netdev-bot+sashiko
1 sibling, 1 reply; 6+ messages in thread
From: Andrew Lunn @ 2026-10-01 12:40 UTC (permalink / raw)
To: iav
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, Maxime Coquelin,
Alexandre Torgue, netdev, linux-stm32, linux-arm-kernel,
linux-kernel
> stmmac_resume() resets the MAC in stmmac_hw_setup(). On dwmac1000 the
> reset clears the interrupt mask
For my understanding, it is the hardware reset which clears the mask,
not software?
If it is hardware, that is an odd hardware design.
Andrew
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC
2026-10-01 12:40 ` Andrew Lunn
@ 2026-10-02 4:36 ` Igor Velkov
2026-10-04 14:42 ` Andrew Lunn
0 siblings, 1 reply; 6+ messages in thread
From: Igor Velkov @ 2026-10-02 4:36 UTC (permalink / raw)
To: Andrew Lunn
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, netdev, linux-kernel
On Thu, Oct 01, 2026 at 02:40:46PM +0200, Andrew Lunn wrote:
> For my understanding, it is the hardware reset which clears the mask,
> not software?
>
> If it is hardware, that is an odd hardware design.
Yes, the hardware: dwmac_dma_reset() sets SWR in DMA_BUS_MODE and the
MAC returns its registers to their reset values. On dwmac1000
GMAC_INT_MASK is a mask register, so its reset value 0 unmasks
everything; dwmac4 has an enable register (GMAC_INT_EN) instead.
A correction to the v1 text: no link change is needed. RGSMIIIS was
already pending before the reset (Helios64, SWR written from a test
script on the running board: int_status 0x1 under int_mask 0x1; after
it int_mask 0, DMA status 0x04000000). Nothing on the RGMII path reads
0xd8, which would clear it, so it stays pending from the first link
change on.
dwmac1000_core_init() rewrites the mask shortly after, from the same
resume thread. When that thread runs on the CPU that takes the MAC
interrupt, the storm starves it: with both on one CPU the storm hit
the first resume on Helios64, ROCK Pi 4A and ODROID-HC4; on different
CPUs it printed at most 3 messages per resume in 30 resumes.
v2 for net, with the description fixed and a Fixes tag:
https://lore.kernel.org/r/20261002043558.1302590-1-iav@iav.lv
--
Igor Velkov
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC
2026-10-02 4:36 ` Igor Velkov
@ 2026-10-04 14:42 ` Andrew Lunn
2026-10-04 18:28 ` Igor Velkov
0 siblings, 1 reply; 6+ messages in thread
From: Andrew Lunn @ 2026-10-04 14:42 UTC (permalink / raw)
To: Igor Velkov
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, netdev, linux-kernel
On Fri, Oct 02, 2026 at 07:36:23AM +0300, Igor Velkov wrote:
> On Thu, Oct 01, 2026 at 02:40:46PM +0200, Andrew Lunn wrote:
> > For my understanding, it is the hardware reset which clears the mask,
> > not software?
> >
> > If it is hardware, that is an odd hardware design.
>
> Yes, the hardware: dwmac_dma_reset() sets SWR in DMA_BUS_MODE and the
> MAC returns its registers to their reset values. On dwmac1000
> GMAC_INT_MASK is a mask register, so its reset value 0 unmasks
> everything; dwmac4 has an enable register (GMAC_INT_EN) instead.
So the hardware design dictates that you must be ready to receive
interrupts when you reset the device, or at least, have them blocked
at a higher level in the interrupt tree.
Is probe written this way? Does the needed code already exists, its
just not used on resume when it should be?
Andrew
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC
2026-10-04 14:42 ` Andrew Lunn
@ 2026-10-04 18:28 ` Igor Velkov
0 siblings, 0 replies; 6+ messages in thread
From: Igor Velkov @ 2026-10-04 18:28 UTC (permalink / raw)
To: Andrew Lunn
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Russell King, netdev, linux-kernel
On Sun, Oct 04, 2026 at 04:42:23PM +0200, Andrew Lunn wrote:
> Is probe written this way? Does the needed code already exists, its
> just not used on resume when it should be?
Open is, by ordering: __stmmac_open() calls stmmac_hw_setup(), which
does the reset, and only then stmmac_request_irq(). stmmac_release()
frees the line again. MTU change, the ethtool ring and channel changes
and the reset subtask all go through release and open, so they get the
same ordering.
Resume is the only other caller of stmmac_hw_setup(), and the only one
that resets with the handler installed: nothing in suspend frees or
disables the line. The PM core disables it for the noirq phase only;
dpm_resume_noirq() enables it again before stmmac_resume() runs.
So there is no helper to reuse, only that ordering. The patch gives
resume the same with disable_irq()/enable_irq() instead of
free_irq()/request_irq().
--
Igor Velkov
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC
2026-09-30 19:28 [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC Igor Velkov via B4 Relay
2026-10-01 12:40 ` Andrew Lunn
@ 2026-10-04 20:13 ` netdev-bot+sashiko
1 sibling, 0 replies; 6+ messages in thread
From: netdev-bot+sashiko @ 2026-10-04 20:13 UTC (permalink / raw)
To: iav
Cc: maxime.chevallier, andrew+netdev, davem, edumazet, kuba, pabeni,
linux, mcoquelin.stm32, alexandre.torgue, netdev, linux-stm32,
linux-arm-kernel, linux-kernel
Thank you for your contribution! Sashiko AI review found 4 potential
issue(s) to consider.
Critical: 0 · High: 0 · Medium: 2 · Low: 2
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [Medium] The defect is specific to dwmac1000, but stmmac_resume() now
calls disable_irq(ndev->irq) on every core for the whole resume.
- [Medium] stmmac_resume() now re-enables ndev->irq on every exit path,
including error exits where GMAC_INT_MASK was never restored.
- [Low] The commit message names commit 2e2c878a3141 ("net: stmmac:
remove SGMII/RGMII/SMII interrupt handling") as the point after which…
- [Low] The new comment in the generic stmmac_resume() says 'Resume
resets the MAC, leaving every core interrupt unmasked until the mask…
--
net: stmmac: mask the MAC interrupt while resume resets the MAC
This patch disables ndev->irq for the whole of stmmac_resume() when the
interface is running, and enables it again on every exit path. The aim is
to stop an RGMII interrupt storm on dwmac1000. There, the MAC reset in
stmmac_hw_setup() clears GMAC_INT_MASK, and it stays clear until
dwmac1000_core_init() writes it again.
> stmmac_resume() resets the MAC in stmmac_hw_setup(). On dwmac1000 the
> reset clears the interrupt mask, and all core interrupts stay unmasked
> until dwmac1000_core_init() writes it again. A link change in that
> window raises an RGMII interrupt, and no handler clears it since
> commit 2e2c878a3141 ("net: stmmac: remove SGMII/RGMII/SMII interrupt handling").
> The line storms:
[ ... ]
> The message repeats every few milliseconds and the network stays down
> until a power cycle or a watchdog reset.
[Severity: Low]
Should this carry a Fixes: tag for the commit it names?
Fixes: 2e2c878a3141 ("net: stmmac: remove SGMII/RGMII/SMII interrupt handling")
That commit removed dwmac1000_rgsmii() and its call from
dwmac1000_irq_status(). That call read GMAC_RGSMIIIS to ack the interrupt:
- if (intr_status & PCS_RGSMIIIS_IRQ)
- dwmac1000_rgsmii(ioaddr, x);
It also moved GMAC_INT_DISABLE_RGMII into GMAC_INT_DEFAULT_MASK. Since
then, the mask written by dwmac1000_core_init() is the only protection.
The only trailers are Assisted-by and Signed-off-by, and the note after
them says the patch was ported to net-next. Both 7.2 and 7.3-rc5 were
tested as affected. Would net, with a Fixes: tag and possibly Cc: stable,
be the better target?
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 3ad9252bf6aea..6e0415538327b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -8356,16 +8356,26 @@ int stmmac_resume(struct device *dev)
> {
> struct net_device *ndev = dev_get_drvdata(dev);
> struct stmmac_priv *priv = netdev_priv(ndev);
> + bool irq_off;
> int ret;
>
> + /* Resume resets the MAC, leaving every core interrupt unmasked until
> + * the mask is written again: a link change in that window would storm.
> + */
[Severity: Low]
Does this comment hold for every core that uses stmmac_resume()?
Only dwmac1000 writes a mask register, where 0 means everything is
unmasked:
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c:dwmac1000_core_init() {
...
writel(GMAC_INT_DEFAULT_MASK, ioaddr + GMAC_INT_MASK);
...
}
dwmac4 and xgmac write enable registers instead. On those cores a reset
leaves the core interrupts disabled, not unmasked:
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c:dwmac4_core_init() {
...
writel(GMAC_INT_DEFAULT_ENABLE, ioaddr + GMAC_INT_EN);
...
}
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c:dwxgmac2_core_init() {
...
writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
...
}
Could the comment say that this is a workaround specific to dwmac1000?
> + irq_off = netif_running(ndev);
> + if (irq_off)
> + disable_irq(ndev->irq);
[Severity: Medium]
What happens to other devices on this line while resume runs? In single
IRQ mode the line is requested as shared:
stmmac_request_irq_single() {
...
ret = request_irq(dev->irq, stmmac_interrupt,
IRQF_SHARED, dev->name, dev);
...
}
disable_irq() masks the line for every handler on it. The line then stays
masked through all of these:
plat->resume()
stmmac_mdio_reset()
SerDes power-up
rtnl_lock()
mutex_lock(&priv->lock)
stmmac_hw_setup(), including the DMA soft reset poll of up to 200ms
in dwmac_dma_reset()
PTP init
phylink_resume()
No other device on the line gets interrupts during that time. Suppose one
of them waits for its own interrupt while holding RTNL, or another lock
that stmmac_resume() needs. Can that stall until a timeout, or forever if
the wait has no timeout? Lockdep would not see this dependency.
The commit message mentions IRQF_SHARED only as the reason to leave the
line enabled during suspend.
The problem is specific to dwmac1000. Could the fix avoid the shared line
altogether? Some options:
rewrite GMAC_INT_MASK right after the reset
restore the read-to-clear of GMAC_RGSMIIIS in dwmac1000
disable the line only between the reset and core_init
[ ... ]
> @@ -8451,6 +8462,9 @@ int stmmac_resume(struct device *dev)
> stmmac_legacy_serdes_power_down(priv);
> mutex_unlock(&priv->lock);
> rtnl_unlock();
> +out:
> + if (irq_off)
> + enable_irq(ndev->irq);
[Severity: Medium]
Can this enable the line again while GMAC_INT_MASK is still clear?
If stmmac_init_dma_engine() fails, stmmac_hw_setup() returns before
stmmac_core_init(). That is the only place where dwmac1000_core_init()
restores the mask:
stmmac_hw_setup() {
...
ret = stmmac_init_dma_engine(priv);
if (ret < 0) {
phylink_rx_clk_stop_unblock(priv->phylink);
...
return ret;
}
...
stmmac_core_init(priv, priv->hw, dev);
...
}
The failure can come from stmmac_prereset_configure(), or from
stmmac_reset() timing out ("Failed to reset the dma"). The timeout is a
known case when clk_rx_i from the PHY is not running yet.
dwmac_dma_reset() returns -ETIMEDOUT and leaves SFT_RESET set:
dwmac_dma_reset() {
...
return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
!(value & DMA_BUS_MODE_SFT_RESET),
10000, 200000);
}
So the hardware finishes the reset once the RX clock starts. That usually
happens when the PHY link comes up, which phylink_prepare_resume() has
already started. The reset clears the mask just as the RGMII link change
event arrives.
The error then takes this path:
stmmac_resume()
stmmac_hw_setup() fails
goto error_unlock
out:
enable_irq(ndev->irq)
stmmac_interrupt() never acks the RGMII source and always returns
IRQ_HANDLED:
stmmac_interrupt() {
...
stmmac_common_interrupt(priv);
stmmac_dma_interrupt(priv);
return IRQ_HANDLED;
}
Because of that, the spurious IRQ detector will not disable the line
either. Does the storm this patch fixes come back on these exits, with no
later core_init to close the window?
The commit message says the line is enabled again "on every exit path".
On these exits, though, it is enabled inside the window the patch is
meant to close.
>
> return ret;
> }
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260930-stmmac-irq-shut-v1-1-104d1a1dcb28%40iav.lv
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-04 20:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-30 19:28 [PATCH net-next] net: stmmac: mask the MAC interrupt while resume resets the MAC Igor Velkov via B4 Relay
2026-10-01 12:40 ` Andrew Lunn
2026-10-02 4:36 ` Igor Velkov
2026-10-04 14:42 ` Andrew Lunn
2026-10-04 18:28 ` Igor Velkov
2026-10-04 20:13 ` netdev-bot+sashiko
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®