INIT_DELAYED_WORK(&dev->pm.ps_work, mt7921_pm_power_save_work);
INIT_WORK(&dev->pm.wake_work, mt7921_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);
int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
- int i;
+ int i, err = 0;
- if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state))
+ mutex_lock(&dev->pm.mutex);
+
+ if (!test_bit(MT76_STATE_PM, &mphy->state))
goto out;
for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "driver own failed\n");
- mt7921_reset(&dev->mt76);
- 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;
+ if (err)
+ mt7921_reset(&dev->mt76);
+
+ return err;
}
int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)
{
struct mt76_phy *mphy = &dev->mt76.phy;
- int i;
+ int i, err = 0;
+
+ mutex_lock(&dev->pm.mutex);
if (test_and_set_bit(MT76_STATE_PM, &mphy->state))
- return 0;
+ goto out;
for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN);
if (i == MT7921_DRV_OWN_RETRY_COUNT) {
dev_err(dev->mt76.dev, "firmware own failed\n");
- mt7921_reset(&dev->mt76);
- return -EIO;
+ clear_bit(MT76_STATE_PM, &mphy->state);
+ err = -EIO;
}
+out:
+ mutex_unlock(&dev->pm.mutex);
- return 0;
+ if (err)
+ mt7921_reset(&dev->mt76);
+
+ return err;
}
void