aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-12-11 14:38:41 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-01-03 06:59:58 -0500
commit4d76d21bd700fcf72a030ad75c71c816707039b8 (patch)
tree7481ffaf00acb623a272cdf35c612610d57fc825
parent2d4072a5470621c552f46d51cd54965aeb033893 (diff)
mac80211: assign VLAN channel contexts
Make AP_VLAN type interfaces track the AP master channel context so they have one assigned for the various lookups. Don't give them their own refcount etc. since they're just slaves to the AP master. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-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: