* [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts")
@ 2026-07-16 20:10 tresonic
2026-07-16 21:47 ` Andrew Lunn
2026-07-18 15:27 ` [PATCH] net: stmmac: dwmac4: mask interrupts before stopping DMA in suspend Luis Lang
0 siblings, 2 replies; 14+ messages in thread
From: tresonic @ 2026-07-16 20:10 UTC (permalink / raw)
To: netdev; +Cc: regressions, rmk+kernel, kuba
Hello,
Please bear with me, this is my first time writing to a mailing list...
Since commit 1b9707e6f1a9, suspend (systemctl suspend) causes a full system freeze on my laptop. Fans and keyboard backlight stay powered; the machine is completely unresponsive and requires a hard power-off (holding the power button) to recover. I could not get any kernel output from the hang.
- Reproduces on current master
- git revert 1b9707e6f1a9... on top of master fixes the issue
- Workaround: sudo ip link set eno1 down before suspend avoids the hang entirely; with the interface down, suspend/resume works normally even on the bad commit
Hardware:
64:00.0 Ethernet controller: Motorcomm Microelectronics. YT6801 Gigabit Ethernet Controller (rev 01)
Kernel driver in use: dwmac-motorcomm
[ 5.672548] YT8531S Gigabit Ethernet stmmac-6400:00: attached PHY driver (mii_bus:phy_addr=stmmac-6400:00, irq=POLL)
[ 5.890940] dwmac-motorcomm 0000:64:00.0 eno1: PHY [stmmac-6400:00] driver [YT8531S Gigabit Ethernet] (irq=POLL)
Thank you,
tresonic
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-16 20:10 [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") tresonic @ 2026-07-16 21:47 ` Andrew Lunn 2026-07-17 7:18 ` tresonic 2026-07-18 15:27 ` [PATCH] net: stmmac: dwmac4: mask interrupts before stopping DMA in suspend Luis Lang 1 sibling, 1 reply; 14+ messages in thread From: Andrew Lunn @ 2026-07-16 21:47 UTC (permalink / raw) To: tresonic; +Cc: netdev, regressions, rmk+kernel, kuba On Thu, Jul 16, 2026 at 10:10:25PM +0200, tresonic wrote: > Hello, > Please bear with me, this is my first time writing to a mailing list... Thanks for the report. Nice description for a first post. Lots of useful details. > Since commit 1b9707e6f1a9, suspend (systemctl suspend) causes a full system freeze on my laptop. Fans and keyboard backlight stay powered; the machine is completely unresponsive and requires a hard power-off (holding the power button) to recover. I could not get any kernel output from the hang. 1b9707e6f1a9 makes in effect 4 changes. Can you do some testing to see if the changes to DMA_CHAN_INTR_ABNORMAL or the changes to DMA_CHAN_INTR_ABNORMAL_4_10 break it. Or both, but i think that is unlikely. Once you know which of those is responsible, can you test to see which of DMA_CHAN_INTR_ENA_RPS or DMA_CHAN_INTR_ENA_RBU broke it. It kind of sounds like an interrupt storm, but that is just a guess. If it is an interrupt storm, it suggests an interrupt is not being disabled during suspend. Andrew ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-16 21:47 ` Andrew Lunn @ 2026-07-17 7:18 ` tresonic 2026-07-17 15:40 ` Andrew Lunn 0 siblings, 1 reply; 14+ messages in thread From: tresonic @ 2026-07-17 7:18 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, regressions, rmk+kernel, kuba On 7/16/26 11:47 PM, Andrew Lunn wrote: > On Thu, Jul 16, 2026 at 10:10:25PM +0200, tresonic wrote: >> Hello, >> Please bear with me, this is my first time writing to a mailing list... > > Thanks for the report. Nice description for a first post. Lots of > useful details. > >> Since commit 1b9707e6f1a9, suspend (systemctl suspend) causes a full system freeze on my laptop. Fans and keyboard backlight stay powered; the machine is completely unresponsive and requires a hard power-off (holding the power button) to recover. I could not get any kernel output from the hang. > > 1b9707e6f1a9 makes in effect 4 changes. > > Can you do some testing to see if the changes to > DMA_CHAN_INTR_ABNORMAL or the changes to DMA_CHAN_INTR_ABNORMAL_4_10 > break it. Or both, but i think that is unlikely. > > Once you know which of those is responsible, can you test to see which > of DMA_CHAN_INTR_ENA_RPS or DMA_CHAN_INTR_ENA_RBU broke it. > > It kind of sounds like an interrupt storm, but that is just a > guess. If it is an interrupt storm, it suggests an interrupt is not > being disabled during suspend. > > Andrew I tested the changes as you suggested and it seems DMA_CHAN_INTR_ENA_RPS in DMA_CHAN_INTR_ABNORMAL_4_10 broke it. With this change on master suspend is working: diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h index 43b036d4e95b..e907142c9ee2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h @@ -121,7 +121,6 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs, DMA_CHAN_INTR_ENA_TIE) #define DMA_CHAN_INTR_ABNORMAL_4_10 (DMA_CHAN_INTR_ENA_AIE_4_10 | \ - DMA_CHAN_INTR_ENA_RPS | \ DMA_CHAN_INTR_ENA_RBU | \ DMA_CHAN_INTR_ENA_FBE) /* DMA default interrupt mask for 4.10a */ tresonic ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-17 7:18 ` tresonic @ 2026-07-17 15:40 ` Andrew Lunn 2026-07-17 22:23 ` tresonic 0 siblings, 1 reply; 14+ messages in thread From: Andrew Lunn @ 2026-07-17 15:40 UTC (permalink / raw) To: tresonic; +Cc: netdev, regressions, rmk+kernel, kuba, Maxime Chevallier > I tested the changes as you suggested and it seems DMA_CHAN_INTR_ENA_RPS in DMA_CHAN_INTR_ABNORMAL_4_10 broke it. > With this change on master suspend is working: > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h > index 43b036d4e95b..e907142c9ee2 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h > @@ -121,7 +121,6 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs, > DMA_CHAN_INTR_ENA_TIE) > > #define DMA_CHAN_INTR_ABNORMAL_4_10 (DMA_CHAN_INTR_ENA_AIE_4_10 | \ > - DMA_CHAN_INTR_ENA_RPS | \ > DMA_CHAN_INTR_ENA_RBU | \ > DMA_CHAN_INTR_ENA_FBE) > /* DMA default interrupt mask for 4.10a */ OK, that narrows it down a bit. I made the guess it is an interrupt storm during suspend, because interrupts are not disabled. DMA_CHAN_INTR_ABNORMAL_4_10 is written to hardware in dwmac410_dma_init_channel(). However, i don't see anywhere these interrupts are clear? struct stmmac_dma_ops has an init_chan operation, but there is no opposite operation to reset a channel? There is however disable_dma_irq. Maybe DMA_CHAN_INTR_ENA_RPS can be cleared there? But i'm also having trouble finding where dwmac4_disable_dma_irq() is actually called. It is called from stmmac_disable_rx_queue() and stmmac_disable_tx_queue() but they only seem to be used in the XDP code. Are the DMAs being stopped during suspend? I don't know this driver well enough to answer that. Can you scatter some printk() around and see what actually happens on suspend. See if you can find somewhere to disable that one interrupt? Andrew ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-17 15:40 ` Andrew Lunn @ 2026-07-17 22:23 ` tresonic 2026-07-17 22:34 ` tresonic 2026-07-18 0:16 ` Andrew Lunn 0 siblings, 2 replies; 14+ messages in thread From: tresonic @ 2026-07-17 22:23 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, regressions, rmk+kernel, kuba, Maxime Chevallier On 7/17/26 5:40 PM, Andrew Lunn wrote: >> I tested the changes as you suggested and it seems DMA_CHAN_INTR_ENA_RPS in DMA_CHAN_INTR_ABNORMAL_4_10 broke it. >> With this change on master suspend is working: >> >> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h >> index 43b036d4e95b..e907142c9ee2 100644 >> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h >> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h >> @@ -121,7 +121,6 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs, >> DMA_CHAN_INTR_ENA_TIE) >> >> #define DMA_CHAN_INTR_ABNORMAL_4_10 (DMA_CHAN_INTR_ENA_AIE_4_10 | \ >> - DMA_CHAN_INTR_ENA_RPS | \ >> DMA_CHAN_INTR_ENA_RBU | \ >> DMA_CHAN_INTR_ENA_FBE) >> /* DMA default interrupt mask for 4.10a */ > > OK, that narrows it down a bit. > > I made the guess it is an interrupt storm during suspend, because > interrupts are not disabled. DMA_CHAN_INTR_ABNORMAL_4_10 is written to > hardware in dwmac410_dma_init_channel(). However, i don't see anywhere > these interrupts are clear? struct stmmac_dma_ops has an init_chan > operation, but there is no opposite operation to reset a channel? > There is however disable_dma_irq. Maybe DMA_CHAN_INTR_ENA_RPS can be > cleared there? > > But i'm also having trouble finding where dwmac4_disable_dma_irq() is > actually called. It is called from stmmac_disable_rx_queue() and > stmmac_disable_tx_queue() but they only seem to be used in the XDP > code. > > Are the DMAs being stopped during suspend? I don't know this driver > well enough to answer that. > > Can you scatter some printk() around and see what actually happens on > suspend. See if you can find somewhere to disable that one interrupt? > > Andrew It seems your assumptions are correct. If i do diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index a0249715fafa..487efc746b20 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -129,6 +129,8 @@ void dwmac4_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); + value &= ~DMA_CHAN_INTR_ENA_RPS; + if (rx) value &= ~DMA_CHAN_INTR_ENA_RIE; if (tx) I can suspend and resume! Could it be sufficient to just do this and reenable on dwmac4_enable_dma_irq? tresonic ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-17 22:23 ` tresonic @ 2026-07-17 22:34 ` tresonic 2026-07-18 0:16 ` Andrew Lunn 1 sibling, 0 replies; 14+ messages in thread From: tresonic @ 2026-07-17 22:34 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, regressions, rmk+kernel, kuba, Maxime Chevallier >> But i'm also having trouble finding where dwmac4_disable_dma_irq() is >> actually called. It is called from stmmac_disable_rx_queue() and >> stmmac_disable_tx_queue() but they only seem to be used in the XDP >> code. Afaict these are called through the stmmac_stop_rx macro which maps to the function pointers in dwmac410_dma_ops. So this actually gets called from stmmac_suspend via stmmac_stop_all_dma. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-17 22:23 ` tresonic 2026-07-17 22:34 ` tresonic @ 2026-07-18 0:16 ` Andrew Lunn 2026-07-18 7:35 ` tresonic 1 sibling, 1 reply; 14+ messages in thread From: Andrew Lunn @ 2026-07-18 0:16 UTC (permalink / raw) To: tresonic; +Cc: netdev, regressions, rmk+kernel, kuba, Maxime Chevallier > It seems your assumptions are correct. If i do > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c > index a0249715fafa..487efc746b20 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c > @@ -129,6 +129,8 @@ void dwmac4_disable_dma_irq(struct stmmac_priv *priv, void __iomem *ioaddr, > const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; > u32 value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); > > + value &= ~DMA_CHAN_INTR_ENA_RPS; > + > if (rx) > value &= ~DMA_CHAN_INTR_ENA_RIE; > if (tx) > > I can suspend and resume! Cool. So we might be going in the correct direction. > Could it be sufficient to just do this and reenable on dwmac4_enable_dma_irq? Unfortunately, it is not as simple as that. The driver implements NAPI. Interrupts are expensive, so what NAPI does is after there is an interrupt indicating there are received packets, and there are more than 64 packets to be received, it disables interrupts, and goes into polling made. Whenever it polls, if there are packets available it keeps on polling. Only when polling indicates there are no more packets, are interrupts re-enabled and polling stopped. You can see parts of this logic in stmmac_napi_poll_rx(). This means it cannot be done here. We need a function which is only called on suspend, and probably release. The interrupt is being enabled in the init_chan call in stmmac_dma_ops. Ideally, it should be disabled in a mirror function, which currently does not exist. So maybe deinit_chan() needs adding. But where to call it from? init_chan() is called from stmmac_init_dma_engine(), from stmmac_hw_setup(). stmmac_resume() does call this. So we need something in stmmac_suspend(). Maybe in stmmac_stop_all_dma()? stmmac is messy, there are often not mirror functions. If there is a stmmac_init_dma_engine() there should be stmmac_deinit_dma_engine(). If there is stmmac_hw_setup() there should be stmmac_hw_tairdown(). But none of these seem to exist. Anyway, do you want to try to implement deinit_chan() and call it from stmmac_stop_all_dma()? Andrew ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-18 0:16 ` Andrew Lunn @ 2026-07-18 7:35 ` tresonic 2026-07-18 13:11 ` Maxime Chevallier 2026-07-18 14:06 ` Andrew Lunn 0 siblings, 2 replies; 14+ messages in thread From: tresonic @ 2026-07-18 7:35 UTC (permalink / raw) To: Andrew Lunn; +Cc: netdev, regressions, rmk+kernel, kuba, Maxime Chevallier Thank you for you explanations! > The interrupt is being enabled in the init_chan call in > stmmac_dma_ops. Ideally, it should be disabled in a mirror function, > which currently does not exist. So maybe deinit_chan() needs > adding. But where to call it from? init_chan() is called from > stmmac_init_dma_engine(), from stmmac_hw_setup(). stmmac_resume() does > call this. So we need something in stmmac_suspend(). Maybe in > stmmac_stop_all_dma()? > > stmmac is messy, there are often not mirror functions. If there is a > stmmac_init_dma_engine() there should be > stmmac_deinit_dma_engine(). If there is stmmac_hw_setup() there should > be stmmac_hw_tairdown(). But none of these seem to exist. > > Anyway, do you want to try to implement deinit_chan() and call it from > stmmac_stop_all_dma()? Yes I'd really like to implement a solution here. This is my try, but I still have some questions: - is it ok to disable all interrupts on deinit_chan()? - maybe the interrupt could also just be disabled in stop_rx? diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index 829a23bdad01..65c243fb829f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -125,6 +125,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) { @@ -577,6 +588,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..8504ecc3dbeb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2560,13 +2560,16 @@ 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 max_chan = max(rx_channels_count, tx_channels_count); u8 chan; - for (chan = 0; chan < rx_channels_count; chan++) - stmmac_stop_rx_dma(priv, chan); - - for (chan = 0; chan < tx_channels_count; chan++) - stmmac_stop_tx_dma(priv, chan); + for (chan = 0; chan < max_chan; chan++) { + if (chan < rx_channels_count) + stmmac_stop_rx_dma(priv, chan); + if (chan < tx_channels_count) + stmmac_stop_tx_dma(priv, chan); + stmmac_deinit_chan(priv, priv->ioaddr, chan); + } } /** tresonic ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-18 7:35 ` tresonic @ 2026-07-18 13:11 ` Maxime Chevallier 2026-07-18 13:32 ` tresonic 2026-07-18 14:06 ` Andrew Lunn 1 sibling, 1 reply; 14+ messages in thread From: Maxime Chevallier @ 2026-07-18 13:11 UTC (permalink / raw) To: tresonic, Andrew Lunn; +Cc: netdev, regressions, rmk+kernel, kuba Hi, On 7/18/26 09:35, tresonic wrote: > Thank you for you explanations! > >> The interrupt is being enabled in the init_chan call in >> stmmac_dma_ops. Ideally, it should be disabled in a mirror function, >> which currently does not exist. So maybe deinit_chan() needs >> adding. But where to call it from? init_chan() is called from >> stmmac_init_dma_engine(), from stmmac_hw_setup(). stmmac_resume() does >> call this. So we need something in stmmac_suspend(). Maybe in >> stmmac_stop_all_dma()? >> >> stmmac is messy, there are often not mirror functions. If there is a >> stmmac_init_dma_engine() there should be >> stmmac_deinit_dma_engine(). If there is stmmac_hw_setup() there should >> be stmmac_hw_tairdown(). But none of these seem to exist. >> (sorry I missed that thread, I was on my way back from netdev) >> Anyway, do you want to try to implement deinit_chan() and call it from >> stmmac_stop_all_dma()? > Yes I'd really like to implement a solution here. > This is my try, but I still have some questions: > - is it ok to disable all interrupts on deinit_chan()? It mirrors the init, so it should be fine. Now I'm not sure how that will interfere with things like WoL though, I've yet to test this. > - maybe the interrupt could also just be disabled in stop_rx? I don't think so, if something is missing w.r.t the interrupts being enabled when they shouldn't, that would need to be addressed in the xdp part, as this seems to be the only place where stop_rx is called without the dma_chan interrupts being masked. > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c > index 829a23bdad01..65c243fb829f 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c [...] I've given this patch a test on imx8mp (that has a dwmac4.10), no regressions found from running basic tests :) I think this is a good fix, if you submit it can you address both dwmac410 and dwmac4 ? They both should be impacted by that problem. Maxime ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-18 13:11 ` Maxime Chevallier @ 2026-07-18 13:32 ` tresonic 2026-07-18 14:11 ` Andrew Lunn 0 siblings, 1 reply; 14+ messages in thread From: tresonic @ 2026-07-18 13:32 UTC (permalink / raw) To: Maxime Chevallier, Andrew Lunn; +Cc: netdev, regressions, rmk+kernel, kuba Hi, thanks for testing and feedback! > I've given this patch a test on imx8mp (that has a dwmac4.10), no regressions found > from running basic tests :) I think this is a good fix, if you submit it can you > address both dwmac410 and dwmac4 ? They both should be impacted by that problem. I've added the deinit_chan for dwmac4. Sorry for the noob question, how would I submit this fix? Just commit and separately git send-email to netdev@vger.kernel.org? These are my currernt changes: 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..8504ecc3dbeb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2560,13 +2560,16 @@ 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 max_chan = max(rx_channels_count, tx_channels_count); u8 chan; - for (chan = 0; chan < rx_channels_count; chan++) - stmmac_stop_rx_dma(priv, chan); - - for (chan = 0; chan < tx_channels_count; chan++) - stmmac_stop_tx_dma(priv, chan); + for (chan = 0; chan < max_chan; chan++) { + if (chan < rx_channels_count) + stmmac_stop_rx_dma(priv, chan); + if (chan < tx_channels_count) + stmmac_stop_tx_dma(priv, chan); + stmmac_deinit_chan(priv, priv->ioaddr, chan); + } } /** tresonic ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-18 13:32 ` tresonic @ 2026-07-18 14:11 ` Andrew Lunn 2026-07-18 15:32 ` tresonic 0 siblings, 1 reply; 14+ messages in thread From: Andrew Lunn @ 2026-07-18 14:11 UTC (permalink / raw) To: tresonic; +Cc: Maxime Chevallier, netdev, regressions, rmk+kernel, kuba > Sorry for the noob question, how would I submit this fix? There are two documents for you to read: https://docs.kernel.org/process/submitting-patches.html https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html Since this is a fix, please use the net tree. And include a Fixes: tag indicating the patch which broke it. > Just commit and separately git send-email to netdev@vger.kernel.org? ./scripts/get_maintainer.pl will give you a list of email addresses. Or take a look at https://b4.docs.kernel.org/en/latest/contributor/prep.html b4 automates some of the steps in producing patches, keeping track of versions, working out who to send to etc. Often with the kernel, the code is easy. Getting the processes correct is harder. But we are here to help. Andrew ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-18 14:11 ` Andrew Lunn @ 2026-07-18 15:32 ` tresonic 0 siblings, 0 replies; 14+ messages in thread From: tresonic @ 2026-07-18 15:32 UTC (permalink / raw) To: Andrew Lunn; +Cc: Maxime Chevallier, netdev, regressions, rmk+kernel, kuba On 7/18/26 4:11 PM, Andrew Lunn wrote: > There are two documents for you to read: > > https://docs.kernel.org/process/submitting-patches.html > > https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html > > Since this is a fix, please use the net tree. And include a Fixes: tag > indicating the patch which broke it. > >> Just commit and separately git send-email to netdev@vger.kernel.org? > > ./scripts/get_maintainer.pl will give you a list of email addresses. I did your suggested change, read through the documents and hope to have sent everything correctly :) Thanks for your help, Luis/tresonic ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") 2026-07-18 7:35 ` tresonic 2026-07-18 13:11 ` Maxime Chevallier @ 2026-07-18 14:06 ` Andrew Lunn 1 sibling, 0 replies; 14+ messages in thread From: Andrew Lunn @ 2026-07-18 14:06 UTC (permalink / raw) To: tresonic; +Cc: netdev, regressions, rmk+kernel, kuba, Maxime Chevallier > { > u8 rx_channels_count = priv->plat->rx_queues_to_use; > u8 tx_channels_count = priv->plat->tx_queues_to_use; > + u8 max_chan = max(rx_channels_count, tx_channels_count); > u8 chan; > > - for (chan = 0; chan < rx_channels_count; chan++) > - stmmac_stop_rx_dma(priv, chan); > - > - for (chan = 0; chan < tx_channels_count; chan++) > - stmmac_stop_tx_dma(priv, chan); > + for (chan = 0; chan < max_chan; chan++) { > + if (chan < rx_channels_count) > + stmmac_stop_rx_dma(priv, chan); > + if (chan < tx_channels_count) > + stmmac_stop_tx_dma(priv, chan); > + stmmac_deinit_chan(priv, priv->ioaddr, chan); > + } It is a personal preference, but i would keep the code simple, stupid, KISS. Keep the two loops as they are. And add a third loop calling stmmac_deinit_chan(). That then mirrors the code in stmmac_init_dma_engine() which also has three loops. I would also rename max_chan to dma_csr_ch so it has the same name as in stmmac_init_dma_engine(). As i said, stmmac has pretty bad naming, mirror functions are not obvious, but when adding new code, we should try to do better. Andrew ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH] net: stmmac: dwmac4: mask interrupts before stopping DMA in suspend 2026-07-16 20:10 [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") tresonic 2026-07-16 21:47 ` Andrew Lunn @ 2026-07-18 15:27 ` Luis Lang 1 sibling, 0 replies; 14+ messages in thread From: Luis Lang @ 2026-07-18 15:27 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), Ovidiu Panait, Oleksij Rempel, 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] 14+ messages in thread
end of thread, other threads:[~2026-07-18 15:33 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16 20:10 [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") tresonic
2026-07-16 21:47 ` Andrew Lunn
2026-07-17 7:18 ` tresonic
2026-07-17 15:40 ` Andrew Lunn
2026-07-17 22:23 ` tresonic
2026-07-17 22:34 ` tresonic
2026-07-18 0:16 ` Andrew Lunn
2026-07-18 7:35 ` tresonic
2026-07-18 13:11 ` Maxime Chevallier
2026-07-18 13:32 ` tresonic
2026-07-18 14:11 ` Andrew Lunn
2026-07-18 15:32 ` tresonic
2026-07-18 14:06 ` Andrew Lunn
2026-07-18 15:27 ` [PATCH] net: stmmac: dwmac4: mask interrupts before stopping DMA in suspend Luis Lang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox