aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/pm.c
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2013-02-28 04:55:26 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-06 10:35:56 -0500
commit12e7f517029dad819c45eca9ca01fdb9ba57616b (patch)
tree38ca321ba277bc918ec58c2f3e2870867d355dec /net/mac80211/pm.c
parent8125696991194aacb1173b6e8196d19098b44e17 (diff)
mac80211: cleanup generic suspend/resume procedures
Since now we disconnect before suspend, various code which save connection state can now be removed from suspend and resume procedure. Cleanup on resume side is smaller as ieee80211_reconfig() is also used for H/W restart. Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/pm.c')
-rw-r--r--net/mac80211/pm.c115
1 files changed, 6 insertions, 109 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 4d105c7f26b7..b471a67f224d 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -6,32 +6,11 @@
6#include "driver-ops.h" 6#include "driver-ops.h"
7#include "led.h" 7#include "led.h"
8 8
9/* return value indicates whether the driver should be further notified */
10static void ieee80211_quiesce(struct ieee80211_sub_if_data *sdata)
11{
12 switch (sdata->vif.type) {
13 case NL80211_IFTYPE_STATION:
14 ieee80211_sta_quiesce(sdata);
15 break;
16 case NL80211_IFTYPE_ADHOC:
17 ieee80211_ibss_quiesce(sdata);
18 break;
19 case NL80211_IFTYPE_MESH_POINT:
20 ieee80211_mesh_quiesce(sdata);
21 break;
22 default:
23 break;
24 }
25
26 cancel_work_sync(&sdata->work);
27}
28
29int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) 9int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
30{ 10{
31 struct ieee80211_local *local = hw_to_local(hw); 11 struct ieee80211_local *local = hw_to_local(hw);
32 struct ieee80211_sub_if_data *sdata; 12 struct ieee80211_sub_if_data *sdata;
33 struct sta_info *sta; 13 struct sta_info *sta;
34 struct ieee80211_chanctx *ctx;
35 14
36 if (!local->open_count) 15 if (!local->open_count)
37 goto suspend; 16 goto suspend;
@@ -95,17 +74,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
95 WARN_ON(err != 1); 74 WARN_ON(err != 1);
96 return err; 75 return err;
97 } else { 76 } else {
98 list_for_each_entry(sdata, &local->interfaces, list)
99 if (ieee80211_sdata_running(sdata))
100 ieee80211_quiesce(sdata);
101 goto suspend; 77 goto suspend;
102 } 78 }
103 } 79 }
104 80
105 /* disable keys */
106 list_for_each_entry(sdata, &local->interfaces, list)
107 ieee80211_disable_keys(sdata);
108
109 /* tear down aggregation sessions and remove STAs */ 81 /* tear down aggregation sessions and remove STAs */
110 mutex_lock(&local->sta_mtx); 82 mutex_lock(&local->sta_mtx);
111 list_for_each_entry(sta, &local->sta_list, list) { 83 list_for_each_entry(sta, &local->sta_list, list) {
@@ -117,100 +89,25 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
117 WARN_ON(drv_sta_state(local, sta->sdata, sta, 89 WARN_ON(drv_sta_state(local, sta->sdata, sta,
118 state, state - 1)); 90 state, state - 1));
119 } 91 }
120
121 mesh_plink_quiesce(sta);
122 } 92 }
123 mutex_unlock(&local->sta_mtx); 93 mutex_unlock(&local->sta_mtx);
124 94
125 /* remove all interfaces */ 95 /* remove all interfaces */
126 list_for_each_entry(sdata, &local->interfaces, list) { 96 list_for_each_entry(sdata, &local->interfaces, list) {
127 static u8 zero_addr[ETH_ALEN] = {};
128 u32 changed = 0;
129
130 if (!ieee80211_sdata_running(sdata)) 97 if (!ieee80211_sdata_running(sdata))
131 continue; 98 continue;
132
133 switch (sdata->vif.type) {
134 case NL80211_IFTYPE_AP_VLAN:
135 case NL80211_IFTYPE_MONITOR:
136 /* skip these */
137 continue;
138 case NL80211_IFTYPE_STATION:
139 if (sdata->vif.bss_conf.assoc)
140 changed = BSS_CHANGED_ASSOC |
141 BSS_CHANGED_BSSID |
142 BSS_CHANGED_IDLE;
143 break;
144 case NL80211_IFTYPE_AP:
145 case NL80211_IFTYPE_ADHOC:
146 case NL80211_IFTYPE_MESH_POINT:
147 if (sdata->vif.bss_conf.enable_beacon)
148 changed = BSS_CHANGED_BEACON_ENABLED;
149 break;
150 default:
151 break;
152 }
153
154 ieee80211_quiesce(sdata);
155
156 sdata->suspend_bss_conf = sdata->vif.bss_conf;
157 memset(&sdata->vif.bss_conf, 0, sizeof(sdata->vif.bss_conf));
158 sdata->vif.bss_conf.idle = true;
159 if (sdata->suspend_bss_conf.bssid)
160 sdata->vif.bss_conf.bssid = zero_addr;
161
162 /* disable beaconing or remove association */
163 ieee80211_bss_info_change_notify(sdata, changed);
164
165 if (sdata->vif.type == NL80211_IFTYPE_AP &&
166 rcu_access_pointer(sdata->u.ap.beacon))
167 drv_stop_ap(local, sdata);
168
169 if (local->use_chanctx) {
170 struct ieee80211_chanctx_conf *conf;
171
172 mutex_lock(&local->chanctx_mtx);
173 conf = rcu_dereference_protected(
174 sdata->vif.chanctx_conf,
175 lockdep_is_held(&local->chanctx_mtx));
176 if (conf) {
177 ctx = container_of(conf,
178 struct ieee80211_chanctx,
179 conf);
180 drv_unassign_vif_chanctx(local, sdata, ctx);
181 }
182
183 mutex_unlock(&local->chanctx_mtx);
184 }
185 drv_remove_interface(local, sdata); 99 drv_remove_interface(local, sdata);
186 } 100 }
187 101
188 sdata = rtnl_dereference(local->monitor_sdata); 102 sdata = rtnl_dereference(local->monitor_sdata);
189 if (sdata) { 103 if (sdata)
190 if (local->use_chanctx) {
191 struct ieee80211_chanctx_conf *conf;
192
193 mutex_lock(&local->chanctx_mtx);
194 conf = rcu_dereference_protected(
195 sdata->vif.chanctx_conf,
196 lockdep_is_held(&local->chanctx_mtx));
197 if (conf) {
198 ctx = container_of(conf,
199 struct ieee80211_chanctx,
200 conf);
201 drv_unassign_vif_chanctx(local, sdata, ctx);
202 }
203
204 mutex_unlock(&local->chanctx_mtx);
205 }
206
207 drv_remove_interface(local, sdata); 104 drv_remove_interface(local, sdata);
208 }
209 105
210 mutex_lock(&local->chanctx_mtx); 106 /*
211 list_for_each_entry(ctx, &local->chanctx_list, list) 107 * We disconnected on all interfaces before suspend, all channel
212 drv_remove_chanctx(local, ctx); 108 * contexts should be released.
213 mutex_unlock(&local->chanctx_mtx); 109 */
110 WARN_ON(!list_empty(&local->chanctx_list));
214 111
215 /* stop hardware - this must stop RX */ 112 /* stop hardware - this must stop RX */
216 if (local->open_count) 113 if (local->open_count)