Thread (2 messages) 2 messages, 1 author, 2d ago

[PATCH net v2] net: stmmac: mask the MAC interrupt while resume resets the MAC

WARM2d

From: Igor Velkov <hidden>
Date: 2026-10-02 04:36:27
Also in: lkml
Subsystem: networking drivers, stmmac ethernet driver, the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Chevallier, Linus Torvalds

stmmac_resume() resets the MAC in stmmac_hw_setup(). On dwmac1000 the
reset sets GMAC_INT_MASK to 0, which unmasks every core interrupt, until
dwmac1000_core_init() writes the mask again. Since commit 2e2c878a3141
("net: stmmac: remove SGMII/RGMII/SMII interrupt handling") nothing on
the RGMII path reads GMAC_RGSMIIIS (only the PCS code does), so RGSMIIIS
stays pending behind the mask from the first link change on, and the
reset lets it through. The line storms:

  dwmac_dma_interrupt: unexpected status 04000000

A register dump at the first message on ODROID-HC4 showed it:

  core int_status 00000001 int_mask 00000000 pmt 00000000 rgsmiiis 0000000d

The mask is written by the resume thread itself. When that thread runs
on the CPU that takes the MAC interrupt, the storm starves it and the
board hangs until a watchdog reset or a soft-lockup panic; on another
CPU the storm ends after a few interrupts.

Disable the interrupt line for the whole resume and enable it again on
every exit path. This matches open(), which resets the MAC before it
requests the interrupt; resume resets it with the line live. 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 with the resume thread on the CPU that takes the MAC
interrupt, 7.3-rc5: without this patch the storm hit the first resume
on Helios64 (dwmac-rk) twice, ROCK Pi 4A (dwmac-rk) once and ODROID-HC4
(dwmac-meson8b) twice; with it, no storm in 10 resumes on Helios64 and
10 on ODROID-HC4. With the thread on another CPU and no patch, the
storm printed at most 3 messages per resume in 30 resumes.

Fixes: 2e2c878a3141 ("net: stmmac: remove SGMII/RGMII/SMII interrupt handling")
Assisted-by: LLM
Signed-off-by: Igor Velkov <redacted>
---
v2:
- target net with a Fixes tag; v1 was posted for net-next
- describe the RGSMIIIS bit pending since link-up and the resume thread
  on the interrupt CPU instead of a link change in the reset window;
  the code comment is fixed the same way
- results on Helios64, ROCK Pi 4A and ODROID-HC4
v1: https://lore.kernel.org/r/20260930-stmmac-irq-shut-v1-1-104d1a1dcb28@iav.lv (local)

Build-tested on net: allmodconfig and allyesconfig with W=1, no new
warnings.

 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 27 ++++++++++++++-----
 1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ec62fa7418f4..b275b6234b55 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -8313,15 +8313,25 @@ int stmmac_resume(struct device *dev)
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct stmmac_priv *priv = netdev_priv(ndev);
 	int ret;
+	bool irq_off;
+
+	/* Resume resets the MAC, leaving every core interrupt unmasked until
+	 * the mask is written again: a status bit already pending 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
@@ -8344,7 +8354,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();
@@ -8367,7 +8377,7 @@ int stmmac_resume(struct device *dev)
 		stmmac_legacy_serdes_power_down(priv);
 		mutex_unlock(&priv->lock);
 		rtnl_unlock();
-		return ret;
+		goto out;
 	}
 
 	stmmac_init_timestamping(priv);
@@ -8393,7 +8403,12 @@ int stmmac_resume(struct device *dev)
 
 	netif_device_attach(ndev);
 
-	return 0;
+	ret = 0;
+out:
+	if (irq_off)
+		enable_irq(ndev->irq);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(stmmac_resume);
 
-- 
2.43.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help