** Description changed:

  [ Impact ]
- When an MT7921AU USB Wi-Fi dongle (e.g. 0e8d:7961) experiences communication 
stalls (USB -110 ETIMEDOUT errors), mt792x_mac_work holds dev->mt76.mutex while 
looping on register reads. When USB core detects the stall and triggers unbind, 
mt792xu_disconnect calls mt76_unregister_device, which takes rtnl_lock and 
calls mt7921_abort_roc.
+ When an MT7921AU/MT7925 USB wireless adapter (e.g. 0e8d:7961) experiences 
communication stalls (USB -110 ETIMEDOUT errors on MT_MIB_SDR9 register reads), 
mt792x_mac_work holds dev->mt76.mutex while looping on register reads. When USB 
core detects the stall and triggers unbind, mt792xu_disconnect calls 
mt76_unregister_device, which takes rtnl_lock and calls mt7921_abort_roc (or 
mt7925_abort_roc).
  
  mt7921_abort_roc then tries to acquire dev->mt76.mutex, which is already
- held by the stuck mac_work thread. This creates an ABBA deadlock between
- rtnl_lock and mt76.mutex.
+ held by the stuck mac_work thread. This creates an unrecoverable ABBA
+ deadlock between rtnl_lock and dev->mt76.mutex.
  
  As a result:
- - mac_work waits on USB timeouts with mt76.mutex held.
- - mt792xu_disconnect waits for mt76.mutex under rtnl_lock.
+ - mac_work waits on USB timeouts with dev->mt76.mutex held.
+ - mt792xu_disconnect waits for dev->mt76.mutex under rtnl_lock.
  - All network operations (NetworkManager, ip, dev_close) hang forever in D 
state waiting for rtnl_lock.
  - The system cannot power off or reboot cleanly without a hard reset.
  
  [ Fix ]
- 1. In mt792xu_disconnect(), set MT76_REMOVED, MT76_RESET, and MT76_MCU_RESET 
flags and wake pending waitqueues before calling mt76_unregister_device(). 
Setting MT76_REMOVED causes all pending and subsequent USB register requests to 
fail immediately with -EIO instead of waiting for 3-second timeouts.
- 2. In mt792xu_disconnect(), synchronously cancel all workers (mac_work, 
ps_work, wake_work, reset_work, init_work) prior to unregistration.
- 3. In mt7921_abort_roc() (and mt7925_abort_roc()), check if MT76_REMOVED is 
set. If the device was removed, clear MT76_STATE_ROC and return 0 immediately 
without taking dev->mt76.mutex.
+ 1. In mt792xu_disconnect(), set MT76_REMOVED, MT76_RESET, and MT76_MCU_RESET 
immediately, wake MCU waitqueues, purge res_q, and cancel reset_work and 
init_work FIRST, followed by mac_work, ps_work, and wake_work before invoking 
mt76_unregister_device(). Setting MT76_REMOVED causes all pending and 
subsequent USB register requests to fail immediately with -EIO instead of 
blocking on 3-second timeouts.
+ 2. In mt7921_mac_reset_work() and mt7925_mac_reset_work(), check 
MT76_REMOVED: if the device was disconnected, abort reset immediately and skip 
waking queues or interface iterations on a dead adapter.
+ 3. In mt7921_abort_roc() and mt7925_abort_roc(), check if MT76_REMOVED is 
set. If the device was removed, clear MT76_STATE_ROC and return 0 immediately 
without waiting on dev->mt76.mutex or sending MCU commands over a dead bus.
+ 4. In mt7921_mcu_parse_response() and mt7925_mcu_parse_response(), suppress 
timeout error logging and mt792x_reset() when MT76_MCU_RESET or MT76_REMOVED is 
set, avoiding spurious teardown noise and preventing reset_work re-queueing 
during unbind.
  
  [ Test Plan ]
- 1. Boot kernel 7.0.0-31-generic with patched mt7921u / mt792x-usb modules.
+ 1. Boot kernel (e.g. 7.0.0-34-generic) with patched mt7921u / mt792x-usb 
modules.
  2. Insert MT7921AU USB Wi-Fi adapter (0e8d:7961) and connect to an AP.
- 3. Physically disconnect the USB adapter while network traffic is active, or 
trigger bus reset while requests are pending.
+ 3. Physically disconnect the USB adapter while network traffic is active 
(~750 pkt/s TX load).
  4. Verify in dmesg:
-    - Device disconnect completes cleanly without call traces.
+    - Device disconnect completes cleanly without call traces, WARNINGs, or 
blocked tasks.
     - rtnl_lock is not blocked; NetworkManager and ip link operate normally.
+    - Re-plugging the adapter re-probes cleanly and reconnects.
     - System reboots and powers off cleanly without hanging in D state.
  
+ Real hardware verification performed on Dell Precision 3650 
(7.0.0-34-generic):
+ - 2x rmmod/insmod cycles: MCU teardown noise reduced to 0 lines, 0 warnings.
+ - Unplug under active TX load (~750 pkt/s): clean teardown, only "USB 
disconnect" and benign "tx urb failed: -71". Clean re-probe and reconnection on 
replug.
+ 
  [ Where problems could occur ]
- - If abort_roc returns early without taking mutex on device removal, any 
cleanup that relied on mutex serialization must be safe. Since MT76_REMOVED is 
set, hardware registers cannot be accessed anyway, so skipping mutex and 
clearing local flag is safe.
- - Canceling works before unregistering prevents concurrent execution during 
teardown, which is the desired behavior on unbind.
+ - If abort_roc returns early without taking mutex on device removal, any 
cleanup that relied on mutex serialization must be safe. Since MT76_REMOVED is 
set, hardware registers cannot be accessed anyway, so skipping mutex and 
clearing local state flag is safe.
+ - Worker cancellations prior to unregistration prevent concurrent execution 
during teardown, which is the desired behavior on unbind.
+ - Suppressing MCU timeout logs when MT76_REMOVED/MT76_MCU_RESET is set only 
silences noise during expected teardown; genuine runtime MCU timeouts with no 
flags set continue to log and trigger recovery reset as before.
  
  [ Other Info ]
- Patch tested and compiled against linux-headers-7.0.0-31-generic on Ubuntu 
26.04 (Resolute). Clean compile with 0 errors and 0 warnings.
+ Target: Ubuntu Resolute (26.04) and upstream linux-wireless.
+ Patch: Fix mt7921u/mt792xu USB disconnect deadlock on timeout v3 (Attachment 
on Launchpad).
+ Verified on hardware by: Piotr Kalinski <[email protected]> 
(Tested-by: Piotr Kalinski <[email protected]>).
  
  --- [ Original Report ]
  Dell Precision 3650 Tower, Ubuntu 26.04 dev kernel 7.0.0-31-generic.
  Alfa AWUS036AXM (MT7921AU, USB ID 0e8d:7961).
  
  Under heavy traffic or weak signal, the adapter disconnects and reconnects 
rapidly. Eventually kernel dmesg shows:
  [  342.112004] mt7921u 1-2:1.0: Message 00000040 (seq 4) timeout
  [  345.184002] mt7921u 1-2:1.0: Message 00000040 (seq 5) timeout
  [  348.256011] mt7921u 1-2:1.0: Failed to get patch sem
  [  351.328008] mt7921u 1-2:1.0: hardware init failed
  
  After that, NetworkManager stops responding. Running 'ip link' hangs 
indefinitely in D state.
  Rebooting hangs on 'A stop job is running for Network Manager' and requires 
SysRq+B or power button.
  
  SysRq-t output shows mt7921_abort_roc blocked waiting on mutex while held by 
mac_work:
  [  420.100012] task:kworker/u16:3   blocked for more than 120 seconds.
  [  420.100020] Call Trace:
  [  420.100025]  __schedule+0x345/0x890
  [  420.100030]  schedule+0x5a/0xc0
  [  420.100035]  schedule_preempt_disabled+0x18/0x30
  [  420.100040]  __mutex_lock.isra.0+0x28a/0x4b0
  [  420.100045]  mt7921_abort_roc+0x2d/0x80 [mt7921_common]
  [  420.100050]  ieee80211_set_disassoc+0x62/0x90 [cfg80211]
  [  420.100055]  mt76_unregister_device+0x48/0x90 [mt76]
  [  420.100060]  mt792xu_disconnect+0x3c/0x70 [mt792x_usb]

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2167595

Title:
  mt7921u: USB reset after -110 timeouts deadlocks in mt7921_abort_roc,
  blocks rtnl_lock and shutdown

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2167595/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to