diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/chan.c | 49 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 |
2 files changed, 53 insertions, 0 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 78dbb371f16e..78c0d90dd641 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -375,6 +375,55 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
375 | return ret; | 375 | return ret; |
376 | } | 376 | } |
377 | 377 | ||
378 | int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | ||
379 | const struct cfg80211_chan_def *chandef, | ||
380 | u32 *changed) | ||
381 | { | ||
382 | struct ieee80211_local *local = sdata->local; | ||
383 | struct ieee80211_chanctx_conf *conf; | ||
384 | struct ieee80211_chanctx *ctx; | ||
385 | int ret; | ||
386 | |||
387 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, | ||
388 | IEEE80211_CHAN_DISABLED)) | ||
389 | return -EINVAL; | ||
390 | |||
391 | mutex_lock(&local->chanctx_mtx); | ||
392 | if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) { | ||
393 | ret = 0; | ||
394 | goto out; | ||
395 | } | ||
396 | |||
397 | if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT || | ||
398 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) { | ||
399 | ret = -EINVAL; | ||
400 | goto out; | ||
401 | } | ||
402 | |||
403 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
404 | lockdep_is_held(&local->chanctx_mtx)); | ||
405 | if (!conf) { | ||
406 | ret = -EINVAL; | ||
407 | goto out; | ||
408 | } | ||
409 | |||
410 | ctx = container_of(conf, struct ieee80211_chanctx, conf); | ||
411 | if (!cfg80211_chandef_compatible(&conf->def, chandef)) { | ||
412 | ret = -EINVAL; | ||
413 | goto out; | ||
414 | } | ||
415 | |||
416 | sdata->vif.bss_conf.chandef = *chandef; | ||
417 | |||
418 | ieee80211_recalc_chanctx_chantype(local, ctx); | ||
419 | |||
420 | *changed |= BSS_CHANGED_BANDWIDTH; | ||
421 | ret = 0; | ||
422 | out: | ||
423 | mutex_unlock(&local->chanctx_mtx); | ||
424 | return ret; | ||
425 | } | ||
426 | |||
378 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | 427 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) |
379 | { | 428 | { |
380 | WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); | 429 | WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 892bac64a189..d1074442f1b5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1613,6 +1613,10 @@ int __must_check | |||
1613 | ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | 1613 | ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, |
1614 | const struct cfg80211_chan_def *chandef, | 1614 | const struct cfg80211_chan_def *chandef, |
1615 | enum ieee80211_chanctx_mode mode); | 1615 | enum ieee80211_chanctx_mode mode); |
1616 | int __must_check | ||
1617 | ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | ||
1618 | const struct cfg80211_chan_def *chandef, | ||
1619 | u32 *changed); | ||
1616 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); | 1620 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); |
1617 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); | 1621 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); |
1618 | void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, | 1622 | void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, |