Re: [PATCH wireless] Revert "wifi: mt76: Disable napi when removing device"
From: Thorsten Leemhuis
Date: Tue Aug 11 2026 - 05:15:12 EST
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 <spasswolf@xxxxxx>
> Closes: https://lore.kernel.org/all/20260724151419.26014-1-spasswolf@xxxxxx/
> 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 <mikhail.v.gavrilov@xxxxxxxxx>
> ---
>
> 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);