summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/mt7921/main.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2022-12-21 13:47:47 +0300
committerFelix Fietkau <nbd@nbd.name>2023-02-03 16:47:15 +0300
commitde19b9c83654e323d83f839a550ca4af37fea15b (patch)
tree2dca5a07067ef49f962631f5ff468d834ee986e0 /drivers/net/wireless/mediatek/mt76/mt7921/main.c
parent8065c0e13f9875f597920a2af47e5dc2940a9c4f (diff)
downloadlinux-de19b9c83654e323d83f839a550ca4af37fea15b.tar.xz
wifi: mt76: mt7921: fix deadlock in mt7921_abort_roc
When mt7921_abort_roc is called with dev->mutex held, it can deadlock while calling cancel_work_sync(&phy->roc_work), because the work function could be waiting to acquire the mutex. Fix this by flushing the work before taking the mutex Reported-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> Fixes: 034ae28b56f1 ("wifi: mt76: mt7921: introduce remain_on_channel support") Fixes: 41ac53c899bd ("wifi: mt76: mt7921: introduce chanctx support") Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7921/main.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7921/main.c22
1 files changed, 7 insertions, 15 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 76ac5069638f..722df8eea91f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -422,15 +422,15 @@ void mt7921_roc_timer(struct timer_list *timer)
static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif)
{
- int err;
-
- if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
- return 0;
+ int err = 0;
del_timer_sync(&phy->roc_timer);
cancel_work_sync(&phy->roc_work);
- err = mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id);
- clear_bit(MT76_STATE_ROC, &phy->mt76->state);
+
+ mt7921_mutex_acquire(phy->dev);
+ if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
+ err = mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id);
+ mt7921_mutex_release(phy->dev);
return err;
}
@@ -487,13 +487,8 @@ static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw,
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
struct mt7921_phy *phy = mt7921_hw_phy(hw);
- int err;
- mt7921_mutex_acquire(phy->dev);
- err = mt7921_abort_roc(phy, mvif);
- mt7921_mutex_release(phy->dev);
-
- return err;
+ return mt7921_abort_roc(phy, mvif);
}
static int mt7921_set_channel(struct mt7921_phy *phy)
@@ -1778,11 +1773,8 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
struct ieee80211_prep_tx_info *info)
{
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
- struct mt7921_dev *dev = mt7921_hw_dev(hw);
- mt7921_mutex_acquire(dev);
mt7921_abort_roc(mvif->phy, mvif);
- mt7921_mutex_release(dev);
}
const struct ieee80211_ops mt7921_ops = {