[PATCH wireless] wifi: mt76: mt792x: defer the MCU shutdown past unregister on USB
Devin Wittmayer
lucid_duck at justthetip.ca
Wed Sep 23 10:24:24 PDT 2026
The USB disconnect path abandons the MCU before it unregisters, so the
teardown commands that follow cannot be answered. The response parser
reads the silence as a timeout and starts a chip reset for each one,
queueing the work that was cancelled nine lines earlier and reloading
firmware onto a device being removed.
Shut the MCU down after unregister instead. MT7921AU on a Pi 5, eight
unload cycles per arm:
unload 5.67 s -> 2.81 s
MCU timeouts 8 -> 0
reset queued 8/8 -> 0/8
Deauthorizing the port with the link up, to cover a surprise removal,
goes from 3.21 s to 0.33 s.
Fixes: 7910bd565d8b ("wifi: mt76: mt792x: quiesce USB paths on disconnect")
Tested-by: Eason Lai <eason.lai at mediatek.com>
Signed-off-by: Devin Wittmayer <lucid_duck at justthetip.ca>
---
drivers/net/wireless/mediatek/mt76/mt792x_usb.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
index 850f6b2cfc4a..5e19e64a9a00 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c
@@ -502,21 +502,26 @@ void mt792xu_disconnect(struct usb_interface *usb_intf)
return;
set_bit(MT76_RESET, &dev->mphy.state);
- set_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
- wake_up(&dev->mt76.mcu.wait);
- skb_queue_purge(&dev->mt76.mcu.res_q);
- cancel_work_sync(&dev->reset_work);
cancel_work_sync(&dev->init_work);
mt76_worker_disable(&dev->mt76.tx_worker);
mt792xu_reset_work_cleanup(dev);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) {
+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
+ wake_up(&dev->mt76.mcu.wait);
+ skb_queue_purge(&dev->mt76.mcu.res_q);
+ cancel_work_sync(&dev->reset_work);
set_bit(MT76_REMOVED, &dev->mphy.state);
return;
}
mt76_unregister_device(&dev->mt76);
+
+ set_bit(MT76_MCU_RESET, &dev->mphy.state);
+ wake_up(&dev->mt76.mcu.wait);
+ skb_queue_purge(&dev->mt76.mcu.res_q);
+ cancel_work_sync(&dev->reset_work);
mt792xu_cleanup(dev);
set_bit(MT76_REMOVED, &dev->mphy.state);
--
2.55.0
More information about the Linux-mediatek
mailing list