* [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®