Skip to content

Commit 5cf8e47

Browse files
committed
wifi: mt76: mt7921: fix missing mutex protection in multiple paths
The MT7921 driver has the same mutex protection bugs as MT7925 - they were inherited when MT7925 was forked from MT7921. Several code paths iterate over active interfaces and call MCU functions without proper mutex protection. Add mutex protection in the following locations: 1. mt7921_set_runtime_pm() in main.c: Called when runtime PM settings change. The callback mt7921_pm_interface_iter() calls MCU functions that require the device mutex to be held. 2. mt7921_regd_set_6ghz_power_type() in main.c: Called during VIF add/remove for 6GHz power type determination. Uses ieee80211_iterate_active_interfaces() without mutex. 3. mt7921_mac_reset_work() in mac.c: After firmware recovery, iterates interfaces to reconnect them. The mt7921_vif_connect_iter() callback calls MCU functions. 4. mt7921_roc_abort_sync() in main.c: The function iterates interfaces and calls MCU functions via mt7921_roc_iter() callback. The mutex must be held during the iteration, not at call sites, to avoid nested mutex acquisition deadlocks in suspend paths. These bugs can cause system hangs during: - Power management state transitions - WiFi reset/recovery - Suspend/resume cycles - 6GHz regulatory power type changes The fix follows the same pattern used in the MT7925 patches, with the mutex protection moved inside mt7921_roc_abort_sync() to avoid deadlocks when called from suspend paths. Suspend paths (pci.c, sdio.c) are updated to remove the outer mutex since mt7921_roc_abort_sync() now handles mutex internally. Signed-off-by: Zac Bowling <zac@zacbowling.com>
1 parent 3c23252 commit 5cf8e47

2 files changed

Lines changed: 10 additions & 1 deletion

File tree

mt7921/mac.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,9 +693,11 @@ void mt7921_mac_reset_work(struct work_struct *work)
693693
clear_bit(MT76_RESET, &dev->mphy.state);
694694
pm->suspended = false;
695695
ieee80211_wake_queues(hw);
696+
mt792x_mutex_acquire(dev);
696697
ieee80211_iterate_active_interfaces(hw,
697698
IEEE80211_IFACE_ITER_RESUME_ALL,
698699
mt7921_vif_connect_iter, NULL);
700+
mt792x_mutex_release(dev);
699701
mt76_connac_power_save_sched(&dev->mt76.phy, pm);
700702
}
701703

mt7921/main.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,13 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev)
373373

374374
del_timer_sync(&phy->roc_timer);
375375
cancel_work_sync(&phy->roc_work);
376-
if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
376+
if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) {
377+
mt792x_mutex_acquire(dev);
377378
ieee80211_iterate_interfaces(mt76_hw(dev),
378379
IEEE80211_IFACE_ITER_RESUME_ALL,
379380
mt7921_roc_iter, (void *)phy);
381+
mt792x_mutex_release(dev);
382+
}
380383
}
381384
EXPORT_SYMBOL_GPL(mt7921_roc_abort_sync);
382385

@@ -619,9 +622,11 @@ void mt7921_set_runtime_pm(struct mt792x_dev *dev)
619622
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
620623

621624
pm->enable = pm->enable_user && !monitor;
625+
mt792x_mutex_acquire(dev);
622626
ieee80211_iterate_active_interfaces(hw,
623627
IEEE80211_IFACE_ITER_RESUME_ALL,
624628
mt7921_pm_interface_iter, dev);
629+
mt792x_mutex_release(dev);
625630
pm->ds_enable = pm->ds_enable_user && !monitor;
626631
mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
627632
}
@@ -765,9 +770,11 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add)
765770
struct mt792x_dev *dev = phy->dev;
766771
u32 valid_vif_num = 0;
767772

773+
mt792x_mutex_acquire(dev);
768774
ieee80211_iterate_active_interfaces(mt76_hw(dev),
769775
IEEE80211_IFACE_ITER_RESUME_ALL,
770776
mt7921_calc_vif_num, &valid_vif_num);
777+
mt792x_mutex_release(dev);
771778

772779
if (valid_vif_num > 1) {
773780
phy->power_type = MT_AP_DEFAULT;

0 commit comments

Comments
 (0)