Re: [PATCH mt76] wifi: mt76: mt792x: drop redundant napi_disable() in unregister path

Mikhail Gavrilov <[email protected]>
Newsgroups org.kernel.vger.linux-wireless,org.kernel.vger.linux-kernel
Message-ID <CABXGCsO07SExb+Z0PeN6MZ1fKC24Tvn3ehSyeQc-3qFC7jM7dQ@mail.gmail.com>
On Thu, Jul 30, 2026 at 10:06 AM Eric Biggers <[email protected]> wrote:
>
> While this patch fixes the shutdown hang for me too on a system using
> mt7925e, Sashiko found that this patch introduces a use-after-free
> because NAPI is now being disabled too late:
> https://sashiko.dev/#/patchset/20260728002048.19351-1-mikhail.v.gavrilov%40gmail.com
> Should 13b7e6a96a00 be reverted, then fixed in another way such as
> calling napi_disable() in mt7915_unregister_device()?
>

You are right, and so is the report.  I went through the path and it is real:

  mt792x_poll_rx()
    mt7921_queue_rx_skb()
      case PKT_TYPE_TXRX_NOTIFY:          /* mmio only, so PCIe */
        mt7921_mac_tx_free()
          mt76_token_release()            /* idr_remove() under token_lock */

and with my patch that can now run concurrently with, a few lines up in
mt7921e_unregister_device():

  mt76_connac2_tx_token_put()
    ...
    idr_destroy(&dev->token)              /* outside token_lock */

The early napi_disable() loops I removed were what kept those two apart.

My justification in the commit message was that RX is harmless once
mac80211 has stopped the hw, because mt76_rx() drops everything with
MT76_STATE_RUNNING clear.  That only covers the normal data path -
PKT_TYPE_TXRX_NOTIFY is dispatched in mt7921_queue_rx_skb() before
mt76_rx() is ever reached, and goes straight to the token IDR.  So the
window is not benign and the patch is wrong.  Please drop it.

I agree with your suggestion.  The disable 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()
where it is forced to happen after the driver has already freed state
that the RX poll can still touch.  mt7921e/mt7925e already did it, and
early enough; mt7915 and friends simply never did.

Unless Nicolas would rather do it himself, I can send a v2 series:

  1) Revert "wifi: mt76: Disable napi when removing device", restoring
     reboot, poweroff and module unload on mt7921e/mt7925e
  2) wifi: mt76: mt7915: disable napi before deleting it, for the
     original __netif_napi_del_locked() and
     page_pool_disable_direct_recycling() warnings

I would keep 2) to mt7915 for now, since that is what was reported and
tested.  mt7603, mt7615, mt7996 and mt76x0/mt76x2 have the same gap in
their unregister paths and can follow separately.

One more item from the same report, not caused by this patch but worth
someone's attention: mt7921e/mt7925e call tasklet_disable() on
mt76.irq_tasklet without a matching tasklet_kill() before
mt76_free_device(), which can leave a scheduled tasklet pointing at
freed memory.

Thanks for catching this.

-- 
Thanks,
Mikhail
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.