aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-07 15:37:29 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-15 03:41:36 -0500
commit2c9b735982ee8a2d34e7eeb3e26b683f81872fdb (patch)
treef2f0f0b741aa0b1ffaa2a95c0533d1eeba745868 /net/mac80211
parentf2d9330ee820b01e2b1caf46370bc7963d259908 (diff)
mac80211: add ieee80211_vif_change_bandwidth
For HT and VHT the current bandwidth can change, add the function ieee80211_vif_change_bandwidth() to take care of this. It returns a failure if the new bandwidth isn't compatible with the existing channel context, the caller has to handle that. When it happens, also inform the driver that the bandwidth changed for this virtual interface (no drivers would actually care today though.) Changing to/from HT/VHT isn't allowed though. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/chan.c49
-rw-r--r--net/mac80211/ieee80211_i.h4
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
378int 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
378void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) 427void 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
1613ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, 1613ieee80211_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);
1616int __must_check
1617ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
1618 const struct cfg80211_chan_def *chandef,
1619 u32 *changed);
1616void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); 1620void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
1617void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); 1621void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
1618void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, 1622void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,