diff options
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r-- | net/mac80211/pm.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 730778a2c90..6326d343986 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -6,12 +6,37 @@ #include "driver-ops.h" #include "led.h" +/* return value indicates whether the driver should be further notified */ +static bool ieee80211_quiesce(struct ieee80211_sub_if_data *sdata) +{ + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + ieee80211_sta_quiesce(sdata); + return true; + case NL80211_IFTYPE_ADHOC: + ieee80211_ibss_quiesce(sdata); + return true; + case NL80211_IFTYPE_MESH_POINT: + ieee80211_mesh_quiesce(sdata); + return true; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: + /* don't tell driver about this */ + return false; + default: + return true; + } +} + int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; struct sta_info *sta; + if (!local->open_count) + goto suspend; + ieee80211_scan_cancel(local); if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { @@ -50,11 +75,19 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) local->wowlan = wowlan && local->open_count; if (local->wowlan) { int err = drv_suspend(local, wowlan); - if (err) { + if (err < 0) { local->quiescing = false; return err; + } else if (err > 0) { + WARN_ON(err != 1); + local->wowlan = false; + } else { + list_for_each_entry(sdata, &local->interfaces, list) { + cancel_work_sync(&sdata->work); + ieee80211_quiesce(sdata); + } + goto suspend; } - goto suspend; } /* disable keys */ @@ -82,23 +115,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) list_for_each_entry(sdata, &local->interfaces, list) { cancel_work_sync(&sdata->work); - switch(sdata->vif.type) { - case NL80211_IFTYPE_STATION: - ieee80211_sta_quiesce(sdata); - break; - case NL80211_IFTYPE_ADHOC: - ieee80211_ibss_quiesce(sdata); - break; - case NL80211_IFTYPE_MESH_POINT: - ieee80211_mesh_quiesce(sdata); - break; - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_MONITOR: - /* don't tell driver about this */ + if (!ieee80211_quiesce(sdata)) continue; - default: - break; - } if (!ieee80211_sdata_running(sdata)) continue; |