Skip to content

Commit

Permalink
mt76: mt7921: introduce PM support
Browse files Browse the repository at this point in the history
Introduce suspend/resume and WoW (Wake-on-WoWLAN) support to mt7921
driver to allow remote wakeu-up from the suspend state.

Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Co-developed-by: Soul Huang <Soul.Huang@mediatek.com>
Signed-off-by: Soul Huang <Soul.Huang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
Sean Wang authored and Felix Fietkau committed Jan 29, 2021
1 parent b88f5c6 commit ffa1bf9
Show file tree
Hide file tree
Showing 5 changed files with 589 additions and 0 deletions.
79 changes: 79 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt7921/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,79 @@ static void mt7921_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}

#ifdef CONFIG_PM
static int mt7921_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt7921_phy *phy = mt7921_hw_phy(hw);
int err;

cancel_delayed_work_sync(&phy->scan_work);
cancel_delayed_work_sync(&phy->mt76->mac_work);

mutex_lock(&dev->mt76.mutex);

clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);

set_bit(MT76_STATE_SUSPEND, &phy->mt76->state);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7921_mcu_set_suspend_iter, phy);

err = mt7921_mcu_set_hif_suspend(dev, true);

mutex_unlock(&dev->mt76.mutex);

return err;
}

static int mt7921_resume(struct ieee80211_hw *hw)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt7921_phy *phy = mt7921_hw_phy(hw);
int err;

mutex_lock(&dev->mt76.mutex);

err = mt7921_mcu_set_hif_suspend(dev, false);
if (err < 0)
goto out;

set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
clear_bit(MT76_STATE_SUSPEND, &phy->mt76->state);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7921_mcu_set_suspend_iter, phy);

ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
MT7921_WATCHDOG_TIME);
out:
mutex_unlock(&dev->mt76.mutex);

return err;
}

static void mt7921_set_wakeup(struct ieee80211_hw *hw, bool enabled)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);
struct mt76_dev *mdev = &dev->mt76;

device_set_wakeup_enable(mdev->dev, enabled);
}

static void mt7921_set_rekey_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *data)
{
struct mt7921_dev *dev = mt7921_hw_dev(hw);

mutex_lock(&dev->mt76.mutex);
mt7921_mcu_update_gtk_rekey(hw, vif, data);
mutex_unlock(&dev->mt76.mutex);
}
#endif /* CONFIG_PM */

const struct ieee80211_ops mt7921_ops = {
.tx = mt7921_tx,
.start = mt7921_start,
Expand Down Expand Up @@ -998,4 +1071,10 @@ const struct ieee80211_ops mt7921_ops = {
.sta_statistics = mt7921_sta_statistics,
.sched_scan_start = mt7921_start_sched_scan,
.sched_scan_stop = mt7921_stop_sched_scan,
#ifdef CONFIG_PM
.suspend = mt7921_suspend,
.resume = mt7921_resume,
.set_wakeup = mt7921_set_wakeup,
.set_rekey_data = mt7921_set_rekey_data,
#endif /* CONFIG_PM */
};
Loading

0 comments on commit ffa1bf9

Please sign in to comment.