diff options
Diffstat (limited to 'net/mac80211/chan.c')
| -rw-r--r-- | net/mac80211/chan.c | 38 |
1 files changed, 38 insertions, 0 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 | ||
| 353 | void 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 | |||
| 334 | void ieee80211_iter_chan_contexts_atomic( | 372 | void 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, |
