* [PATCH net v2] net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend
@ 2026-07-20 11:15 Luis Lang
2026-07-20 13:59 ` Andrew Lunn
2026-07-20 14:40 ` Maxime Chevallier
0 siblings, 2 replies; 3+ messages in thread
From: Luis Lang @ 2026-07-20 11:15 UTC (permalink / raw)
To: netdev
Cc: Luis Lang, Andrew Lunn, Maxime Chevallier, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Maxime Coquelin, Alexandre Torgue, Russell King (Oracle),
Oleksij Rempel, Ovidiu Panait, Rohan G Thomas,
moderated list:ARM/STM32 ARCHITECTURE,
moderated list:ARM/STM32 ARCHITECTURE, open list
Since commit 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU
interrupts"), suspending causes an interrupt storm from the RPS
interrupt.
Fix this by adding a deinit_chan() op to stmmac_dma_ops, which
masks all default dma channel interrupts. This is called from
stmmac_stop_all_dma(), so interrupts don't trigger while suspending.
Fixes: 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts")
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Suggested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: Luis Lang <luis.la@mail.de>
---
.../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 24 +++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 ++++
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++++
3 files changed, 32 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 829a23bdad01..23ffe1adcd0d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -106,6 +106,17 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
}
+static void dwmac4_dma_deinit_channel(struct stmmac_priv *priv,
+ void __iomem *ioaddr, u32 chan)
+{
+ const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
+ u32 value;
+
+ value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
+ value &= ~DMA_CHAN_INTR_DEFAULT_MASK;
+ writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
+}
+
static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg, u32 chan)
@@ -125,6 +136,17 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
}
+static void dwmac410_dma_deinit_channel(struct stmmac_priv *priv,
+ void __iomem *ioaddr, u32 chan)
+{
+ const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
+ u32 value;
+
+ value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
+ value &= ~DMA_CHAN_INTR_DEFAULT_MASK_4_10;
+ writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
+}
+
static void dwmac4_dma_init(void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg)
{
@@ -548,6 +570,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = {
.reset = dwmac4_dma_reset,
.init = dwmac4_dma_init,
.init_chan = dwmac4_dma_init_channel,
+ .deinit_chan = dwmac4_dma_deinit_channel,
.init_rx_chan = dwmac4_dma_init_rx_chan,
.init_tx_chan = dwmac4_dma_init_tx_chan,
.axi = dwmac4_dma_axi,
@@ -577,6 +600,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops = {
.reset = dwmac4_dma_reset,
.init = dwmac4_dma_init,
.init_chan = dwmac410_dma_init_channel,
+ .deinit_chan = dwmac410_dma_deinit_channel,
.init_rx_chan = dwmac4_dma_init_rx_chan,
.init_tx_chan = dwmac4_dma_init_tx_chan,
.axi = dwmac4_dma_axi,
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index e6317b94fff7..04dafec021b4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -170,6 +170,8 @@ struct stmmac_dma_ops {
void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg, u32 chan);
+ void (*deinit_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
+ u32 chan);
void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
struct stmmac_dma_cfg *dma_cfg,
dma_addr_t phy, u32 chan);
@@ -235,6 +237,8 @@ struct stmmac_dma_ops {
stmmac_do_void_callback(__priv, dma, init, __args)
#define stmmac_init_chan(__priv, __args...) \
stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
+#define stmmac_deinit_chan(__priv, __args...) \
+ stmmac_do_void_callback(__priv, dma, deinit_chan, __priv, __args)
#define stmmac_init_rx_chan(__priv, __args...) \
stmmac_do_void_callback(__priv, dma, init_rx_chan, __priv, __args)
#define stmmac_init_tx_chan(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 2a0d7eff88d3..af29a50ddb89 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2560,6 +2560,7 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
{
u8 rx_channels_count = priv->plat->rx_queues_to_use;
u8 tx_channels_count = priv->plat->tx_queues_to_use;
+ u8 dma_csr_ch = max(rx_channels_count, tx_channels_count);
u8 chan;
for (chan = 0; chan < rx_channels_count; chan++)
@@ -2567,6 +2568,9 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
for (chan = 0; chan < tx_channels_count; chan++)
stmmac_stop_tx_dma(priv, chan);
+
+ for (chan = 0; chan < dma_csr_ch; chan++)
+ stmmac_deinit_chan(priv, priv->ioaddr, chan);
}
/**
--
2.55.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net v2] net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend
2026-07-20 11:15 [PATCH net v2] net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend Luis Lang
@ 2026-07-20 13:59 ` Andrew Lunn
2026-07-20 14:40 ` Maxime Chevallier
1 sibling, 0 replies; 3+ messages in thread
From: Andrew Lunn @ 2026-07-20 13:59 UTC (permalink / raw)
To: Luis Lang
Cc: netdev, Maxime Chevallier, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin,
Alexandre Torgue, Russell King (Oracle), Oleksij Rempel,
Ovidiu Panait, Rohan G Thomas,
moderated list:ARM/STM32 ARCHITECTURE,
moderated list:ARM/STM32 ARCHITECTURE, open list
On Mon, Jul 20, 2026 at 01:15:29PM +0200, Luis Lang wrote:
> Since commit 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU
> interrupts"), suspending causes an interrupt storm from the RPS
> interrupt.
> Fix this by adding a deinit_chan() op to stmmac_dma_ops, which
> masks all default dma channel interrupts. This is called from
> stmmac_stop_all_dma(), so interrupts don't trigger while suspending.
>
> Fixes: 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts")
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Suggested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
> Signed-off-by: Luis Lang <luis.la@mail.de>
Nice. Thanks for working on this.
These are the sort of patches i like to see. We see a lot of AI driven
patches fixing theoretical issues which nobody really cares about. The
submitter does not appear to understand what they are doing, maybe
compile tests it, but never boot it on real hardware.
You have built and booted lots of kernels, done git bisects, sent a
good bug report, done the work of actually fixing the problem with a
little help from us, and pretty much got the processes correct first
time. You have the basics for being a real kernel hacker. I would be
happy to receive more patches from you.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Thanks
Andrew
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net v2] net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend
2026-07-20 11:15 [PATCH net v2] net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend Luis Lang
2026-07-20 13:59 ` Andrew Lunn
@ 2026-07-20 14:40 ` Maxime Chevallier
1 sibling, 0 replies; 3+ messages in thread
From: Maxime Chevallier @ 2026-07-20 14:40 UTC (permalink / raw)
To: Luis Lang, netdev
Cc: Andrew Lunn, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Russell King (Oracle), Oleksij Rempel, Ovidiu Panait,
Rohan G Thomas, moderated list:ARM/STM32 ARCHITECTURE,
moderated list:ARM/STM32 ARCHITECTURE, open list
Hi Luis,
On 7/20/26 13:15, Luis Lang wrote:
> Since commit 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU
> interrupts"), suspending causes an interrupt storm from the RPS
> interrupt.
> Fix this by adding a deinit_chan() op to stmmac_dma_ops, which
> masks all default dma channel interrupts. This is called from
> stmmac_stop_all_dma(), so interrupts don't trigger while suspending.
>
> Fixes: 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts")
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Suggested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
> Signed-off-by: Luis Lang <luis.la@mail.de>
I wasn't able to reproduce the original issue on dwmac4, however
I could test that suspend/resume as well as WoL still works on a
dwmac4 device with this patch applied.
Thanks for the patch !
Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Maxime
> ---
> .../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 24 +++++++++++++++++++
> drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 ++++
> .../net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++++
> 3 files changed, 32 insertions(+)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> index 829a23bdad01..23ffe1adcd0d 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> @@ -106,6 +106,17 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
> ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> }
>
> +static void dwmac4_dma_deinit_channel(struct stmmac_priv *priv,
> + void __iomem *ioaddr, u32 chan)
> +{
> + const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> + u32 value;
> +
> + value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> + value &= ~DMA_CHAN_INTR_DEFAULT_MASK;
> + writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> +}
> +
> static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
> void __iomem *ioaddr,
> struct stmmac_dma_cfg *dma_cfg, u32 chan)
> @@ -125,6 +136,17 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
> ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> }
>
> +static void dwmac410_dma_deinit_channel(struct stmmac_priv *priv,
> + void __iomem *ioaddr, u32 chan)
> +{
> + const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
> + u32 value;
> +
> + value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> + value &= ~DMA_CHAN_INTR_DEFAULT_MASK_4_10;
> + writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
> +}
> +
> static void dwmac4_dma_init(void __iomem *ioaddr,
> struct stmmac_dma_cfg *dma_cfg)
> {
> @@ -548,6 +570,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = {
> .reset = dwmac4_dma_reset,
> .init = dwmac4_dma_init,
> .init_chan = dwmac4_dma_init_channel,
> + .deinit_chan = dwmac4_dma_deinit_channel,
> .init_rx_chan = dwmac4_dma_init_rx_chan,
> .init_tx_chan = dwmac4_dma_init_tx_chan,
> .axi = dwmac4_dma_axi,
> @@ -577,6 +600,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops = {
> .reset = dwmac4_dma_reset,
> .init = dwmac4_dma_init,
> .init_chan = dwmac410_dma_init_channel,
> + .deinit_chan = dwmac410_dma_deinit_channel,
> .init_rx_chan = dwmac4_dma_init_rx_chan,
> .init_tx_chan = dwmac4_dma_init_tx_chan,
> .axi = dwmac4_dma_axi,
> diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> index e6317b94fff7..04dafec021b4 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
> @@ -170,6 +170,8 @@ struct stmmac_dma_ops {
> void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
> void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> struct stmmac_dma_cfg *dma_cfg, u32 chan);
> + void (*deinit_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> + u32 chan);
> void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
> struct stmmac_dma_cfg *dma_cfg,
> dma_addr_t phy, u32 chan);
> @@ -235,6 +237,8 @@ struct stmmac_dma_ops {
> stmmac_do_void_callback(__priv, dma, init, __args)
> #define stmmac_init_chan(__priv, __args...) \
> stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
> +#define stmmac_deinit_chan(__priv, __args...) \
> + stmmac_do_void_callback(__priv, dma, deinit_chan, __priv, __args)
> #define stmmac_init_rx_chan(__priv, __args...) \
> stmmac_do_void_callback(__priv, dma, init_rx_chan, __priv, __args)
> #define stmmac_init_tx_chan(__priv, __args...) \
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 2a0d7eff88d3..af29a50ddb89 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2560,6 +2560,7 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
> {
> u8 rx_channels_count = priv->plat->rx_queues_to_use;
> u8 tx_channels_count = priv->plat->tx_queues_to_use;
> + u8 dma_csr_ch = max(rx_channels_count, tx_channels_count);
> u8 chan;
>
> for (chan = 0; chan < rx_channels_count; chan++)
> @@ -2567,6 +2568,9 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
>
> for (chan = 0; chan < tx_channels_count; chan++)
> stmmac_stop_tx_dma(priv, chan);
> +
> + for (chan = 0; chan < dma_csr_ch; chan++)
> + stmmac_deinit_chan(priv, priv->ioaddr, chan);
> }
>
> /**
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-20 14:40 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 11:15 [PATCH net v2] net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend Luis Lang
2026-07-20 13:59 ` Andrew Lunn
2026-07-20 14:40 ` Maxime Chevallier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox