aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r--net/mac80211/pm.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index e37355193ed1..730778a2c90c 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -6,7 +6,7 @@
6#include "driver-ops.h" 6#include "driver-ops.h"
7#include "led.h" 7#include "led.h"
8 8
9int __ieee80211_suspend(struct ieee80211_hw *hw) 9int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
10{ 10{
11 struct ieee80211_local *local = hw_to_local(hw); 11 struct ieee80211_local *local = hw_to_local(hw);
12 struct ieee80211_sub_if_data *sdata; 12 struct ieee80211_sub_if_data *sdata;
@@ -14,12 +14,23 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
14 14
15 ieee80211_scan_cancel(local); 15 ieee80211_scan_cancel(local);
16 16
17 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
18 mutex_lock(&local->sta_mtx);
19 list_for_each_entry(sta, &local->sta_list, list) {
20 set_sta_flags(sta, WLAN_STA_BLOCK_BA);
21 ieee80211_sta_tear_down_BA_sessions(sta, true);
22 }
23 mutex_unlock(&local->sta_mtx);
24 }
25
17 ieee80211_stop_queues_by_reason(hw, 26 ieee80211_stop_queues_by_reason(hw,
18 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 27 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
19 28
20 /* flush out all packets */ 29 /* flush out all packets */
21 synchronize_net(); 30 synchronize_net();
22 31
32 drv_flush(local, false);
33
23 local->quiescing = true; 34 local->quiescing = true;
24 /* make quiescing visible to timers everywhere */ 35 /* make quiescing visible to timers everywhere */
25 mb(); 36 mb();
@@ -36,6 +47,16 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
36 cancel_work_sync(&local->dynamic_ps_enable_work); 47 cancel_work_sync(&local->dynamic_ps_enable_work);
37 del_timer_sync(&local->dynamic_ps_timer); 48 del_timer_sync(&local->dynamic_ps_timer);
38 49
50 local->wowlan = wowlan && local->open_count;
51 if (local->wowlan) {
52 int err = drv_suspend(local, wowlan);
53 if (err) {
54 local->quiescing = false;
55 return err;
56 }
57 goto suspend;
58 }
59
39 /* disable keys */ 60 /* disable keys */
40 list_for_each_entry(sdata, &local->interfaces, list) 61 list_for_each_entry(sdata, &local->interfaces, list)
41 ieee80211_disable_keys(sdata); 62 ieee80211_disable_keys(sdata);
@@ -43,11 +64,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
43 /* tear down aggregation sessions and remove STAs */ 64 /* tear down aggregation sessions and remove STAs */
44 mutex_lock(&local->sta_mtx); 65 mutex_lock(&local->sta_mtx);
45 list_for_each_entry(sta, &local->sta_list, list) { 66 list_for_each_entry(sta, &local->sta_list, list) {
46 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
47 set_sta_flags(sta, WLAN_STA_BLOCK_BA);
48 ieee80211_sta_tear_down_BA_sessions(sta, true);
49 }
50
51 if (sta->uploaded) { 67 if (sta->uploaded) {
52 sdata = sta->sdata; 68 sdata = sta->sdata;
53 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 69 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -98,6 +114,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
98 if (local->open_count) 114 if (local->open_count)
99 ieee80211_stop_device(local); 115 ieee80211_stop_device(local);
100 116
117 suspend:
101 local->suspended = true; 118 local->suspended = true;
102 /* need suspended to be visible before quiescing is false */ 119 /* need suspended to be visible before quiescing is false */
103 barrier(); 120 barrier();