diff options
author | Lorenzo Bianconi <lorenzo@kernel.org> | 2021-04-18 18:45:28 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2021-04-21 20:55:52 +0200 |
commit | 7cd740f0e499d9bfd672ff1f3f6512503141abbe (patch) | |
tree | 07cd3dca5edace2f3be00b15deb2c7d20716162d | |
parent | fad90e43eac0434108af18e326e179d1b5153135 (diff) | |
download | lwn-7cd740f0e499d9bfd672ff1f3f6512503141abbe.tar.gz lwn-7cd740f0e499d9bfd672ff1f3f6512503141abbe.zip |
mt76: mt7663: fix a race between mt7615_mcu_drv_pmctrl and mt7615_mcu_fw_pmctrl
Introduce a mutex in order to avoid a race between mt7615_mcu_lp_drv_pmctrl and
mt7615_mcu_fw_pmctrl routines since they are run two independent works
Fixes: 1f549009b5b2 ("mt76: mt7615: do not request {driver,fw}_own if already granted")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7615/init.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 20 |
2 files changed, 15 insertions, 6 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index d84662fb0304..5429536e8d43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -505,6 +505,7 @@ void mt7615_init_device(struct mt7615_dev *dev) INIT_DELAYED_WORK(&dev->pm.ps_work, mt7615_pm_power_save_work); INIT_WORK(&dev->pm.wake_work, mt7615_pm_wake_work); + mutex_init(&dev->pm.mutex); init_completion(&dev->pm.wake_cmpl); spin_lock_init(&dev->pm.txq_lock); set_bit(MT76_STATE_PM, &dev->mphy.state); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 364daef4b0be..7081bb4a28bd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -323,9 +323,11 @@ static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev) static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; - int i; + int i, err = 0; + + mutex_lock(&dev->pm.mutex); - if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state)) + if (!test_bit(MT76_STATE_PM, &mphy->state)) goto out; for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) { @@ -337,14 +339,16 @@ static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev) if (i == MT7615_DRV_OWN_RETRY_COUNT) { dev_err(dev->mt76.dev, "driver own failed\n"); - set_bit(MT76_STATE_PM, &mphy->state); - return -EIO; + err = -EIO; + goto out; } + clear_bit(MT76_STATE_PM, &mphy->state); out: dev->pm.last_activity = jiffies; + mutex_unlock(&dev->pm.mutex); - return 0; + return err; } static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) @@ -353,8 +357,10 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) int err = 0; u32 addr; + mutex_lock(&dev->pm.mutex); + if (test_and_set_bit(MT76_STATE_PM, &mphy->state)) - return 0; + goto out; mt7622_trigger_hif_int(dev, true); @@ -370,6 +376,8 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) } mt7622_trigger_hif_int(dev, false); +out: + mutex_unlock(&dev->pm.mutex); return err; } |