wifi: mt76: mt7921: fix potential deadlock in mt7921_roc_abort_sync
Subsystems (2)
PATCH 1/1 wifi: mt76: mt7921: fix potential deadlock in mt7921_roc_abort_sync
From: Sean Wang <[email protected]>
roc_abort_sync() can deadlock with roc_work(). roc_work() holds dev->mt76.mutex, while cancel_work_sync() waits for roc_work() to finish. If the caller already owns the same mutex, both sides block and no progress is possible.
This deadlock can occur during station removal when mt76_sta_state() -> mt76_sta_remove() -> mt7921_mac_sta_remove() -> mt7921_roc_abort_sync() invokes cancel_work_sync() while roc_work() is still running and holding dev->mt76.mutex.
This avoids the mutex deadlock and preserves exactly-once work ownership.
Fixes 352d966126e6 ("wifi: mt76: mt7921: fix a potential association failure upon resuming")
Co-developed-by Quan Zhou <[email protected]>
Signed-off-by Quan Zhou <[email protected]>
Signed-off-by Sean Wang <[email protected]>
--- drivers/net/wireless/mediatek/mt76/mt7921/main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/main.c +8 -5
@@ -371,12 +371,15 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev) {struct mt792x_phy *phy = &dev->phy; +if (!test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) +return ; +timer_delete_sync (&phy->roc_timer); -cancel_work_sync (&phy->roc_work); -if (test_and_clear_bit (MT76_STATE_ROC , &phy->mt76->state)) -ieee80211_iterate_interfaces (mt76_hw (dev), -IEEE80211_IFACE_ITER_RESUME_ALL , - mt7921_roc_iter, (void *)phy); +cancel_work (&phy->roc_work); + +ieee80211_iterate_interfaces (mt76_hw (dev), +IEEE80211_IFACE_ITER_RESUME_ALL , + mt7921_roc_iter, (void *)phy); }EXPORT_SYMBOL_GPL (mt7921_roc_abort_sync);
Signature · 1 line
2.43.0