Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: Fix HT channel selection

HT management is done differently for AP and STA modes, unify
to just the ->config() callback since HT is fundamentally a
PHY property and cannot be per-BSS.

Rename enum nl80211_sec_chan_offset as nl80211_channel_type to denote
the channel type ( NO_HT, HT20, HT40+, HT40- ).

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Sujith and committed by
John W. Linville
094d05dc 420e7fab

+109 -169
+29 -94
drivers/net/wireless/ath9k/main.c
··· 623 623 return -1; 624 624 } 625 625 626 - /* ext_chan_offset: (-1, 0, 1) (below, none, above) */ 627 - 628 626 static u32 ath_get_extchanmode(struct ath_softc *sc, 629 627 struct ieee80211_channel *chan, 630 - int ext_chan_offset, 631 - enum ath9k_ht_macmode tx_chan_width) 628 + enum nl80211_channel_type channel_type) 632 629 { 633 630 u32 chanmode = 0; 634 631 635 632 switch (chan->band) { 636 633 case IEEE80211_BAND_2GHZ: 637 - if ((ext_chan_offset == 0) && 638 - (tx_chan_width == ATH9K_HT_MACMODE_20)) 634 + switch(channel_type) { 635 + case NL80211_CHAN_NO_HT: 636 + case NL80211_CHAN_HT20: 639 637 chanmode = CHANNEL_G_HT20; 640 - if ((ext_chan_offset == 1) && 641 - (tx_chan_width == ATH9K_HT_MACMODE_2040)) 638 + break; 639 + case NL80211_CHAN_HT40PLUS: 642 640 chanmode = CHANNEL_G_HT40PLUS; 643 - if ((ext_chan_offset == -1) && 644 - (tx_chan_width == ATH9K_HT_MACMODE_2040)) 641 + break; 642 + case NL80211_CHAN_HT40MINUS: 645 643 chanmode = CHANNEL_G_HT40MINUS; 644 + break; 645 + } 646 646 break; 647 647 case IEEE80211_BAND_5GHZ: 648 - if ((ext_chan_offset == 0) && 649 - (tx_chan_width == ATH9K_HT_MACMODE_20)) 648 + switch(channel_type) { 649 + case NL80211_CHAN_NO_HT: 650 + case NL80211_CHAN_HT20: 650 651 chanmode = CHANNEL_A_HT20; 651 - if ((ext_chan_offset == 1) && 652 - (tx_chan_width == ATH9K_HT_MACMODE_2040)) 652 + break; 653 + case NL80211_CHAN_HT40PLUS: 653 654 chanmode = CHANNEL_A_HT40PLUS; 654 - if ((ext_chan_offset == -1) && 655 - (tx_chan_width == ATH9K_HT_MACMODE_2040)) 655 + break; 656 + case NL80211_CHAN_HT40MINUS: 656 657 chanmode = CHANNEL_A_HT40MINUS; 658 + break; 659 + } 657 660 break; 658 661 default: 659 662 break; ··· 832 829 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; 833 830 } 834 831 835 - static void ath9k_ht_conf(struct ath_softc *sc, 836 - struct ieee80211_bss_conf *bss_conf) 837 - { 838 - if (sc->hw->conf.ht.enabled) { 839 - if (bss_conf->ht.width_40_ok) 840 - sc->tx_chan_width = ATH9K_HT_MACMODE_2040; 841 - else 842 - sc->tx_chan_width = ATH9K_HT_MACMODE_20; 843 - 844 - ath9k_hw_set11nmac2040(sc->sc_ah, sc->tx_chan_width); 845 - 846 - DPRINTF(sc, ATH_DBG_CONFIG, 847 - "BSS Changed HT, chanwidth: %d\n", sc->tx_chan_width); 848 - } 849 - } 850 - 851 - static inline int ath_sec_offset(u8 ext_offset) 852 - { 853 - if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) 854 - return 0; 855 - else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) 856 - return 1; 857 - else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) 858 - return -1; 859 - 860 - return 0; 861 - } 862 - 863 832 static void ath9k_bss_assoc_info(struct ath_softc *sc, 864 833 struct ieee80211_vif *vif, 865 834 struct ieee80211_bss_conf *bss_conf) 866 835 { 867 - struct ieee80211_hw *hw = sc->hw; 868 - struct ieee80211_channel *curchan = hw->conf.channel; 869 836 struct ath_vap *avp = (void *)vif->drv_priv; 870 - int pos; 871 837 872 838 if (bss_conf->assoc) { 873 - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d\n", bss_conf->aid); 839 + DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", 840 + bss_conf->aid, sc->sc_curbssid); 874 841 875 842 /* New association, store aid */ 876 843 if (avp->av_opmode == NL80211_IFTYPE_STATION) { ··· 858 885 sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; 859 886 sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; 860 887 sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; 861 - 862 - /* Update chainmask */ 863 - ath_update_chainmask(sc, hw->conf.ht.enabled); 864 - 865 - DPRINTF(sc, ATH_DBG_CONFIG, 866 - "bssid %pM aid 0x%x\n", 867 - sc->sc_curbssid, sc->sc_curaid); 868 - 869 - pos = ath_get_channel(sc, curchan); 870 - if (pos == -1) { 871 - DPRINTF(sc, ATH_DBG_FATAL, 872 - "Invalid channel: %d\n", curchan->center_freq); 873 - return; 874 - } 875 - 876 - if (hw->conf.ht.enabled) { 877 - int offset = 878 - ath_sec_offset(bss_conf->ht.secondary_channel_offset); 879 - sc->tx_chan_width = (bss_conf->ht.width_40_ok) ? 880 - ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; 881 - 882 - sc->sc_ah->ah_channels[pos].chanmode = 883 - ath_get_extchanmode(sc, curchan, 884 - offset, sc->tx_chan_width); 885 - } else { 886 - sc->sc_ah->ah_channels[pos].chanmode = 887 - (curchan->band == IEEE80211_BAND_2GHZ) ? 888 - CHANNEL_G : CHANNEL_A; 889 - } 890 - 891 - /* set h/w channel */ 892 - if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) 893 - DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel: %d\n", 894 - curchan->center_freq); 895 888 896 889 /* Start ANI */ 897 890 mod_timer(&sc->sc_ani.timer, ··· 2085 2146 struct ath_softc *sc = hw->priv; 2086 2147 struct ieee80211_conf *conf = &hw->conf; 2087 2148 2088 - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { 2149 + if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | 2150 + IEEE80211_CONF_CHANGE_HT)) { 2089 2151 struct ieee80211_channel *curchan = hw->conf.channel; 2090 2152 int pos; 2091 2153 ··· 2105 2165 (curchan->band == IEEE80211_BAND_2GHZ) ? 2106 2166 CHANNEL_G : CHANNEL_A; 2107 2167 2108 - if ((sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) && 2109 - (conf->ht.enabled)) { 2110 - sc->tx_chan_width = (!!conf->ht.sec_chan_offset) ? 2111 - ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; 2168 + if (conf->ht.enabled) { 2169 + if (conf->ht.channel_type == NL80211_CHAN_HT40PLUS || 2170 + conf->ht.channel_type == NL80211_CHAN_HT40MINUS) 2171 + sc->tx_chan_width = ATH9K_HT_MACMODE_2040; 2112 2172 2113 2173 sc->sc_ah->ah_channels[pos].chanmode = 2114 2174 ath_get_extchanmode(sc, curchan, 2115 - conf->ht.sec_chan_offset, 2116 - sc->tx_chan_width); 2175 + conf->ht.channel_type); 2117 2176 } 2118 2177 2119 2178 if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { 2120 2179 DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); 2121 2180 return -EINVAL; 2122 2181 } 2123 - } 2124 2182 2125 - if (changed & IEEE80211_CONF_CHANGE_HT) 2126 2183 ath_update_chainmask(sc, conf->ht.enabled); 2184 + } 2127 2185 2128 2186 if (changed & IEEE80211_CONF_CHANGE_POWER) 2129 2187 sc->sc_config.txpowlimit = 2 * conf->power_level; ··· 2354 2416 else 2355 2417 sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; 2356 2418 } 2357 - 2358 - if (changed & BSS_CHANGED_HT) 2359 - ath9k_ht_conf(sc, bss_conf); 2360 2419 2361 2420 if (changed & BSS_CHANGED_ASSOC) { 2362 2421 DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+13 -5
drivers/net/wireless/iwlwifi/iwl-agn.c
··· 515 515 iwl_conf->supported_chan_width = 516 516 !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); 517 517 518 - iwl_conf->extension_chan_offset = bss_conf->ht.secondary_channel_offset; 518 + /* 519 + * XXX: The HT configuration needs to be moved into iwl_mac_config() 520 + * to be done there correctly. 521 + */ 522 + 523 + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; 524 + if (priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40MINUS) 525 + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; 526 + else if(priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40PLUS) 527 + iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 528 + 519 529 /* If no above or below channel supplied disable FAT channel */ 520 530 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && 521 - iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) { 522 - iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; 531 + iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) 523 532 iwl_conf->supported_chan_width = 0; 524 - } 525 533 526 534 iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); 527 535 528 536 memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); 529 537 530 - iwl_conf->tx_chan_width = bss_conf->ht.width_40_ok; 538 + iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; 531 539 iwl_conf->ht_protection = 532 540 bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; 533 541 iwl_conf->non_GF_STA_present =
+2 -4
drivers/net/wireless/mac80211_hwsim.c
··· 495 495 } 496 496 497 497 if (changed & BSS_CHANGED_HT) { 498 - printk(KERN_DEBUG " %s: HT: sec_ch_offs=%d width_40_ok=%d " 499 - "op_mode=%d\n", 498 + printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", 500 499 wiphy_name(hw->wiphy), 501 - info->ht.secondary_channel_offset, 502 - info->ht.width_40_ok, info->ht.operation_mode); 500 + info->ht.operation_mode); 503 501 } 504 502 505 503 if (changed & BSS_CHANGED_BASIC_RATES) {
+11 -11
include/linux/nl80211.h
··· 201 201 * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) 202 202 * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters 203 203 * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz 204 - * @NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET: included with NL80211_ATTR_WIPHY_FREQ 204 + * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ 205 205 * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): 206 - * NL80211_SEC_CHAN_NO_HT = HT not allowed (i.e., same as not including 206 + * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including 207 207 * this attribute) 208 - * NL80211_SEC_CHAN_DISABLED = HT20 only 209 - * NL80211_SEC_CHAN_BELOW = secondary channel is below the primary channel 210 - * NL80211_SEC_CHAN_ABOVE = secondary channel is above the primary channel 208 + * NL80211_CHAN_HT20 = HT20 only 209 + * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel 210 + * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel 211 211 * 212 212 * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on 213 213 * @NL80211_ATTR_IFNAME: network interface name ··· 344 344 345 345 NL80211_ATTR_WIPHY_TXQ_PARAMS, 346 346 NL80211_ATTR_WIPHY_FREQ, 347 - NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET, 347 + NL80211_ATTR_WIPHY_CHANNEL_TYPE, 348 348 349 349 /* add attributes here, update the policy in nl80211.c */ 350 350 ··· 805 805 NL80211_TXQ_Q_BK 806 806 }; 807 807 808 - enum nl80211_sec_chan_offset { 809 - NL80211_SEC_CHAN_NO_HT /* No HT */, 810 - NL80211_SEC_CHAN_DISABLED /* HT20 only */, 811 - NL80211_SEC_CHAN_BELOW /* HT40- */, 812 - NL80211_SEC_CHAN_ABOVE /* HT40+ */ 808 + enum nl80211_channel_type { 809 + NL80211_CHAN_NO_HT, 810 + NL80211_CHAN_HT20, 811 + NL80211_CHAN_HT40MINUS, 812 + NL80211_CHAN_HT40PLUS 813 813 }; 814 814 #endif /* __LINUX_NL80211_H */
+1 -1
include/net/cfg80211.h
··· 563 563 564 564 int (*set_channel)(struct wiphy *wiphy, 565 565 struct ieee80211_channel *chan, 566 - enum nl80211_sec_chan_offset); 566 + enum nl80211_channel_type channel_type); 567 567 }; 568 568 569 569 /* temporary wext handlers */
+1 -8
include/net/mac80211.h
··· 165 165 166 166 /** 167 167 * struct ieee80211_bss_ht_conf - BSS's changing HT configuration 168 - * @secondary_channel_offset: secondary channel offset, uses 169 - * %IEEE80211_HT_PARAM_CHA_SEC_ values 170 - * @width_40_ok: indicates that 40 MHz bandwidth may be used for TX 171 168 * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) 172 169 */ 173 170 struct ieee80211_bss_ht_conf { 174 - u8 secondary_channel_offset; 175 - bool width_40_ok; 176 171 u16 operation_mode; 177 172 }; 178 173 ··· 503 508 504 509 struct ieee80211_ht_conf { 505 510 bool enabled; 506 - int sec_chan_offset; /* 0 = HT40 disabled; -1 = HT40 enabled, secondary 507 - * channel below primary; 1 = HT40 enabled, 508 - * secondary channel above primary */ 511 + enum nl80211_channel_type channel_type; 509 512 }; 510 513 511 514 /**
+2 -2
net/mac80211/cfg.c
··· 1122 1122 1123 1123 static int ieee80211_set_channel(struct wiphy *wiphy, 1124 1124 struct ieee80211_channel *chan, 1125 - enum nl80211_sec_chan_offset sec_chan_offset) 1125 + enum nl80211_channel_type channel_type) 1126 1126 { 1127 1127 struct ieee80211_local *local = wiphy_priv(wiphy); 1128 1128 1129 1129 local->oper_channel = chan; 1130 - local->oper_sec_chan_offset = sec_chan_offset; 1130 + local->oper_channel_type = channel_type; 1131 1131 1132 1132 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 1133 1133 }
+24 -11
net/mac80211/ht.c
··· 98 98 struct ieee80211_bss_ht_conf ht; 99 99 u32 changed = 0; 100 100 bool enable_ht = true, ht_changed; 101 + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 101 102 102 103 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 103 104 ··· 113 112 ieee80211_channel_to_frequency(hti->control_chan)) 114 113 enable_ht = false; 115 114 116 - /* 117 - * XXX: This is totally incorrect when there are multiple virtual 118 - * interfaces, needs to be fixed later. 119 - */ 120 - ht_changed = local->hw.conf.ht.enabled != enable_ht; 115 + if (enable_ht) { 116 + channel_type = NL80211_CHAN_HT20; 117 + 118 + if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && 119 + (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && 120 + (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { 121 + switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { 122 + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 123 + channel_type = NL80211_CHAN_HT40PLUS; 124 + break; 125 + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 126 + channel_type = NL80211_CHAN_HT40MINUS; 127 + break; 128 + } 129 + } 130 + } 131 + 132 + ht_changed = local->hw.conf.ht.enabled != enable_ht || 133 + channel_type != local->hw.conf.ht.channel_type; 134 + 135 + local->oper_channel_type = channel_type; 121 136 local->hw.conf.ht.enabled = enable_ht; 137 + 122 138 if (ht_changed) 123 139 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); 124 140 125 141 /* disable HT */ 126 142 if (!enable_ht) 127 143 return 0; 128 - ht.secondary_channel_offset = 129 - hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; 130 - ht.width_40_ok = 131 - !(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && 132 - (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && 133 - (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY); 144 + 134 145 ht.operation_mode = le16_to_cpu(hti->operation_mode); 135 146 136 147 /* if bss configuration changed store the new one */
+1 -1
net/mac80211/ieee80211_i.h
··· 625 625 struct delayed_work scan_work; 626 626 struct ieee80211_sub_if_data *scan_sdata; 627 627 struct ieee80211_channel *oper_channel, *scan_channel; 628 - enum nl80211_sec_chan_offset oper_sec_chan_offset; 628 + enum nl80211_channel_type oper_channel_type; 629 629 u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; 630 630 size_t scan_ssid_len; 631 631 struct list_head bss_list;
+10 -17
net/mac80211/main.c
··· 195 195 struct ieee80211_channel *chan; 196 196 int ret = 0; 197 197 int power; 198 - enum nl80211_sec_chan_offset sec_chan_offset; 198 + enum nl80211_channel_type channel_type; 199 199 200 200 might_sleep(); 201 201 202 202 if (local->sw_scanning) { 203 203 chan = local->scan_channel; 204 - sec_chan_offset = NL80211_SEC_CHAN_NO_HT; 204 + channel_type = NL80211_CHAN_NO_HT; 205 205 } else { 206 206 chan = local->oper_channel; 207 - sec_chan_offset = local->oper_sec_chan_offset; 207 + channel_type = local->oper_channel_type; 208 208 } 209 209 210 210 if (chan != local->hw.conf.channel || 211 - sec_chan_offset != local->hw.conf.ht.sec_chan_offset) { 211 + channel_type != local->hw.conf.ht.channel_type) { 212 212 local->hw.conf.channel = chan; 213 - switch (sec_chan_offset) { 214 - case NL80211_SEC_CHAN_NO_HT: 213 + local->hw.conf.ht.channel_type = channel_type; 214 + switch (channel_type) { 215 + case NL80211_CHAN_NO_HT: 215 216 local->hw.conf.ht.enabled = false; 216 - local->hw.conf.ht.sec_chan_offset = 0; 217 217 break; 218 - case NL80211_SEC_CHAN_DISABLED: 218 + case NL80211_CHAN_HT20: 219 + case NL80211_CHAN_HT40MINUS: 220 + case NL80211_CHAN_HT40PLUS: 219 221 local->hw.conf.ht.enabled = true; 220 - local->hw.conf.ht.sec_chan_offset = 0; 221 - break; 222 - case NL80211_SEC_CHAN_BELOW: 223 - local->hw.conf.ht.enabled = true; 224 - local->hw.conf.ht.sec_chan_offset = -1; 225 - break; 226 - case NL80211_SEC_CHAN_ABOVE: 227 - local->hw.conf.ht.enabled = true; 228 - local->hw.conf.ht.sec_chan_offset = 1; 229 222 break; 230 223 } 231 224 changed |= IEEE80211_CONF_CHANGE_CHANNEL;
+1
net/mac80211/mlme.c
··· 858 858 rcu_read_unlock(); 859 859 860 860 local->hw.conf.ht.enabled = false; 861 + local->oper_channel_type = NL80211_CHAN_NO_HT; 861 862 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); 862 863 863 864 ieee80211_bss_info_change_notify(sdata, changed);
+1 -1
net/mac80211/util.c
··· 641 641 chan->flags & IEEE80211_CHAN_NO_IBSS) 642 642 return ret; 643 643 local->oper_channel = chan; 644 - local->oper_sec_chan_offset = NL80211_SEC_CHAN_NO_HT; 644 + local->oper_channel_type = NL80211_CHAN_NO_HT; 645 645 646 646 if (local->sw_scanning || local->hw_scanning) 647 647 ret = 0;
+13 -14
net/wireless/nl80211.c
··· 60 60 .len = BUS_ID_SIZE-1 }, 61 61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, 62 62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, 63 - [NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET] = { .type = NLA_U32 }, 63 + [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, 64 64 65 65 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 66 66 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, ··· 362 362 } 363 363 364 364 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { 365 - enum nl80211_sec_chan_offset sec_chan_offset = 366 - NL80211_SEC_CHAN_NO_HT; 365 + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 367 366 struct ieee80211_channel *chan; 368 367 struct ieee80211_sta_ht_cap *ht_cap; 369 368 u32 freq, sec_freq; ··· 374 375 375 376 result = -EINVAL; 376 377 377 - if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) { 378 - sec_chan_offset = nla_get_u32(info->attrs[ 379 - NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]); 380 - if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && 381 - sec_chan_offset != NL80211_SEC_CHAN_DISABLED && 382 - sec_chan_offset != NL80211_SEC_CHAN_BELOW && 383 - sec_chan_offset != NL80211_SEC_CHAN_ABOVE) 378 + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { 379 + channel_type = nla_get_u32(info->attrs[ 380 + NL80211_ATTR_WIPHY_CHANNEL_TYPE]); 381 + if (channel_type != NL80211_CHAN_NO_HT && 382 + channel_type != NL80211_CHAN_HT20 && 383 + channel_type != NL80211_CHAN_HT40PLUS && 384 + channel_type != NL80211_CHAN_HT40MINUS) 384 385 goto bad_res; 385 386 } 386 387 ··· 391 392 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) 392 393 goto bad_res; 393 394 394 - if (sec_chan_offset == NL80211_SEC_CHAN_BELOW) 395 + if (channel_type == NL80211_CHAN_HT40MINUS) 395 396 sec_freq = freq - 20; 396 - else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE) 397 + else if (channel_type == NL80211_CHAN_HT40PLUS) 397 398 sec_freq = freq + 20; 398 399 else 399 400 sec_freq = 0; ··· 401 402 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; 402 403 403 404 /* no HT capabilities */ 404 - if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && 405 + if (channel_type != NL80211_CHAN_NO_HT && 405 406 !ht_cap->ht_supported) 406 407 goto bad_res; 407 408 ··· 421 422 } 422 423 423 424 result = rdev->ops->set_channel(&rdev->wiphy, chan, 424 - sec_chan_offset); 425 + channel_type); 425 426 if (result) 426 427 goto bad_res; 427 428 }