aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h4
-rw-r--r--net/mac80211/chan.c49
-rw-r--r--net/mac80211/ieee80211_i.h4
3 files changed, 57 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index b7fb311e83f4..54e2add8429f 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -215,6 +215,9 @@ struct ieee80211_chanctx_conf {
* changed (currently only in P2P client mode, GO mode will be later)
* @BSS_CHANGED_DTIM_PERIOD: the DTIM period value was changed (set when
* it becomes valid, managed mode only)
+ * @BSS_CHANGED_BANDWIDTH: The bandwidth used by this interface changed,
+ * note that this is only called when it changes after the channel
+ * context had been assigned.
*/
enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0,
@@ -238,6 +241,7 @@ enum ieee80211_bss_change {
BSS_CHANGED_TXPOWER = 1<<18,
BSS_CHANGED_P2P_PS = 1<<19,
BSS_CHANGED_DTIM_PERIOD = 1<<20,
+ BSS_CHANGED_BANDWIDTH = 1<<21,
/* when adding here, make sure to change ieee80211_reconfig */
};
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,
return ret;
}
+int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
+ const struct cfg80211_chan_def *chandef,
+ u32 *changed)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_chanctx_conf *conf;
+ struct ieee80211_chanctx *ctx;
+ int ret;
+
+ if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
+ IEEE80211_CHAN_DISABLED))
+ return -EINVAL;
+
+ mutex_lock(&local->chanctx_mtx);
+ if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
+ ret = 0;
+ goto out;
+ }
+
+ if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
+ sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+ lockdep_is_held(&local->chanctx_mtx));
+ if (!conf) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ctx = container_of(conf, struct ieee80211_chanctx, conf);
+ if (!cfg80211_chandef_compatible(&conf->def, chandef)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ sdata->vif.bss_conf.chandef = *chandef;
+
+ ieee80211_recalc_chanctx_chantype(local, ctx);
+
+ *changed |= BSS_CHANGED_BANDWIDTH;
+ ret = 0;
+ out:
+ mutex_unlock(&local->chanctx_mtx);
+ return ret;
+}
+
void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
{
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
ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
const struct cfg80211_chan_def *chandef,
enum ieee80211_chanctx_mode mode);
+int __must_check
+ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
+ const struct cfg80211_chan_def *chandef,
+ u32 *changed);
void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,