mt76: mt7615: run mt7615_mcu_set_roc holding mt76 mutex
authorLorenzo Bianconi <lorenzo@kernel.org>
Fri, 3 Jul 2020 08:15:52 +0000 (10:15 +0200)
committerFelix Fietkau <nbd@nbd.name>
Tue, 21 Jul 2020 17:01:17 +0000 (19:01 +0200)
Make sure to run mt7615_mcu_set_roc() holding mt76 mutex in order to
wake the device from low power state and avoid races

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7615/main.c

index c52b5c68ba97c93a987620e9e1d4c2c1ea33dd48..47dca270150deac7d8dc2e83b62d6addc5d3b48a 100644 (file)
@@ -871,9 +871,11 @@ void mt7615_roc_work(struct work_struct *work)
        if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
                return;
 
+       mt7615_mutex_acquire(phy->dev);
        ieee80211_iterate_active_interfaces(phy->mt76->hw,
                                            IEEE80211_IFACE_ITER_RESUME_ALL,
                                            mt7615_roc_iter, phy);
+       mt7615_mutex_release(phy->dev);
        ieee80211_remain_on_channel_expired(phy->mt76->hw);
 }
 
@@ -991,20 +993,24 @@ static int mt7615_remain_on_channel(struct ieee80211_hw *hw,
        if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state))
                return 0;
 
+       mt7615_mutex_acquire(phy->dev);
+
        err = mt7615_mcu_set_roc(phy, vif, chan, duration);
        if (err < 0) {
                clear_bit(MT76_STATE_ROC, &phy->mt76->state);
-               return err;
+               goto out;
        }
 
        if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, HZ)) {
                mt7615_mcu_set_roc(phy, vif, NULL, 0);
                clear_bit(MT76_STATE_ROC, &phy->mt76->state);
-
-               return -ETIMEDOUT;
+               err = -ETIMEDOUT;
        }
 
-       return 0;
+out:
+       mt7615_mutex_release(phy->dev);
+
+       return err;
 }
 
 static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
@@ -1018,7 +1024,9 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
        del_timer_sync(&phy->roc_timer);
        cancel_work_sync(&phy->roc_work);
 
+       mt7615_mutex_acquire(phy->dev);
        mt7615_mcu_set_roc(phy, vif, NULL, 0);
+       mt7615_mutex_release(phy->dev);
 
        return 0;
 }