aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/chan.c38
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/iface.c9
3 files changed, 45 insertions, 3 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 53f03120db55..80e55527504b 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -4,6 +4,7 @@
4 4
5#include <linux/nl80211.h> 5#include <linux/nl80211.h>
6#include <linux/export.h> 6#include <linux/export.h>
7#include <linux/rtnetlink.h>
7#include <net/cfg80211.h> 8#include <net/cfg80211.h>
8#include "ieee80211_i.h" 9#include "ieee80211_i.h"
9#include "driver-ops.h" 10#include "driver-ops.h"
@@ -197,6 +198,15 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
197 198
198 ctx = container_of(conf, struct ieee80211_chanctx, conf); 199 ctx = container_of(conf, struct ieee80211_chanctx, conf);
199 200
201 if (sdata->vif.type == NL80211_IFTYPE_AP) {
202 struct ieee80211_sub_if_data *vlan;
203
204 /* for the VLAN list */
205 ASSERT_RTNL();
206 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
207 rcu_assign_pointer(vlan->vif.chanctx_conf, NULL);
208 }
209
200 ieee80211_unassign_vif_chanctx(sdata, ctx); 210 ieee80211_unassign_vif_chanctx(sdata, ctx);
201 if (ctx->refcount == 0) 211 if (ctx->refcount == 0)
202 ieee80211_free_chanctx(local, ctx); 212 ieee80211_free_chanctx(local, ctx);
@@ -316,6 +326,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
316 goto out; 326 goto out;
317 } 327 }
318 328
329 if (sdata->vif.type == NL80211_IFTYPE_AP) {
330 struct ieee80211_sub_if_data *vlan;
331
332 /* for the VLAN list */
333 ASSERT_RTNL();
334 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
335 rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf);
336 }
337
319 ieee80211_recalc_smps_chanctx(local, ctx); 338 ieee80211_recalc_smps_chanctx(local, ctx);
320 out: 339 out:
321 mutex_unlock(&local->chanctx_mtx); 340 mutex_unlock(&local->chanctx_mtx);
@@ -331,6 +350,25 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
331 mutex_unlock(&sdata->local->chanctx_mtx); 350 mutex_unlock(&sdata->local->chanctx_mtx);
332} 351}
333 352
353void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
354{
355 struct ieee80211_local *local = sdata->local;
356 struct ieee80211_sub_if_data *ap;
357 struct ieee80211_chanctx_conf *conf;
358
359 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
360 return;
361
362 ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
363
364 mutex_lock(&local->chanctx_mtx);
365
366 conf = rcu_dereference_protected(ap->vif.chanctx_conf,
367 lockdep_is_held(&local->chanctx_mtx));
368 rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
369 mutex_unlock(&local->chanctx_mtx);
370}
371
334void ieee80211_iter_chan_contexts_atomic( 372void ieee80211_iter_chan_contexts_atomic(
335 struct ieee80211_hw *hw, 373 struct ieee80211_hw *hw,
336 void (*iter)(struct ieee80211_hw *hw, 374 void (*iter)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 112bb6192399..28fc9875537c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1628,6 +1628,7 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
1628 const struct cfg80211_chan_def *chandef, 1628 const struct cfg80211_chan_def *chandef,
1629 enum ieee80211_chanctx_mode mode); 1629 enum ieee80211_chanctx_mode mode);
1630void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); 1630void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
1631void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
1631 1632
1632void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, 1633void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
1633 struct ieee80211_chanctx *chanctx); 1634 struct ieee80211_chanctx *chanctx);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 09a80b55cf5a..54fb7f9db564 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -586,11 +586,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
586 586
587 switch (sdata->vif.type) { 587 switch (sdata->vif.type) {
588 case NL80211_IFTYPE_AP_VLAN: 588 case NL80211_IFTYPE_AP_VLAN:
589 /* no need to tell driver, but set carrier */ 589 /* no need to tell driver, but set carrier and chanctx */
590 if (rtnl_dereference(sdata->bss->beacon)) 590 if (rtnl_dereference(sdata->bss->beacon)) {
591 ieee80211_vif_vlan_copy_chanctx(sdata);
591 netif_carrier_on(dev); 592 netif_carrier_on(dev);
592 else 593 } else {
593 netif_carrier_off(dev); 594 netif_carrier_off(dev);
595 }
594 break; 596 break;
595 case NL80211_IFTYPE_MONITOR: 597 case NL80211_IFTYPE_MONITOR:
596 if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { 598 if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
@@ -839,6 +841,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
839 switch (sdata->vif.type) { 841 switch (sdata->vif.type) {
840 case NL80211_IFTYPE_AP_VLAN: 842 case NL80211_IFTYPE_AP_VLAN:
841 list_del(&sdata->u.vlan.list); 843 list_del(&sdata->u.vlan.list);
844 rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
842 /* no need to tell driver */ 845 /* no need to tell driver */
843 break; 846 break;
844 case NL80211_IFTYPE_MONITOR: 847 case NL80211_IFTYPE_MONITOR: