aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/key.c14
-rw-r--r--net/mac80211/key.h1
-rw-r--r--net/mac80211/pm.c115
-rw-r--r--net/mac80211/util.c26
5 files changed, 6 insertions, 154 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 68087975c717..bc3ea58985d5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -768,10 +768,6 @@ struct ieee80211_sub_if_data {
768 } debugfs; 768 } debugfs;
769#endif 769#endif
770 770
771#ifdef CONFIG_PM
772 struct ieee80211_bss_conf suspend_bss_conf;
773#endif
774
775 /* must be last, dynamically sized area in this! */ 771 /* must be last, dynamically sized area in this! */
776 struct ieee80211_vif vif; 772 struct ieee80211_vif vif;
777}; 773};
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index ef252eb58c36..df81b178c594 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -566,20 +566,6 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
566} 566}
567EXPORT_SYMBOL(ieee80211_iter_keys); 567EXPORT_SYMBOL(ieee80211_iter_keys);
568 568
569void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
570{
571 struct ieee80211_key *key;
572
573 ASSERT_RTNL();
574
575 mutex_lock(&sdata->local->key_mtx);
576
577 list_for_each_entry(key, &sdata->key_list, list)
578 ieee80211_key_disable_hw_accel(key);
579
580 mutex_unlock(&sdata->local->key_mtx);
581}
582
583void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) 569void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
584{ 570{
585 struct ieee80211_key *key, *tmp; 571 struct ieee80211_key *key, *tmp;
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 382dc44ed330..8b037307a586 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -143,7 +143,6 @@ void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
143 int idx); 143 int idx);
144void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); 144void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
145void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); 145void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
146void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
147 146
148#define key_mtx_dereference(local, ref) \ 147#define key_mtx_dereference(local, ref) \
149 rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) 148 rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx)))
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)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0f38f43ac62e..f5d4e326b0c9 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1534,11 +1534,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1534 BSS_CHANGED_IDLE | 1534 BSS_CHANGED_IDLE |
1535 BSS_CHANGED_TXPOWER; 1535 BSS_CHANGED_TXPOWER;
1536 1536
1537#ifdef CONFIG_PM
1538 if (local->resuming && !reconfig_due_to_wowlan)
1539 sdata->vif.bss_conf = sdata->suspend_bss_conf;
1540#endif
1541
1542 switch (sdata->vif.type) { 1537 switch (sdata->vif.type) {
1543 case NL80211_IFTYPE_STATION: 1538 case NL80211_IFTYPE_STATION:
1544 changed |= BSS_CHANGED_ASSOC | 1539 changed |= BSS_CHANGED_ASSOC |
@@ -1678,28 +1673,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1678 mb(); 1673 mb();
1679 local->resuming = false; 1674 local->resuming = false;
1680 1675
1681 list_for_each_entry(sdata, &local->interfaces, list) {
1682 switch(sdata->vif.type) {
1683 case NL80211_IFTYPE_STATION:
1684 ieee80211_sta_restart(sdata);
1685 break;
1686 case NL80211_IFTYPE_ADHOC:
1687 ieee80211_ibss_restart(sdata);
1688 break;
1689 case NL80211_IFTYPE_MESH_POINT:
1690 ieee80211_mesh_restart(sdata);
1691 break;
1692 default:
1693 break;
1694 }
1695 }
1696
1697 mod_timer(&local->sta_cleanup, jiffies + 1); 1676 mod_timer(&local->sta_cleanup, jiffies + 1);
1698
1699 mutex_lock(&local->sta_mtx);
1700 list_for_each_entry(sta, &local->sta_list, list)
1701 mesh_plink_restart(sta);
1702 mutex_unlock(&local->sta_mtx);
1703#else 1677#else
1704 WARN_ON(1); 1678 WARN_ON(1);
1705#endif 1679#endif