Re: [PATCH wireless] Revert "wifi: mt76: Disable napi when removing device"
Thorsten Leemhuis <[email protected]>
| Newsgroups | dev.linux.lists.regressions,org.kernel.vger.linux-kernel,org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <[email protected]> |
On 8/4/26 14:00, Mikhail Gavrilov wrote: > This reverts commit 13b7e6a96a005c656d38f3da51581deaf9866375. > > That commit made mt76_dma_cleanup() disable every RX NAPI instance before > deleting it, to silence WARNs in __netif_napi_del_locked() and > page_pool_disable_direct_recycling() seen when unloading mt7915e with an > MT7916. > > On mt7921e and mt7925e the same instances are already disabled earlier, > in mt7921e_unregister_device() and mt7925e_unregister_device(), which > only afterwards call mt792x_dma_cleanup() -> mt76_dma_cleanup(). Each > instance is therefore disabled twice, and napi_disable() is not > idempotent: on return it leaves NAPIF_STATE_SCHED and NAPIF_STATE_NPSVC > set, so the second call spins in usleep_range() forever, waiting for bits > that nobody will clear. > > mt7921_pci_shutdown() and mt7925_pci_shutdown() reuse the remove path, so > this is hit on every reboot, poweroff and module unload. It is silent: > the stuck task keeps sleeping and rescheduling, so neither the hung task > detector nor the lockup detectors fire, and the last line on the console > is "systemd-shutdown[1]: Rebooting." > [...]> Dropping the two driver-side loops instead was tried and rejected: with > them gone, the RX poll can reach mt76_token_release() via > PKT_TYPE_TXRX_NOTIFY and mt7921_mac_tx_free() while > mt76_connac2_tx_token_put() is running idr_destroy(&dev->token) outside > token_lock, which is a use-after-free rather than a hang [1]. > > Revert for now, so that reboot, poweroff and module unload work again. > The WARNs on mt7915e are a less severe problem than an unbootable > machine, and fixing them belongs in the drivers that delete the NAPI > instances, where each one can pick a point that is safe for its own > teardown order, rather than in the shared mt76_dma_cleanup(). What's the status of this? Looks like things stalled. > Reported-by: Bert Karwatzki <[email protected]> > Closes: https://lore.kernel.org/all/[email protected]/ > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221818 FWIW, I think it would be good to get this revert into 7.2 final, as there were more reports about this: https://bugzilla.kernel.org/show_bug.cgi?id=221848 https://bugzilla.kernel.org/show_bug.cgi?id=221862 And this is likely the same issue, too: https://bugzilla.kernel.org/show_bug.cgi?id=221831 I've also seen multiple people mention it in a matrix channel dedicated to Fedora's kernel. Ciao, Thorsten > Link: https://lore.kernel.org/all/20260730050428.GA73812@sol/ [1] > Signed-off-by: Mikhail Gavrilov <[email protected]> > --- > > Sending this because the regression is now in its second week with four > independent reporters, and the two-part alternative (this revert plus > napi_disable() added inside mt7915_unregister_device()) needs MT7916 > hardware that I do not have. I deliberately left the mt7915 side out; > Nicolas is best placed to do it, since MT7916 is what he reported > against. > > Verified on 7.2.0-rc5 with KASAN and lockdep enabled, MT7922 / mt7921e: > before the revert 'modprobe -r mt7921e' hangs (backtrace above, taken > with sysrq-w) and the machine never gets past "Rebooting."; after it, > module unload and reload, reboot and poweroff all work again. > > The hang was independently bisected to the same commit by Bert Karwatzki > on MT7925 and reproduced by Devin Wittmayer on MT7927 and MT7922, and > Eric Biggers saw it on mt7925e as well. > > drivers/net/wireless/mediatek/mt76/dma.c | 5 +---- > 1 file changed, 1 insertion(+), 4 deletions(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c > index 322041859217..f8c2fe5f2f58 100644 > --- a/drivers/net/wireless/mediatek/mt76/dma.c > +++ b/drivers/net/wireless/mediatek/mt76/dma.c > @@ -1189,10 +1189,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) > mt76_for_each_q_rx(dev, i) { > struct mt76_queue *q = &dev->q_rx[i]; > > - if (!mt76_queue_is_wed_rro(q)) { > - napi_disable(&dev->napi[i]); > - netif_napi_del(&dev->napi[i]); > - } > + netif_napi_del(&dev->napi[i]); > mt76_dma_rx_cleanup(dev, q); > > page_pool_destroy(q->page_pool);