aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c33
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c9
-rw-r--r--include/net/mac80211.h17
-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
20 files changed, 220 insertions, 262 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index b0338543547b..6be3faeaa59a 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -681,7 +681,7 @@ static void mac80211_hwsim_tx_iter(void *_data, u8 *addr,
681 return; 681 return;
682 682
683 if (!hwsim_chans_compat(data->channel, 683 if (!hwsim_chans_compat(data->channel,
684 rcu_dereference(vif->chanctx_conf)->channel)) 684 rcu_dereference(vif->chanctx_conf)->def.chan))
685 return; 685 return;
686 686
687 data->receive = true; 687 data->receive = true;
@@ -832,7 +832,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
832 } else { 832 } else {
833 chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf); 833 chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf);
834 if (chanctx_conf) 834 if (chanctx_conf)
835 channel = chanctx_conf->channel; 835 channel = chanctx_conf->def.chan;
836 else 836 else
837 channel = NULL; 837 channel = NULL;
838 } 838 }
@@ -977,7 +977,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
977 return; 977 return;
978 978
979 mac80211_hwsim_tx_frame(hw, skb, 979 mac80211_hwsim_tx_frame(hw, skb,
980 rcu_dereference(vif->chanctx_conf)->channel); 980 rcu_dereference(vif->chanctx_conf)->def.chan);
981} 981}
982 982
983 983
@@ -1107,9 +1107,8 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
1107 } 1107 }
1108 1108
1109 if (changed & BSS_CHANGED_HT) { 1109 if (changed & BSS_CHANGED_HT) {
1110 wiphy_debug(hw->wiphy, " HT: op_mode=0x%x, chantype=%s\n", 1110 wiphy_debug(hw->wiphy, " HT: op_mode=0x%x\n",
1111 info->ht_operation_mode, 1111 info->ht_operation_mode);
1112 hwsim_chantypes[info->channel_type]);
1113 } 1112 }
1114 1113
1115 if (changed & BSS_CHANGED_BASIC_RATES) { 1114 if (changed & BSS_CHANGED_BASIC_RATES) {
@@ -1497,16 +1496,20 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
1497 struct ieee80211_chanctx_conf *ctx) 1496 struct ieee80211_chanctx_conf *ctx)
1498{ 1497{
1499 hwsim_set_chanctx_magic(ctx); 1498 hwsim_set_chanctx_magic(ctx);
1500 wiphy_debug(hw->wiphy, "add channel context %d MHz/%d\n", 1499 wiphy_debug(hw->wiphy,
1501 ctx->channel->center_freq, ctx->channel_type); 1500 "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
1501 ctx->def.chan->center_freq, ctx->def.width,
1502 ctx->def.center_freq1, ctx->def.center_freq2);
1502 return 0; 1503 return 0;
1503} 1504}
1504 1505
1505static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, 1506static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
1506 struct ieee80211_chanctx_conf *ctx) 1507 struct ieee80211_chanctx_conf *ctx)
1507{ 1508{
1508 wiphy_debug(hw->wiphy, "remove channel context %d MHz/%d\n", 1509 wiphy_debug(hw->wiphy,
1509 ctx->channel->center_freq, ctx->channel_type); 1510 "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
1511 ctx->def.chan->center_freq, ctx->def.width,
1512 ctx->def.center_freq1, ctx->def.center_freq2);
1510 hwsim_check_chanctx_magic(ctx); 1513 hwsim_check_chanctx_magic(ctx);
1511 hwsim_clear_chanctx_magic(ctx); 1514 hwsim_clear_chanctx_magic(ctx);
1512} 1515}
@@ -1516,8 +1519,10 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
1516 u32 changed) 1519 u32 changed)
1517{ 1520{
1518 hwsim_check_chanctx_magic(ctx); 1521 hwsim_check_chanctx_magic(ctx);
1519 wiphy_debug(hw->wiphy, "change channel context %#x (%d MHz/%d)\n", 1522 wiphy_debug(hw->wiphy,
1520 changed, ctx->channel->center_freq, ctx->channel_type); 1523 "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
1524 ctx->def.chan->center_freq, ctx->def.width,
1525 ctx->def.center_freq1, ctx->def.center_freq2);
1521} 1526}
1522 1527
1523static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw, 1528static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
@@ -1639,7 +1644,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
1639 1644
1640 rcu_read_lock(); 1645 rcu_read_lock();
1641 mac80211_hwsim_tx_frame(data->hw, skb, 1646 mac80211_hwsim_tx_frame(data->hw, skb,
1642 rcu_dereference(vif->chanctx_conf)->channel); 1647 rcu_dereference(vif->chanctx_conf)->def.chan);
1643 rcu_read_unlock(); 1648 rcu_read_unlock();
1644} 1649}
1645 1650
@@ -1671,7 +1676,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
1671 1676
1672 rcu_read_lock(); 1677 rcu_read_lock();
1673 mac80211_hwsim_tx_frame(data->hw, skb, 1678 mac80211_hwsim_tx_frame(data->hw, skb,
1674 rcu_dereference(vif->chanctx_conf)->channel); 1679 rcu_dereference(vif->chanctx_conf)->def.chan);
1675 rcu_read_unlock(); 1680 rcu_read_unlock();
1676} 1681}
1677 1682
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 380cf1ff6cd1..4f1a05b92d2d 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -3791,7 +3791,7 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
3791 3791
3792 /* Handle HT information change */ 3792 /* Handle HT information change */
3793 if ((changed & BSS_CHANGED_HT) && 3793 if ((changed & BSS_CHANGED_HT) &&
3794 (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { 3794 (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
3795 ret = wl1271_acx_set_ht_information(wl, wlvif, 3795 ret = wl1271_acx_set_ht_information(wl, wlvif,
3796 bss_conf->ht_operation_mode); 3796 bss_conf->ht_operation_mode);
3797 if (ret < 0) { 3797 if (ret < 0) {
@@ -3905,7 +3905,8 @@ sta_not_found:
3905 u32 rates; 3905 u32 rates;
3906 int ieoffset; 3906 int ieoffset;
3907 wlvif->aid = bss_conf->aid; 3907 wlvif->aid = bss_conf->aid;
3908 wlvif->channel_type = bss_conf->channel_type; 3908 wlvif->channel_type =
3909 cfg80211_get_chandef_type(&bss_conf->chandef);
3909 wlvif->beacon_int = bss_conf->beacon_int; 3910 wlvif->beacon_int = bss_conf->beacon_int;
3910 do_join = true; 3911 do_join = true;
3911 set_assoc = true; 3912 set_assoc = true;
@@ -4071,7 +4072,7 @@ sta_not_found:
4071 /* Handle new association with HT. Do this after join. */ 4072 /* Handle new association with HT. Do this after join. */
4072 if (sta_exists) { 4073 if (sta_exists) {
4073 if ((changed & BSS_CHANGED_HT) && 4074 if ((changed & BSS_CHANGED_HT) &&
4074 (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { 4075 (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
4075 ret = wl1271_acx_set_ht_capabilities(wl, 4076 ret = wl1271_acx_set_ht_capabilities(wl,
4076 &sta_ht_cap, 4077 &sta_ht_cap,
4077 true, 4078 true,
@@ -4098,7 +4099,7 @@ sta_not_found:
4098 4099
4099 /* Handle HT information change. Done after join. */ 4100 /* Handle HT information change. Done after join. */
4100 if ((changed & BSS_CHANGED_HT) && 4101 if ((changed & BSS_CHANGED_HT) &&
4101 (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { 4102 (bss_conf->chandef.width != NL80211_CHAN_WIDTH_20_NOHT)) {
4102 ret = wl1271_acx_set_ht_information(wl, wlvif, 4103 ret = wl1271_acx_set_ht_information(wl, wlvif,
4103 bss_conf->ht_operation_mode); 4104 bss_conf->ht_operation_mode);
4104 if (ret < 0) { 4105 if (ret < 0) {
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 12093778b057..6af51328dcd1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -145,11 +145,11 @@ struct ieee80211_low_level_stats {
145 145
146/** 146/**
147 * enum ieee80211_chanctx_change - change flag for channel context 147 * enum ieee80211_chanctx_change - change flag for channel context
148 * @IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE: The channel type was changed 148 * @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
149 * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed 149 * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
150 */ 150 */
151enum ieee80211_chanctx_change { 151enum ieee80211_chanctx_change {
152 IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE = BIT(0), 152 IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0),
153 IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1), 153 IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1),
154}; 154};
155 155
@@ -159,8 +159,7 @@ enum ieee80211_chanctx_change {
159 * This is the driver-visible part. The ieee80211_chanctx 159 * This is the driver-visible part. The ieee80211_chanctx
160 * that contains it is visible in mac80211 only. 160 * that contains it is visible in mac80211 only.
161 * 161 *
162 * @channel: the channel to tune to 162 * @def: the channel definition
163 * @channel_type: the channel (HT) type
164 * @rx_chains_static: The number of RX chains that must always be 163 * @rx_chains_static: The number of RX chains that must always be
165 * active on the channel to receive MIMO transmissions 164 * active on the channel to receive MIMO transmissions
166 * @rx_chains_dynamic: The number of RX chains that must be enabled 165 * @rx_chains_dynamic: The number of RX chains that must be enabled
@@ -170,8 +169,7 @@ enum ieee80211_chanctx_change {
170 * sizeof(void *), size is determined in hw information. 169 * sizeof(void *), size is determined in hw information.
171 */ 170 */
172struct ieee80211_chanctx_conf { 171struct ieee80211_chanctx_conf {
173 struct ieee80211_channel *channel; 172 struct cfg80211_chan_def def;
174 enum nl80211_channel_type channel_type;
175 173
176 u8 rx_chains_static, rx_chains_dynamic; 174 u8 rx_chains_static, rx_chains_dynamic;
177 175
@@ -288,9 +286,8 @@ enum ieee80211_rssi_event {
288 * @mcast_rate: per-band multicast rate index + 1 (0: disabled) 286 * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
289 * @bssid: The BSSID for this BSS 287 * @bssid: The BSSID for this BSS
290 * @enable_beacon: whether beaconing should be enabled or not 288 * @enable_beacon: whether beaconing should be enabled or not
291 * @channel_type: Channel type for this BSS -- the hardware might be 289 * @chandef: Channel definition for this BSS -- the hardware might be
292 * configured for HT40+ while this BSS only uses no-HT, for 290 * configured a higher bandwidth than this BSS uses, for example.
293 * example.
294 * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation. 291 * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
295 * This field is only valid when the channel type is one of the HT types. 292 * This field is only valid when the channel type is one of the HT types.
296 * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value 293 * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
@@ -339,7 +336,7 @@ struct ieee80211_bss_conf {
339 u16 ht_operation_mode; 336 u16 ht_operation_mode;
340 s32 cqm_rssi_thold; 337 s32 cqm_rssi_thold;
341 u32 cqm_rssi_hyst; 338 u32 cqm_rssi_hyst;
342 enum nl80211_channel_type channel_type; 339 struct cfg80211_chan_def chandef;
343 __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; 340 __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
344 u8 arp_addr_cnt; 341 u8 arp_addr_cnt;
345 bool arp_filter_enabled; 342 bool arp_filter_enabled;
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,