aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-11-09 05:39:59 -0500
committerJohannes Berg <johannes.berg@intel.com>2012-11-26 06:42:59 -0500
commit4bf88530be971bf95a7830ca61b4120980bf4347 (patch)
tree405d426806cb76551d09f427dafeeee79dac0dea /net
parent3d9d1d6656a73ea8407734cfb00b81d14ef62d4b (diff)
mac80211: convert to channel definition struct
Convert mac80211 (and where necessary, some drivers a little bit) to the new channel definition struct. This will allow extending mac80211 for VHT, which is currently restricted to channel contexts since there are no drivers using that which makes it easier. As I also don't care about VHT for drivers not using the channel context API, I won't convert the previous API to VHT support. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c41
-rw-r--r--net/mac80211/chan.c128
-rw-r--r--net/mac80211/debugfs_netdev.c2
-rw-r--r--net/mac80211/ibss.c34
-rw-r--r--net/mac80211/ieee80211_i.h18
-rw-r--r--net/mac80211/iface.c5
-rw-r--r--net/mac80211/main.c21
-rw-r--r--net/mac80211/mesh.c28
-rw-r--r--net/mac80211/mesh_plink.c19
-rw-r--r--net/mac80211/mlme.c26
-rw-r--r--net/mac80211/rate.c5
-rw-r--r--net/mac80211/rate.h2
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/sta_info.h4
-rw-r--r--net/mac80211/trace.h23
-rw-r--r--net/mac80211/tx.c20
-rw-r--r--net/mac80211/util.c45
17 files changed, 189 insertions, 234 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7136b945798e..b9702d16d608 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -615,7 +615,7 @@ do_survey:
615 rcu_read_lock(); 615 rcu_read_lock();
616 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 616 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
617 if (chanctx_conf) 617 if (chanctx_conf)
618 channel = chanctx_conf->channel; 618 channel = chanctx_conf->def.chan;
619 else 619 else
620 channel = NULL; 620 channel = NULL;
621 rcu_read_unlock(); 621 rcu_read_unlock();
@@ -739,13 +739,9 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
739{ 739{
740 struct ieee80211_local *local = wiphy_priv(wiphy); 740 struct ieee80211_local *local = wiphy_priv(wiphy);
741 struct ieee80211_sub_if_data *sdata; 741 struct ieee80211_sub_if_data *sdata;
742 enum nl80211_channel_type channel_type;
743 int ret = 0; 742 int ret = 0;
744 743
745 channel_type = cfg80211_get_chandef_type(chandef); 744 if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
746
747 if (local->monitor_channel == chandef->chan &&
748 local->monitor_channel_type == channel_type)
749 return 0; 745 return 0;
750 746
751 mutex_lock(&local->iflist_mtx); 747 mutex_lock(&local->iflist_mtx);
@@ -755,20 +751,17 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
755 lockdep_is_held(&local->iflist_mtx)); 751 lockdep_is_held(&local->iflist_mtx));
756 if (sdata) { 752 if (sdata) {
757 ieee80211_vif_release_channel(sdata); 753 ieee80211_vif_release_channel(sdata);
758 ret = ieee80211_vif_use_channel( 754 ret = ieee80211_vif_use_channel(sdata, chandef,
759 sdata, chandef->chan, channel_type,
760 IEEE80211_CHANCTX_EXCLUSIVE); 755 IEEE80211_CHANCTX_EXCLUSIVE);
761 } 756 }
762 } else if (local->open_count == local->monitors) { 757 } else if (local->open_count == local->monitors) {
763 local->_oper_channel = chandef->chan; 758 local->_oper_channel = chandef->chan;
764 local->_oper_channel_type = channel_type; 759 local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
765 ieee80211_hw_config(local, 0); 760 ieee80211_hw_config(local, 0);
766 } 761 }
767 762
768 if (ret == 0) { 763 if (ret == 0)
769 local->monitor_channel = chandef->chan; 764 local->monitor_chandef = *chandef;
770 local->monitor_channel_type = channel_type;
771 }
772 mutex_unlock(&local->iflist_mtx); 765 mutex_unlock(&local->iflist_mtx);
773 766
774 return ret; 767 return ret;
@@ -890,10 +883,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
890 sdata->smps_mode = IEEE80211_SMPS_OFF; 883 sdata->smps_mode = IEEE80211_SMPS_OFF;
891 sdata->needed_rx_chains = sdata->local->rx_chains; 884 sdata->needed_rx_chains = sdata->local->rx_chains;
892 885
893 err = ieee80211_vif_use_channel( 886 err = ieee80211_vif_use_channel(sdata, &params->chandef,
894 sdata, params->chandef.chan, 887 IEEE80211_CHANCTX_SHARED);
895 cfg80211_get_chandef_type(&params->chandef),
896 IEEE80211_CHANCTX_SHARED);
897 if (err) 888 if (err)
898 return err; 889 return err;
899 890
@@ -1710,10 +1701,8 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
1710 sdata->smps_mode = IEEE80211_SMPS_OFF; 1701 sdata->smps_mode = IEEE80211_SMPS_OFF;
1711 sdata->needed_rx_chains = sdata->local->rx_chains; 1702 sdata->needed_rx_chains = sdata->local->rx_chains;
1712 1703
1713 err = ieee80211_vif_use_channel( 1704 err = ieee80211_vif_use_channel(sdata, &setup->chandef,
1714 sdata, setup->chandef.chan, 1705 IEEE80211_CHANCTX_SHARED);
1715 cfg80211_get_chandef_type(&setup->chandef),
1716 IEEE80211_CHANCTX_SHARED);
1717 if (err) 1706 if (err)
1718 return err; 1707 return err;
1719 1708
@@ -2133,7 +2122,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
2133 * the new value until we associate. 2122 * the new value until we associate.
2134 */ 2123 */
2135 if (!sdata->u.mgd.associated || 2124 if (!sdata->u.mgd.associated ||
2136 sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) 2125 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
2137 return 0; 2126 return 0;
2138 2127
2139 ap = sdata->u.mgd.associated->bssid; 2128 ap = sdata->u.mgd.associated->bssid;
@@ -2589,7 +2578,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2589 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 2578 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
2590 2579
2591 if (chanctx_conf) 2580 if (chanctx_conf)
2592 need_offchan = chan != chanctx_conf->channel; 2581 need_offchan = chan != chanctx_conf->def.chan;
2593 else 2582 else
2594 need_offchan = true; 2583 need_offchan = true;
2595 rcu_read_unlock(); 2584 rcu_read_unlock();
@@ -3057,7 +3046,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
3057 rcu_read_unlock(); 3046 rcu_read_unlock();
3058 return -EINVAL; 3047 return -EINVAL;
3059 } 3048 }
3060 band = chanctx_conf->channel->band; 3049 band = chanctx_conf->def.chan->band;
3061 sta = sta_info_get(sdata, peer); 3050 sta = sta_info_get(sdata, peer);
3062 if (sta) { 3051 if (sta) {
3063 qos = test_sta_flag(sta, WLAN_STA_WME); 3052 qos = test_sta_flag(sta, WLAN_STA_WME);
@@ -3125,9 +3114,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
3125 rcu_read_lock(); 3114 rcu_read_lock();
3126 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 3115 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
3127 if (chanctx_conf) { 3116 if (chanctx_conf) {
3128 cfg80211_chandef_create(chandef, 3117 *chandef = chanctx_conf->def;
3129 chanctx_conf->channel,
3130 chanctx_conf->channel_type);
3131 ret = 0; 3118 ret = 0;
3132 } 3119 }
3133 rcu_read_unlock(); 3120 rcu_read_unlock();
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index a2b06d40aebf..53f03120db55 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -8,93 +8,47 @@
8#include "ieee80211_i.h" 8#include "ieee80211_i.h"
9#include "driver-ops.h" 9#include "driver-ops.h"
10 10
11static bool 11static void ieee80211_change_chandef(struct ieee80211_local *local,
12ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, 12 struct ieee80211_chanctx *ctx,
13 enum nl80211_channel_type chantype2, 13 const struct cfg80211_chan_def *chandef)
14 enum nl80211_channel_type *compat)
15{ 14{
16 /* 15 if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
17 * start out with chantype1 being the result,
18 * overwriting later if needed
19 */
20 if (compat)
21 *compat = chantype1;
22
23 switch (chantype1) {
24 case NL80211_CHAN_NO_HT:
25 if (compat)
26 *compat = chantype2;
27 break;
28 case NL80211_CHAN_HT20:
29 /*
30 * allow any change that doesn't go to no-HT
31 * (if it already is no-HT no change is needed)
32 */
33 if (chantype2 == NL80211_CHAN_NO_HT)
34 break;
35 if (compat)
36 *compat = chantype2;
37 break;
38 case NL80211_CHAN_HT40PLUS:
39 case NL80211_CHAN_HT40MINUS:
40 /* allow smaller bandwidth and same */
41 if (chantype2 == NL80211_CHAN_NO_HT)
42 break;
43 if (chantype2 == NL80211_CHAN_HT20)
44 break;
45 if (chantype2 == chantype1)
46 break;
47 return false;
48 }
49
50 return true;
51}
52
53static void ieee80211_change_chantype(struct ieee80211_local *local,
54 struct ieee80211_chanctx *ctx,
55 enum nl80211_channel_type chantype)
56{
57 if (chantype == ctx->conf.channel_type)
58 return; 16 return;
59 17
60 ctx->conf.channel_type = chantype; 18 WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
61 drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE); 19
20 ctx->conf.def = *chandef;
21 drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
62 22
63 if (!local->use_chanctx) { 23 if (!local->use_chanctx) {
64 local->_oper_channel_type = chantype; 24 local->_oper_channel_type = cfg80211_get_chandef_type(chandef);
65 ieee80211_hw_config(local, 0); 25 ieee80211_hw_config(local, 0);
66 } 26 }
67} 27}
68 28
69static struct ieee80211_chanctx * 29static struct ieee80211_chanctx *
70ieee80211_find_chanctx(struct ieee80211_local *local, 30ieee80211_find_chanctx(struct ieee80211_local *local,
71 struct ieee80211_channel *channel, 31 const struct cfg80211_chan_def *chandef,
72 enum nl80211_channel_type channel_type,
73 enum ieee80211_chanctx_mode mode) 32 enum ieee80211_chanctx_mode mode)
74{ 33{
75 struct ieee80211_chanctx *ctx; 34 struct ieee80211_chanctx *ctx;
76 enum nl80211_channel_type compat_type;
77 35
78 lockdep_assert_held(&local->chanctx_mtx); 36 lockdep_assert_held(&local->chanctx_mtx);
79 37
80 if (mode == IEEE80211_CHANCTX_EXCLUSIVE) 38 if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
81 return NULL; 39 return NULL;
82 if (WARN_ON(!channel))
83 return NULL;
84 40
85 list_for_each_entry(ctx, &local->chanctx_list, list) { 41 list_for_each_entry(ctx, &local->chanctx_list, list) {
86 compat_type = ctx->conf.channel_type; 42 const struct cfg80211_chan_def *compat;
87 43
88 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) 44 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
89 continue; 45 continue;
90 if (ctx->conf.channel != channel) 46
91 continue; 47 compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
92 if (!ieee80211_channel_types_are_compatible(ctx->conf.channel_type, 48 if (!compat)
93 channel_type,
94 &compat_type))
95 continue; 49 continue;
96 50
97 ieee80211_change_chantype(local, ctx, compat_type); 51 ieee80211_change_chandef(local, ctx, compat);
98 52
99 return ctx; 53 return ctx;
100 } 54 }
@@ -104,8 +58,7 @@ ieee80211_find_chanctx(struct ieee80211_local *local,
104 58
105static struct ieee80211_chanctx * 59static struct ieee80211_chanctx *
106ieee80211_new_chanctx(struct ieee80211_local *local, 60ieee80211_new_chanctx(struct ieee80211_local *local,
107 struct ieee80211_channel *channel, 61 const struct cfg80211_chan_def *chandef,
108 enum nl80211_channel_type channel_type,
109 enum ieee80211_chanctx_mode mode) 62 enum ieee80211_chanctx_mode mode)
110{ 63{
111 struct ieee80211_chanctx *ctx; 64 struct ieee80211_chanctx *ctx;
@@ -117,15 +70,15 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
117 if (!ctx) 70 if (!ctx)
118 return ERR_PTR(-ENOMEM); 71 return ERR_PTR(-ENOMEM);
119 72
120 ctx->conf.channel = channel; 73 ctx->conf.def = *chandef;
121 ctx->conf.channel_type = channel_type;
122 ctx->conf.rx_chains_static = 1; 74 ctx->conf.rx_chains_static = 1;
123 ctx->conf.rx_chains_dynamic = 1; 75 ctx->conf.rx_chains_dynamic = 1;
124 ctx->mode = mode; 76 ctx->mode = mode;
125 77
126 if (!local->use_chanctx) { 78 if (!local->use_chanctx) {
127 local->_oper_channel_type = channel_type; 79 local->_oper_channel_type =
128 local->_oper_channel = channel; 80 cfg80211_get_chandef_type(chandef);
81 local->_oper_channel = chandef->chan;
129 ieee80211_hw_config(local, 0); 82 ieee80211_hw_config(local, 0);
130 } else { 83 } else {
131 err = drv_add_chanctx(local, ctx); 84 err = drv_add_chanctx(local, ctx);
@@ -178,41 +131,37 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
178 return 0; 131 return 0;
179} 132}
180 133
181static enum nl80211_channel_type 134static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
182ieee80211_calc_chantype(struct ieee80211_local *local, 135 struct ieee80211_chanctx *ctx)
183 struct ieee80211_chanctx *ctx)
184{ 136{
185 struct ieee80211_chanctx_conf *conf = &ctx->conf; 137 struct ieee80211_chanctx_conf *conf = &ctx->conf;
186 struct ieee80211_sub_if_data *sdata; 138 struct ieee80211_sub_if_data *sdata;
187 enum nl80211_channel_type result = NL80211_CHAN_NO_HT; 139 const struct cfg80211_chan_def *compat = NULL;
188 140
189 lockdep_assert_held(&local->chanctx_mtx); 141 lockdep_assert_held(&local->chanctx_mtx);
190 142
191 rcu_read_lock(); 143 rcu_read_lock();
192 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 144 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
145
193 if (!ieee80211_sdata_running(sdata)) 146 if (!ieee80211_sdata_running(sdata))
194 continue; 147 continue;
195 if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) 148 if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
196 continue; 149 continue;
197 150
198 WARN_ON_ONCE(!ieee80211_channel_types_are_compatible( 151 if (!compat)
199 sdata->vif.bss_conf.channel_type, 152 compat = &sdata->vif.bss_conf.chandef;
200 result, &result)); 153
154 compat = cfg80211_chandef_compatible(
155 &sdata->vif.bss_conf.chandef, compat);
156 if (!compat)
157 break;
201 } 158 }
202 rcu_read_unlock(); 159 rcu_read_unlock();
203 160
204 return result; 161 if (WARN_ON_ONCE(!compat))
205} 162 return;
206
207static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
208 struct ieee80211_chanctx *ctx)
209{
210 enum nl80211_channel_type chantype;
211
212 lockdep_assert_held(&local->chanctx_mtx);
213 163
214 chantype = ieee80211_calc_chantype(local, ctx); 164 ieee80211_change_chandef(local, ctx, compat);
215 ieee80211_change_chantype(local, ctx, chantype);
216} 165}
217 166
218static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, 167static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
@@ -337,8 +286,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
337} 286}
338 287
339int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, 288int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
340 struct ieee80211_channel *channel, 289 const struct cfg80211_chan_def *chandef,
341 enum nl80211_channel_type channel_type,
342 enum ieee80211_chanctx_mode mode) 290 enum ieee80211_chanctx_mode mode)
343{ 291{
344 struct ieee80211_local *local = sdata->local; 292 struct ieee80211_local *local = sdata->local;
@@ -350,15 +298,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
350 mutex_lock(&local->chanctx_mtx); 298 mutex_lock(&local->chanctx_mtx);
351 __ieee80211_vif_release_channel(sdata); 299 __ieee80211_vif_release_channel(sdata);
352 300
353 ctx = ieee80211_find_chanctx(local, channel, channel_type, mode); 301 ctx = ieee80211_find_chanctx(local, chandef, mode);
354 if (!ctx) 302 if (!ctx)
355 ctx = ieee80211_new_chanctx(local, channel, channel_type, mode); 303 ctx = ieee80211_new_chanctx(local, chandef, mode);
356 if (IS_ERR(ctx)) { 304 if (IS_ERR(ctx)) {
357 ret = PTR_ERR(ctx); 305 ret = PTR_ERR(ctx);
358 goto out; 306 goto out;
359 } 307 }
360 308
361 sdata->vif.bss_conf.channel_type = channel_type; 309 sdata->vif.bss_conf.chandef = *chandef;
362 310
363 ret = ieee80211_assign_vif_chanctx(sdata, ctx); 311 ret = ieee80211_assign_vif_chanctx(sdata, ctx);
364 if (ret) { 312 if (ret) {
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ba9bd0ef119a..cbde5cc49a40 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -168,7 +168,6 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
168 168
169IEEE80211_IF_FILE(flags, flags, HEX); 169IEEE80211_IF_FILE(flags, flags, HEX);
170IEEE80211_IF_FILE(state, state, LHEX); 170IEEE80211_IF_FILE(state, state, LHEX);
171IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
172IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC); 171IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC);
173IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC); 172IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC);
174IEEE80211_IF_FILE(user_power_level, user_power_level, DEC); 173IEEE80211_IF_FILE(user_power_level, user_power_level, DEC);
@@ -632,7 +631,6 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
632 631
633 DEBUGFS_ADD(flags); 632 DEBUGFS_ADD(flags);
634 DEBUGFS_ADD(state); 633 DEBUGFS_ADD(state);
635 DEBUGFS_ADD(channel_type);
636 DEBUGFS_ADD(txpower); 634 DEBUGFS_ADD(txpower);
637 DEBUGFS_ADD(user_power_level); 635 DEBUGFS_ADD(user_power_level);
638 DEBUGFS_ADD(ap_power_level); 636 DEBUGFS_ADD(ap_power_level);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 5648bbed240b..11a6a1bde2fd 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -52,7 +52,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
52 u32 bss_change; 52 u32 bss_change;
53 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 53 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
54 struct cfg80211_chan_def chandef; 54 struct cfg80211_chan_def chandef;
55 enum nl80211_channel_type chan_type;
56 55
57 lockdep_assert_held(&ifibss->mtx); 56 lockdep_assert_held(&ifibss->mtx);
58 57
@@ -80,13 +79,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
80 79
81 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; 80 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
82 81
83 chan_type = ifibss->channel_type; 82 cfg80211_chandef_create(&chandef, chan, ifibss->channel_type);
84 cfg80211_chandef_create(&chandef, chan, chan_type); 83 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
85 if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) 84 chandef.width = NL80211_CHAN_WIDTH_20;
86 chan_type = NL80211_CHAN_HT20; 85 chandef.center_freq1 = chan->center_freq;
86 }
87 87
88 ieee80211_vif_release_channel(sdata); 88 ieee80211_vif_release_channel(sdata);
89 if (ieee80211_vif_use_channel(sdata, chan, chan_type, 89 if (ieee80211_vif_use_channel(sdata, &chandef,
90 ifibss->fixed_channel ? 90 ifibss->fixed_channel ?
91 IEEE80211_CHANCTX_SHARED : 91 IEEE80211_CHANCTX_SHARED :
92 IEEE80211_CHANCTX_EXCLUSIVE)) { 92 IEEE80211_CHANCTX_EXCLUSIVE)) {
@@ -160,7 +160,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
160 ifibss->ie, ifibss->ie_len); 160 ifibss->ie, ifibss->ie_len);
161 161
162 /* add HT capability and information IEs */ 162 /* add HT capability and information IEs */
163 if (chan_type != NL80211_CHAN_NO_HT && 163 if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
164 sband->ht_cap.ht_supported) { 164 sband->ht_cap.ht_supported) {
165 pos = skb_put(skb, 4 + 165 pos = skb_put(skb, 4 +
166 sizeof(struct ieee80211_ht_cap) + 166 sizeof(struct ieee80211_ht_cap) +
@@ -173,7 +173,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
173 * keep them at 0 173 * keep them at 0
174 */ 174 */
175 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, 175 pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap,
176 chan, chan_type, 0); 176 &chandef, 0);
177 } 177 }
178 178
179 if (local->hw.queues >= IEEE80211_NUM_ACS) { 179 if (local->hw.queues >= IEEE80211_NUM_ACS) {
@@ -329,7 +329,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
329 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 329 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
330 if (WARN_ON_ONCE(!chanctx_conf)) 330 if (WARN_ON_ONCE(!chanctx_conf))
331 return NULL; 331 return NULL;
332 band = chanctx_conf->channel->band; 332 band = chanctx_conf->def.chan->band;
333 rcu_read_unlock(); 333 rcu_read_unlock();
334 334
335 sta = sta_info_alloc(sdata, addr, GFP_KERNEL); 335 sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
@@ -478,9 +478,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
478 sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { 478 sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) {
479 /* we both use HT */ 479 /* we both use HT */
480 struct ieee80211_sta_ht_cap sta_ht_cap_new; 480 struct ieee80211_sta_ht_cap sta_ht_cap_new;
481 enum nl80211_channel_type channel_type = 481 struct cfg80211_chan_def chandef;
482 ieee80211_ht_oper_to_channel_type( 482
483 elems->ht_operation); 483 ieee80211_ht_oper_to_chandef(channel,
484 elems->ht_operation,
485 &chandef);
484 486
485 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, 487 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
486 elems->ht_cap_elem, 488 elems->ht_cap_elem,
@@ -490,9 +492,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
490 * fall back to HT20 if we don't use or use 492 * fall back to HT20 if we don't use or use
491 * the other extension channel 493 * the other extension channel
492 */ 494 */
493 if (!(channel_type == NL80211_CHAN_HT40MINUS || 495 if (chandef.width != NL80211_CHAN_WIDTH_40 ||
494 channel_type == NL80211_CHAN_HT40PLUS) || 496 cfg80211_get_chandef_type(&chandef) !=
495 channel_type != sdata->u.ibss.channel_type) 497 sdata->u.ibss.channel_type)
496 sta_ht_cap_new.cap &= 498 sta_ht_cap_new.cap &=
497 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; 499 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
498 500
@@ -616,7 +618,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
616 rcu_read_unlock(); 618 rcu_read_unlock();
617 return; 619 return;
618 } 620 }
619 band = chanctx_conf->channel->band; 621 band = chanctx_conf->def.chan->band;
620 rcu_read_unlock(); 622 rcu_read_unlock();
621 623
622 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); 624 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index fba4b1f425c1..0a8f83d142f9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -799,7 +799,7 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
799 rcu_read_lock(); 799 rcu_read_lock();
800 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 800 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
801 if (!WARN_ON(!chanctx_conf)) 801 if (!WARN_ON(!chanctx_conf))
802 band = chanctx_conf->channel->band; 802 band = chanctx_conf->def.chan->band;
803 rcu_read_unlock(); 803 rcu_read_unlock();
804 804
805 return band; 805 return band;
@@ -1156,8 +1156,7 @@ struct ieee80211_local {
1156 1156
1157 /* virtual monitor interface */ 1157 /* virtual monitor interface */
1158 struct ieee80211_sub_if_data __rcu *monitor_sdata; 1158 struct ieee80211_sub_if_data __rcu *monitor_sdata;
1159 struct ieee80211_channel *monitor_channel; 1159 struct cfg80211_chan_def monitor_chandef;
1160 enum nl80211_channel_type monitor_channel_type;
1161}; 1160};
1162 1161
1163static inline struct ieee80211_sub_if_data * 1162static inline struct ieee80211_sub_if_data *
@@ -1514,7 +1513,7 @@ static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
1514 } 1513 }
1515 1514
1516 __ieee80211_tx_skb_tid_band(sdata, skb, tid, 1515 __ieee80211_tx_skb_tid_band(sdata, skb, tid,
1517 chanctx_conf->channel->band); 1516 chanctx_conf->def.chan->band);
1518 rcu_read_unlock(); 1517 rcu_read_unlock();
1519} 1518}
1520 1519
@@ -1603,8 +1602,7 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
1603u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 1602u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1604 u16 cap); 1603 u16 cap);
1605u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 1604u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1606 struct ieee80211_channel *channel, 1605 const struct cfg80211_chan_def *chandef,
1607 enum nl80211_channel_type channel_type,
1608 u16 prot_mode); 1606 u16 prot_mode);
1609u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, 1607u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
1610 u32 cap); 1608 u32 cap);
@@ -1616,13 +1614,13 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
1616 enum ieee80211_band band); 1614 enum ieee80211_band band);
1617 1615
1618/* channel management */ 1616/* channel management */
1619enum nl80211_channel_type 1617void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
1620ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); 1618 struct ieee80211_ht_operation *ht_oper,
1619 struct cfg80211_chan_def *chandef);
1621 1620
1622int __must_check 1621int __must_check
1623ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, 1622ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
1624 struct ieee80211_channel *channel, 1623 const struct cfg80211_chan_def *chandef,
1625 enum nl80211_channel_type channel_type,
1626 enum ieee80211_chanctx_mode mode); 1624 enum ieee80211_chanctx_mode mode);
1627void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); 1625void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
1628 1626
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 80ce90b29d9d..5331662489f7 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -54,7 +54,7 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
54 return false; 54 return false;
55 } 55 }
56 56
57 power = chanctx_conf->channel->max_power; 57 power = chanctx_conf->def.chan->max_power;
58 rcu_read_unlock(); 58 rcu_read_unlock();
59 59
60 if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) 60 if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
@@ -415,8 +415,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
415 goto out_unlock; 415 goto out_unlock;
416 } 416 }
417 417
418 ret = ieee80211_vif_use_channel(sdata, local->monitor_channel, 418 ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
419 local->monitor_channel_type,
420 IEEE80211_CHANCTX_EXCLUSIVE); 419 IEEE80211_CHANCTX_EXCLUSIVE);
421 if (ret) { 420 if (ret) {
422 drv_remove_interface(local, sdata); 421 drv_remove_interface(local, sdata);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b229cded4567..6e933409979a 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -798,10 +798,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
798 local->_oper_channel = &sband->channels[0]; 798 local->_oper_channel = &sband->channels[0];
799 local->hw.conf.channel_type = NL80211_CHAN_NO_HT; 799 local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
800 } 800 }
801 if (!local->monitor_channel) { 801 cfg80211_chandef_create(&local->monitor_chandef,
802 local->monitor_channel = &sband->channels[0]; 802 &sband->channels[0],
803 local->monitor_channel_type = NL80211_CHAN_NO_HT; 803 NL80211_CHAN_NO_HT);
804 }
805 channels += sband->n_channels; 804 channels += sband->n_channels;
806 805
807 if (max_bitrates < sband->n_bitrates) 806 if (max_bitrates < sband->n_bitrates)
@@ -884,10 +883,22 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
884 if (supp_ht) 883 if (supp_ht)
885 local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); 884 local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
886 885
887 if (supp_vht) 886 if (supp_vht) {
888 local->scan_ies_len += 887 local->scan_ies_len +=
889 2 + sizeof(struct ieee80211_vht_cap); 888 2 + sizeof(struct ieee80211_vht_cap);
890 889
890 /*
891 * (for now at least), drivers wanting to use VHT must
892 * support channel contexts, as they contain all the
893 * necessary VHT information and the global hw config
894 * doesn't (yet)
895 */
896 if (WARN_ON(!local->use_chanctx)) {
897 result = -EINVAL;
898 goto fail_wiphy_register;
899 }
900 }
901
891 if (!local->ops->hw_scan) { 902 if (!local->ops->hw_scan) {
892 /* For hw_scan, driver needs to set these up. */ 903 /* For hw_scan, driver needs to set these up. */
893 local->hw.wiphy->max_scan_ssids = 4; 904 local->hw.wiphy->max_scan_ssids = 4;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 943694a52624..1bf03f9ff3ba 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -76,7 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
76 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 76 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
77 struct ieee80211_local *local = sdata->local; 77 struct ieee80211_local *local = sdata->local;
78 u32 basic_rates = 0; 78 u32 basic_rates = 0;
79 enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT; 79 struct cfg80211_chan_def sta_chan_def;
80 80
81 /* 81 /*
82 * As support for each feature is added, check for matching 82 * As support for each feature is added, check for matching
@@ -103,17 +103,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
103 if (sdata->vif.bss_conf.basic_rates != basic_rates) 103 if (sdata->vif.bss_conf.basic_rates != basic_rates)
104 goto mismatch; 104 goto mismatch;
105 105
106 if (ie->ht_operation) 106 ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
107 sta_channel_type = 107 ie->ht_operation, &sta_chan_def);
108 ieee80211_ht_oper_to_channel_type(ie->ht_operation); 108
109 109 if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
110 /* Disallow HT40+/- mismatch */ 110 &sta_chan_def))
111 if (ie->ht_operation &&
112 (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS ||
113 sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) &&
114 (sta_channel_type == NL80211_CHAN_HT40MINUS ||
115 sta_channel_type == NL80211_CHAN_HT40PLUS) &&
116 sdata->vif.bss_conf.channel_type != sta_channel_type)
117 goto mismatch; 111 goto mismatch;
118 112
119 return true; 113 return true;
@@ -368,7 +362,7 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
368 rcu_read_unlock(); 362 rcu_read_unlock();
369 return -EINVAL; 363 return -EINVAL;
370 } 364 }
371 chan = chanctx_conf->channel; 365 chan = chanctx_conf->def.chan;
372 rcu_read_unlock(); 366 rcu_read_unlock();
373 367
374 sband = local->hw.wiphy->bands[chan->band]; 368 sband = local->hw.wiphy->bands[chan->band];
@@ -392,7 +386,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb,
392 386
393 sband = local->hw.wiphy->bands[band]; 387 sband = local->hw.wiphy->bands[band];
394 if (!sband->ht_cap.ht_supported || 388 if (!sband->ht_cap.ht_supported ||
395 sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) 389 sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
396 return 0; 390 return 0;
397 391
398 if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) 392 if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
@@ -411,7 +405,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
411 struct ieee80211_chanctx_conf *chanctx_conf; 405 struct ieee80211_chanctx_conf *chanctx_conf;
412 struct ieee80211_channel *channel; 406 struct ieee80211_channel *channel;
413 enum nl80211_channel_type channel_type = 407 enum nl80211_channel_type channel_type =
414 sdata->vif.bss_conf.channel_type; 408 cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef);
415 struct ieee80211_supported_band *sband; 409 struct ieee80211_supported_band *sband;
416 struct ieee80211_sta_ht_cap *ht_cap; 410 struct ieee80211_sta_ht_cap *ht_cap;
417 u8 *pos; 411 u8 *pos;
@@ -422,7 +416,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
422 rcu_read_unlock(); 416 rcu_read_unlock();
423 return -EINVAL; 417 return -EINVAL;
424 } 418 }
425 channel = chanctx_conf->channel; 419 channel = chanctx_conf->def.chan;
426 rcu_read_unlock(); 420 rcu_read_unlock();
427 421
428 sband = local->hw.wiphy->bands[channel->band]; 422 sband = local->hw.wiphy->bands[channel->band];
@@ -435,7 +429,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb,
435 return -ENOMEM; 429 return -ENOMEM;
436 430
437 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); 431 pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
438 ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type, 432 ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef,
439 sdata->vif.bss_conf.ht_operation_mode); 433 sdata->vif.bss_conf.ht_operation_mode);
440 434
441 return 0; 435 return 0;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 7a47f4063d0a..ca52dfdd5375 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -111,7 +111,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
111 u16 ht_opmode; 111 u16 ht_opmode;
112 bool non_ht_sta = false, ht20_sta = false; 112 bool non_ht_sta = false, ht20_sta = false;
113 113
114 if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) 114 if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
115 return 0; 115 return 0;
116 116
117 rcu_read_lock(); 117 rcu_read_lock();
@@ -120,14 +120,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
120 sta->plink_state != NL80211_PLINK_ESTAB) 120 sta->plink_state != NL80211_PLINK_ESTAB)
121 continue; 121 continue;
122 122
123 switch (sta->ch_type) { 123 switch (sta->ch_width) {
124 case NL80211_CHAN_NO_HT: 124 case NL80211_CHAN_WIDTH_20_NOHT:
125 mpl_dbg(sdata, 125 mpl_dbg(sdata,
126 "mesh_plink %pM: nonHT sta (%pM) is present\n", 126 "mesh_plink %pM: nonHT sta (%pM) is present\n",
127 sdata->vif.addr, sta->sta.addr); 127 sdata->vif.addr, sta->sta.addr);
128 non_ht_sta = true; 128 non_ht_sta = true;
129 goto out; 129 goto out;
130 case NL80211_CHAN_HT20: 130 case NL80211_CHAN_WIDTH_20:
131 mpl_dbg(sdata, 131 mpl_dbg(sdata,
132 "mesh_plink %pM: HT20 sta (%pM) is present\n", 132 "mesh_plink %pM: HT20 sta (%pM) is present\n",
133 sdata->vif.addr, sta->sta.addr); 133 sdata->vif.addr, sta->sta.addr);
@@ -142,7 +142,7 @@ out:
142 if (non_ht_sta) 142 if (non_ht_sta)
143 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; 143 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
144 else if (ht20_sta && 144 else if (ht20_sta &&
145 sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20) 145 sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20)
146 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; 146 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
147 else 147 else
148 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; 148 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
@@ -372,7 +372,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
372 372
373 sta->sta.supp_rates[band] = rates; 373 sta->sta.supp_rates[band] = rates;
374 if (elems->ht_cap_elem && 374 if (elems->ht_cap_elem &&
375 sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT) 375 sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT)
376 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, 376 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
377 elems->ht_cap_elem, 377 elems->ht_cap_elem,
378 &sta->sta.ht_cap); 378 &sta->sta.ht_cap);
@@ -380,12 +380,15 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
380 memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); 380 memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));
381 381
382 if (elems->ht_operation) { 382 if (elems->ht_operation) {
383 struct cfg80211_chan_def chandef;
384
383 if (!(elems->ht_operation->ht_param & 385 if (!(elems->ht_operation->ht_param &
384 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) 386 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
385 sta->sta.ht_cap.cap &= 387 sta->sta.ht_cap.cap &=
386 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; 388 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
387 sta->ch_type = 389 ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
388 ieee80211_ht_oper_to_channel_type(elems->ht_operation); 390 elems->ht_operation, &chandef);
391 sta->ch_width = chandef.width;
389 } 392 }
390 393
391 rate_control_rate_init(sta); 394 rate_control_rate_init(sta);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2cec14cc02d1..d2a4f78b4b0f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -191,17 +191,19 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
191 rcu_read_unlock(); 191 rcu_read_unlock();
192 return 0; 192 return 0;
193 } 193 }
194 chan = chanctx_conf->channel; 194 chan = chanctx_conf->def.chan;
195 rcu_read_unlock(); 195 rcu_read_unlock();
196 sband = local->hw.wiphy->bands[chan->band]; 196 sband = local->hw.wiphy->bands[chan->band];
197 197
198 switch (sdata->vif.bss_conf.channel_type) { 198 switch (sdata->vif.bss_conf.chandef.width) {
199 case NL80211_CHAN_HT40PLUS: 199 case NL80211_CHAN_WIDTH_40:
200 if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) 200 if (sdata->vif.bss_conf.chandef.chan->center_freq >
201 sdata->vif.bss_conf.chandef.center_freq1 &&
202 chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
201 disable_40 = true; 203 disable_40 = true;
202 break; 204 if (sdata->vif.bss_conf.chandef.chan->center_freq <
203 case NL80211_CHAN_HT40MINUS: 205 sdata->vif.bss_conf.chandef.center_freq1 &&
204 if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) 206 chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
205 disable_40 = true; 207 disable_40 = true;
206 break; 208 break;
207 default: 209 default:
@@ -381,7 +383,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
381 rcu_read_unlock(); 383 rcu_read_unlock();
382 return; 384 return;
383 } 385 }
384 chan = chanctx_conf->channel; 386 chan = chanctx_conf->def.chan;
385 rcu_read_unlock(); 387 rcu_read_unlock();
386 sband = local->hw.wiphy->bands[chan->band]; 388 sband = local->hw.wiphy->bands[chan->band];
387 389
@@ -2476,11 +2478,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2476 return; 2478 return;
2477 } 2479 }
2478 2480
2479 if (rx_status->freq != chanctx_conf->channel->center_freq) { 2481 if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
2480 rcu_read_unlock(); 2482 rcu_read_unlock();
2481 return; 2483 return;
2482 } 2484 }
2483 chan = chanctx_conf->channel; 2485 chan = chanctx_conf->def.chan;
2484 rcu_read_unlock(); 2486 rcu_read_unlock();
2485 2487
2486 if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && 2488 if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
@@ -3191,6 +3193,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3191 const u8 *ht_oper_ie; 3193 const u8 *ht_oper_ie;
3192 const struct ieee80211_ht_operation *ht_oper = NULL; 3194 const struct ieee80211_ht_operation *ht_oper = NULL;
3193 struct ieee80211_supported_band *sband; 3195 struct ieee80211_supported_band *sband;
3196 struct cfg80211_chan_def chandef;
3194 3197
3195 sband = local->hw.wiphy->bands[cbss->channel->band]; 3198 sband = local->hw.wiphy->bands[cbss->channel->band];
3196 3199
@@ -3277,7 +3280,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3277 sdata->smps_mode = IEEE80211_SMPS_OFF; 3280 sdata->smps_mode = IEEE80211_SMPS_OFF;
3278 3281
3279 ieee80211_vif_release_channel(sdata); 3282 ieee80211_vif_release_channel(sdata);
3280 return ieee80211_vif_use_channel(sdata, cbss->channel, channel_type, 3283 cfg80211_chandef_create(&chandef, cbss->channel, channel_type);
3284 return ieee80211_vif_use_channel(sdata, &chandef,
3281 IEEE80211_CHANCTX_SHARED); 3285 IEEE80211_CHANCTX_SHARED);
3282} 3286}
3283 3287
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 3313c117b322..dd88381c53b7 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -391,7 +391,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
391 return; 391 return;
392 392
393 /* if HT BSS, and we handle a data frame, also try HT rates */ 393 /* if HT BSS, and we handle a data frame, also try HT rates */
394 if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT) 394 if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
395 return; 395 return;
396 396
397 fc = hdr->frame_control; 397 fc = hdr->frame_control;
@@ -408,8 +408,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate,
408 408
409 alt_rate.flags |= IEEE80211_TX_RC_MCS; 409 alt_rate.flags |= IEEE80211_TX_RC_MCS;
410 410
411 if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) || 411 if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_40)
412 (txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS))
413 alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; 412 alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
414 413
415 if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { 414 if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) {
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index ec198ef6aa8a..301386dabf88 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -65,7 +65,7 @@ static inline void rate_control_rate_init(struct sta_info *sta)
65 return; 65 return;
66 } 66 }
67 67
68 sband = local->hw.wiphy->bands[chanctx_conf->channel->band]; 68 sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
69 rcu_read_unlock(); 69 rcu_read_unlock();
70 70
71 ref->ops->rate_init(ref->priv, sband, ista, priv_sta); 71 ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a0836d7187c1..dadcfcf29122 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1087,7 +1087,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
1087 return; 1087 return;
1088 } 1088 }
1089 1089
1090 ieee80211_xmit(sdata, skb, chanctx_conf->channel->band); 1090 ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band);
1091 rcu_read_unlock(); 1091 rcu_read_unlock();
1092} 1092}
1093 1093
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 776f3d0b4a47..2b2d5aac2bb1 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -272,7 +272,7 @@ struct sta_ampdu_mlme {
272 * @t_offset: timing offset relative to this host 272 * @t_offset: timing offset relative to this host
273 * @t_offset_setpoint: reference timing offset of this sta to be used when 273 * @t_offset_setpoint: reference timing offset of this sta to be used when
274 * calculating clockdrift 274 * calculating clockdrift
275 * @ch_type: peer's channel type 275 * @ch_width: peer's channel width
276 * @debugfs: debug filesystem info 276 * @debugfs: debug filesystem info
277 * @dead: set to true when sta is unlinked 277 * @dead: set to true when sta is unlinked
278 * @uploaded: set to true when sta is uploaded to the driver 278 * @uploaded: set to true when sta is uploaded to the driver
@@ -368,7 +368,7 @@ struct sta_info {
368 struct timer_list plink_timer; 368 struct timer_list plink_timer;
369 s64 t_offset; 369 s64 t_offset;
370 s64 t_offset_setpoint; 370 s64 t_offset_setpoint;
371 enum nl80211_channel_type ch_type; 371 enum nl80211_chan_width ch_width;
372#endif 372#endif
373 373
374#ifdef CONFIG_MAC80211_DEBUGFS 374#ifdef CONFIG_MAC80211_DEBUGFS
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index bc28346ba207..a8270b441a6f 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -28,16 +28,21 @@
28#define VIF_PR_FMT " vif:%s(%d%s)" 28#define VIF_PR_FMT " vif:%s(%d%s)"
29#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" 29#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
30 30
31#define CHANCTX_ENTRY __field(int, freq) \ 31#define CHANCTX_ENTRY __field(u32, control_freq) \
32 __field(int, chantype) \ 32 __field(u32, chan_width) \
33 __field(u32, center_freq1) \
34 __field(u32, center_freq2) \
33 __field(u8, rx_chains_static) \ 35 __field(u8, rx_chains_static) \
34 __field(u8, rx_chains_dynamic) 36 __field(u8, rx_chains_dynamic)
35#define CHANCTX_ASSIGN __entry->freq = ctx->conf.channel->center_freq; \ 37#define CHANCTX_ASSIGN __entry->control_freq = ctx->conf.def.chan->center_freq;\
36 __entry->chantype = ctx->conf.channel_type; \ 38 __entry->chan_width = ctx->conf.def.width; \
39 __entry->center_freq1 = ctx->conf.def.center_freq1; \
40 __entry->center_freq2 = ctx->conf.def.center_freq2; \
37 __entry->rx_chains_static = ctx->conf.rx_chains_static; \ 41 __entry->rx_chains_static = ctx->conf.rx_chains_static; \
38 __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic 42 __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
39#define CHANCTX_PR_FMT " freq:%d MHz chantype:%d chains:%d/%d" 43#define CHANCTX_PR_FMT " control:%d MHz width:%d center: %d/%d MHz chains:%d/%d"
40#define CHANCTX_PR_ARG __entry->freq, __entry->chantype, \ 44#define CHANCTX_PR_ARG __entry->control_freq, __entry->chan_width, \
45 __entry->center_freq1, __entry->center_freq2, \
41 __entry->rx_chains_static, __entry->rx_chains_dynamic 46 __entry->rx_chains_static, __entry->rx_chains_dynamic
42 47
43 48
@@ -334,7 +339,8 @@ TRACE_EVENT(drv_bss_info_changed,
334 __field(u16, ht_operation_mode) 339 __field(u16, ht_operation_mode)
335 __field(s32, cqm_rssi_thold); 340 __field(s32, cqm_rssi_thold);
336 __field(s32, cqm_rssi_hyst); 341 __field(s32, cqm_rssi_hyst);
337 __field(u32, channel_type); 342 __field(u32, channel_width);
343 __field(u32, channel_cfreq1);
338 __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt); 344 __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt);
339 __field(bool, arp_filter_enabled); 345 __field(bool, arp_filter_enabled);
340 __field(bool, qos); 346 __field(bool, qos);
@@ -370,7 +376,8 @@ TRACE_EVENT(drv_bss_info_changed,
370 __entry->ht_operation_mode = info->ht_operation_mode; 376 __entry->ht_operation_mode = info->ht_operation_mode;
371 __entry->cqm_rssi_thold = info->cqm_rssi_thold; 377 __entry->cqm_rssi_thold = info->cqm_rssi_thold;
372 __entry->cqm_rssi_hyst = info->cqm_rssi_hyst; 378 __entry->cqm_rssi_hyst = info->cqm_rssi_hyst;
373 __entry->channel_type = info->channel_type; 379 __entry->channel_width = info->chandef.width;
380 __entry->channel_cfreq1 = info->chandef.center_freq1;
374 memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, 381 memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list,
375 sizeof(u32) * info->arp_addr_cnt); 382 sizeof(u32) * info->arp_addr_cnt);
376 __entry->arp_filter_enabled = info->arp_filter_enabled; 383 __entry->arp_filter_enabled = info->arp_filter_enabled;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index b5468876287e..d8ef3417bf2b 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1676,7 +1676,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
1676 if (!chanctx_conf) 1676 if (!chanctx_conf)
1677 goto fail_rcu; 1677 goto fail_rcu;
1678 1678
1679 chan = chanctx_conf->channel; 1679 chan = chanctx_conf->def.chan;
1680 1680
1681 /* 1681 /*
1682 * Frame injection is not allowed if beaconing is not allowed 1682 * Frame injection is not allowed if beaconing is not allowed
@@ -1779,7 +1779,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1779 chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); 1779 chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf);
1780 if (!chanctx_conf) 1780 if (!chanctx_conf)
1781 goto fail_rcu; 1781 goto fail_rcu;
1782 band = chanctx_conf->channel->band; 1782 band = chanctx_conf->def.chan->band;
1783 if (sta) 1783 if (sta)
1784 break; 1784 break;
1785 /* fall through */ 1785 /* fall through */
@@ -1794,7 +1794,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1794 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 1794 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
1795 if (!chanctx_conf) 1795 if (!chanctx_conf)
1796 goto fail_rcu; 1796 goto fail_rcu;
1797 band = chanctx_conf->channel->band; 1797 band = chanctx_conf->def.chan->band;
1798 break; 1798 break;
1799 case NL80211_IFTYPE_WDS: 1799 case NL80211_IFTYPE_WDS:
1800 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); 1800 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
@@ -1871,7 +1871,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1871 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 1871 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
1872 if (!chanctx_conf) 1872 if (!chanctx_conf)
1873 goto fail_rcu; 1873 goto fail_rcu;
1874 band = chanctx_conf->channel->band; 1874 band = chanctx_conf->def.chan->band;
1875 break; 1875 break;
1876#endif 1876#endif
1877 case NL80211_IFTYPE_STATION: 1877 case NL80211_IFTYPE_STATION:
@@ -1930,7 +1930,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1930 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 1930 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
1931 if (!chanctx_conf) 1931 if (!chanctx_conf)
1932 goto fail_rcu; 1932 goto fail_rcu;
1933 band = chanctx_conf->channel->band; 1933 band = chanctx_conf->def.chan->band;
1934 break; 1934 break;
1935 case NL80211_IFTYPE_ADHOC: 1935 case NL80211_IFTYPE_ADHOC:
1936 /* DA SA BSSID */ 1936 /* DA SA BSSID */
@@ -1941,7 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1941 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 1941 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
1942 if (!chanctx_conf) 1942 if (!chanctx_conf)
1943 goto fail_rcu; 1943 goto fail_rcu;
1944 band = chanctx_conf->channel->band; 1944 band = chanctx_conf->def.chan->band;
1945 break; 1945 break;
1946 default: 1946 default:
1947 goto fail_rcu; 1947 goto fail_rcu;
@@ -2191,7 +2191,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
2191 return true; 2191 return true;
2192 } 2192 }
2193 result = ieee80211_tx(sdata, skb, true, 2193 result = ieee80211_tx(sdata, skb, true,
2194 chanctx_conf->channel->band); 2194 chanctx_conf->def.chan->band);
2195 } else { 2195 } else {
2196 struct sk_buff_head skbs; 2196 struct sk_buff_head skbs;
2197 2197
@@ -2455,7 +2455,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2455 *pos++ = WLAN_EID_SSID; 2455 *pos++ = WLAN_EID_SSID;
2456 *pos++ = 0x0; 2456 *pos++ = 0x0;
2457 2457
2458 band = chanctx_conf->channel->band; 2458 band = chanctx_conf->def.chan->band;
2459 2459
2460 if (ieee80211_add_srates_ie(sdata, skb, true, band) || 2460 if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
2461 mesh_add_ds_params_ie(skb, sdata) || 2461 mesh_add_ds_params_ie(skb, sdata) ||
@@ -2474,7 +2474,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2474 goto out; 2474 goto out;
2475 } 2475 }
2476 2476
2477 band = chanctx_conf->channel->band; 2477 band = chanctx_conf->def.chan->band;
2478 2478
2479 info = IEEE80211_SKB_CB(skb); 2479 info = IEEE80211_SKB_CB(skb);
2480 2480
@@ -2754,7 +2754,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
2754 info = IEEE80211_SKB_CB(skb); 2754 info = IEEE80211_SKB_CB(skb);
2755 2755
2756 tx.flags |= IEEE80211_TX_PS_BUFFERED; 2756 tx.flags |= IEEE80211_TX_PS_BUFFERED;
2757 info->band = chanctx_conf->channel->band; 2757 info->band = chanctx_conf->def.chan->band;
2758 2758
2759 if (invoke_tx_handlers(&tx)) 2759 if (invoke_tx_handlers(&tx))
2760 skb = NULL; 2760 skb = NULL;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2f08a7e09b7e..3b3dd32f121f 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -898,7 +898,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
898 rcu_read_lock(); 898 rcu_read_lock();
899 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 899 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
900 use_11b = (chanctx_conf && 900 use_11b = (chanctx_conf &&
901 chanctx_conf->channel->band == IEEE80211_BAND_2GHZ) && 901 chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ) &&
902 !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); 902 !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
903 rcu_read_unlock(); 903 rcu_read_unlock();
904 904
@@ -991,7 +991,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
991 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 991 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
992 992
993 if (chanctx_conf && 993 if (chanctx_conf &&
994 chanctx_conf->channel->band == IEEE80211_BAND_2GHZ && 994 chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ &&
995 have_higher_than_11mbit) 995 have_higher_than_11mbit)
996 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; 996 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
997 else 997 else
@@ -1871,8 +1871,7 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
1871} 1871}
1872 1872
1873u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, 1873u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1874 struct ieee80211_channel *channel, 1874 const struct cfg80211_chan_def *chandef,
1875 enum nl80211_channel_type channel_type,
1876 u16 prot_mode) 1875 u16 prot_mode)
1877{ 1876{
1878 struct ieee80211_ht_operation *ht_oper; 1877 struct ieee80211_ht_operation *ht_oper;
@@ -1880,23 +1879,25 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1880 *pos++ = WLAN_EID_HT_OPERATION; 1879 *pos++ = WLAN_EID_HT_OPERATION;
1881 *pos++ = sizeof(struct ieee80211_ht_operation); 1880 *pos++ = sizeof(struct ieee80211_ht_operation);
1882 ht_oper = (struct ieee80211_ht_operation *)pos; 1881 ht_oper = (struct ieee80211_ht_operation *)pos;
1883 ht_oper->primary_chan = 1882 ht_oper->primary_chan = ieee80211_frequency_to_channel(
1884 ieee80211_frequency_to_channel(channel->center_freq); 1883 chandef->chan->center_freq);
1885 switch (channel_type) { 1884 switch (chandef->width) {
1886 case NL80211_CHAN_HT40MINUS: 1885 case NL80211_CHAN_WIDTH_160:
1887 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; 1886 case NL80211_CHAN_WIDTH_80P80:
1888 break; 1887 case NL80211_CHAN_WIDTH_80:
1889 case NL80211_CHAN_HT40PLUS: 1888 case NL80211_CHAN_WIDTH_40:
1890 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 1889 if (chandef->center_freq1 > chandef->chan->center_freq)
1890 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1891 else
1892 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1891 break; 1893 break;
1892 case NL80211_CHAN_HT20:
1893 default: 1894 default:
1894 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; 1895 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1895 break; 1896 break;
1896 } 1897 }
1897 if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && 1898 if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
1898 channel_type != NL80211_CHAN_NO_HT && 1899 chandef->width != NL80211_CHAN_WIDTH_20_NOHT &&
1899 channel_type != NL80211_CHAN_HT20) 1900 chandef->width != NL80211_CHAN_WIDTH_20)
1900 ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; 1901 ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
1901 1902
1902 ht_oper->operation_mode = cpu_to_le16(prot_mode); 1903 ht_oper->operation_mode = cpu_to_le16(prot_mode);
@@ -1910,13 +1911,17 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
1910 return pos + sizeof(struct ieee80211_ht_operation); 1911 return pos + sizeof(struct ieee80211_ht_operation);
1911} 1912}
1912 1913
1913enum nl80211_channel_type 1914void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
1914ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) 1915 struct ieee80211_ht_operation *ht_oper,
1916 struct cfg80211_chan_def *chandef)
1915{ 1917{
1916 enum nl80211_channel_type channel_type; 1918 enum nl80211_channel_type channel_type;
1917 1919
1918 if (!ht_oper) 1920 if (!ht_oper) {
1919 return NL80211_CHAN_NO_HT; 1921 cfg80211_chandef_create(chandef, control_chan,
1922 NL80211_CHAN_NO_HT);
1923 return;
1924 }
1920 1925
1921 switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { 1926 switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
1922 case IEEE80211_HT_PARAM_CHA_SEC_NONE: 1927 case IEEE80211_HT_PARAM_CHA_SEC_NONE:
@@ -1932,7 +1937,7 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper)
1932 channel_type = NL80211_CHAN_NO_HT; 1937 channel_type = NL80211_CHAN_NO_HT;
1933 } 1938 }
1934 1939
1935 return channel_type; 1940 cfg80211_chandef_create(chandef, control_chan, channel_type);
1936} 1941}
1937 1942
1938int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, 1943int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,