Re: [REGRESSION][BISECTED] stmmac: suspend hangs since 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts")
From: Andrew Lunn <andrew@lunn.ch>
Date: 2026-07-18 00:17:00
Also in:
regressions
quoted hunk ↗ jump to hunk
It seems your assumptions are correct. If i dodiff --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