aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/pm.c44
-rw-r--r--net/mac80211/util.c15
2 files changed, 56 insertions, 3 deletions
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 0f1c434638bc..79a48f37d409 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -33,6 +33,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
33 struct ieee80211_local *local = hw_to_local(hw); 33 struct ieee80211_local *local = hw_to_local(hw);
34 struct ieee80211_sub_if_data *sdata; 34 struct ieee80211_sub_if_data *sdata;
35 struct sta_info *sta; 35 struct sta_info *sta;
36 struct ieee80211_chanctx *ctx;
36 37
37 if (!local->open_count) 38 if (!local->open_count)
38 goto suspend; 39 goto suspend;
@@ -139,14 +140,51 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
139 rcu_access_pointer(sdata->u.ap.beacon)) 140 rcu_access_pointer(sdata->u.ap.beacon))
140 drv_stop_ap(local, sdata); 141 drv_stop_ap(local, sdata);
141 142
142 /* the interface is leaving the channel and is removed */ 143 if (local->use_chanctx) {
143 ieee80211_vif_release_channel(sdata); 144 struct ieee80211_chanctx_conf *conf;
145
146 mutex_lock(&local->chanctx_mtx);
147 conf = rcu_dereference_protected(
148 sdata->vif.chanctx_conf,
149 lockdep_is_held(&local->chanctx_mtx));
150 if (conf) {
151 ctx = container_of(conf,
152 struct ieee80211_chanctx,
153 conf);
154 drv_unassign_vif_chanctx(local, sdata, ctx);
155 }
156
157 mutex_unlock(&local->chanctx_mtx);
158 }
144 drv_remove_interface(local, sdata); 159 drv_remove_interface(local, sdata);
145 } 160 }
146 161
147 sdata = rtnl_dereference(local->monitor_sdata); 162 sdata = rtnl_dereference(local->monitor_sdata);
148 if (sdata) 163 if (sdata) {
164 if (local->use_chanctx) {
165 struct ieee80211_chanctx_conf *conf;
166
167 mutex_lock(&local->chanctx_mtx);
168 conf = rcu_dereference_protected(
169 sdata->vif.chanctx_conf,
170 lockdep_is_held(&local->chanctx_mtx));
171 if (conf) {
172 ctx = container_of(conf,
173 struct ieee80211_chanctx,
174 conf);
175 drv_unassign_vif_chanctx(local, sdata, ctx);
176 }
177
178 mutex_unlock(&local->chanctx_mtx);
179 }
180
149 drv_remove_interface(local, sdata); 181 drv_remove_interface(local, sdata);
182 }
183
184 mutex_lock(&local->chanctx_mtx);
185 list_for_each_entry(ctx, &local->chanctx_list, list)
186 drv_remove_chanctx(local, ctx);
187 mutex_unlock(&local->chanctx_mtx);
150 188
151 /* stop hardware - this must stop RX */ 189 /* stop hardware - this must stop RX */
152 if (local->open_count) 190 if (local->open_count)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7fb55bf6561e..2f08a7e09b7e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1441,6 +1441,21 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1441 mutex_unlock(&local->chanctx_mtx); 1441 mutex_unlock(&local->chanctx_mtx);
1442 } 1442 }
1443 1443
1444 sdata = rtnl_dereference(local->monitor_sdata);
1445 if (sdata && local->use_chanctx && ieee80211_sdata_running(sdata)) {
1446 struct ieee80211_chanctx_conf *ctx_conf;
1447
1448 mutex_lock(&local->chanctx_mtx);
1449 ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
1450 lockdep_is_held(&local->chanctx_mtx));
1451 if (ctx_conf) {
1452 ctx = container_of(ctx_conf, struct ieee80211_chanctx,
1453 conf);
1454 drv_assign_vif_chanctx(local, sdata, ctx);
1455 }
1456 mutex_unlock(&local->chanctx_mtx);
1457 }
1458
1444 /* add STAs back */ 1459 /* add STAs back */
1445 mutex_lock(&local->sta_mtx); 1460 mutex_lock(&local->sta_mtx);
1446 list_for_each_entry(sta, &local->sta_list, list) { 1461 list_for_each_entry(sta, &local->sta_list, list) {