diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2008-12-12 01:27:43 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-12-19 15:22:54 -0500 |
commit | 094d05dc32fc2930e381189a942016e5561775d9 (patch) | |
tree | 4deedbcbe196f88cb8d9fe0cd0755775a7ff0939 | |
parent | 420e7fabd9c6d907280ed6b3e40eef425c5d8d8d (diff) |
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>
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 123 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 6 | ||||
-rw-r--r-- | include/linux/nl80211.h | 22 | ||||
-rw-r--r-- | include/net/cfg80211.h | 2 | ||||
-rw-r--r-- | include/net/mac80211.h | 9 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 4 | ||||
-rw-r--r-- | net/mac80211/ht.c | 35 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 27 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 1 | ||||
-rw-r--r-- | net/mac80211/util.c | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 27 |
13 files changed, 109 insertions, 169 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 02e1771bb274..e22fea18bad6 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -623,37 +623,40 @@ static int ath_get_channel(struct ath_softc *sc, | |||
623 | return -1; | 623 | return -1; |
624 | } | 624 | } |
625 | 625 | ||
626 | /* ext_chan_offset: (-1, 0, 1) (below, none, above) */ | ||
627 | |||
628 | static u32 ath_get_extchanmode(struct ath_softc *sc, | 626 | static u32 ath_get_extchanmode(struct ath_softc *sc, |
629 | struct ieee80211_channel *chan, | 627 | struct ieee80211_channel *chan, |
630 | int ext_chan_offset, | 628 | enum nl80211_channel_type channel_type) |
631 | enum ath9k_ht_macmode tx_chan_width) | ||
632 | { | 629 | { |
633 | u32 chanmode = 0; | 630 | u32 chanmode = 0; |
634 | 631 | ||
635 | switch (chan->band) { | 632 | switch (chan->band) { |
636 | case IEEE80211_BAND_2GHZ: | 633 | case IEEE80211_BAND_2GHZ: |
637 | if ((ext_chan_offset == 0) && | 634 | switch(channel_type) { |
638 | (tx_chan_width == ATH9K_HT_MACMODE_20)) | 635 | case NL80211_CHAN_NO_HT: |
636 | case NL80211_CHAN_HT20: | ||
639 | chanmode = CHANNEL_G_HT20; | 637 | chanmode = CHANNEL_G_HT20; |
640 | if ((ext_chan_offset == 1) && | 638 | break; |
641 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 639 | case NL80211_CHAN_HT40PLUS: |
642 | chanmode = CHANNEL_G_HT40PLUS; | 640 | chanmode = CHANNEL_G_HT40PLUS; |
643 | if ((ext_chan_offset == -1) && | 641 | break; |
644 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 642 | case NL80211_CHAN_HT40MINUS: |
645 | chanmode = CHANNEL_G_HT40MINUS; | 643 | chanmode = CHANNEL_G_HT40MINUS; |
644 | break; | ||
645 | } | ||
646 | break; | 646 | break; |
647 | case IEEE80211_BAND_5GHZ: | 647 | case IEEE80211_BAND_5GHZ: |
648 | if ((ext_chan_offset == 0) && | 648 | switch(channel_type) { |
649 | (tx_chan_width == ATH9K_HT_MACMODE_20)) | 649 | case NL80211_CHAN_NO_HT: |
650 | case NL80211_CHAN_HT20: | ||
650 | chanmode = CHANNEL_A_HT20; | 651 | chanmode = CHANNEL_A_HT20; |
651 | if ((ext_chan_offset == 1) && | 652 | break; |
652 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 653 | case NL80211_CHAN_HT40PLUS: |
653 | chanmode = CHANNEL_A_HT40PLUS; | 654 | chanmode = CHANNEL_A_HT40PLUS; |
654 | if ((ext_chan_offset == -1) && | 655 | break; |
655 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 656 | case NL80211_CHAN_HT40MINUS: |
656 | chanmode = CHANNEL_A_HT40MINUS; | 657 | chanmode = CHANNEL_A_HT40MINUS; |
658 | break; | ||
659 | } | ||
657 | break; | 660 | break; |
658 | default: | 661 | default: |
659 | break; | 662 | break; |
@@ -829,45 +832,15 @@ static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) | |||
829 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 832 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
830 | } | 833 | } |
831 | 834 | ||
832 | static void ath9k_ht_conf(struct ath_softc *sc, | ||
833 | struct ieee80211_bss_conf *bss_conf) | ||
834 | { | ||
835 | if (sc->hw->conf.ht.enabled) { | ||
836 | if (bss_conf->ht.width_40_ok) | ||
837 | sc->tx_chan_width = ATH9K_HT_MACMODE_2040; | ||
838 | else | ||
839 | sc->tx_chan_width = ATH9K_HT_MACMODE_20; | ||
840 | |||
841 | ath9k_hw_set11nmac2040(sc->sc_ah, sc->tx_chan_width); | ||
842 | |||
843 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
844 | "BSS Changed HT, chanwidth: %d\n", sc->tx_chan_width); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | static inline int ath_sec_offset(u8 ext_offset) | ||
849 | { | ||
850 | if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) | ||
851 | return 0; | ||
852 | else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | ||
853 | return 1; | ||
854 | else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
855 | return -1; | ||
856 | |||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | 835 | static void ath9k_bss_assoc_info(struct ath_softc *sc, |
861 | struct ieee80211_vif *vif, | 836 | struct ieee80211_vif *vif, |
862 | struct ieee80211_bss_conf *bss_conf) | 837 | struct ieee80211_bss_conf *bss_conf) |
863 | { | 838 | { |
864 | struct ieee80211_hw *hw = sc->hw; | ||
865 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
866 | struct ath_vap *avp = (void *)vif->drv_priv; | 839 | struct ath_vap *avp = (void *)vif->drv_priv; |
867 | int pos; | ||
868 | 840 | ||
869 | if (bss_conf->assoc) { | 841 | if (bss_conf->assoc) { |
870 | DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d\n", bss_conf->aid); | 842 | DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", |
843 | bss_conf->aid, sc->sc_curbssid); | ||
871 | 844 | ||
872 | /* New association, store aid */ | 845 | /* New association, store aid */ |
873 | if (avp->av_opmode == NL80211_IFTYPE_STATION) { | 846 | if (avp->av_opmode == NL80211_IFTYPE_STATION) { |
@@ -886,40 +859,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
886 | sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; | 859 | sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; |
887 | sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; | 860 | sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; |
888 | 861 | ||
889 | /* Update chainmask */ | ||
890 | ath_update_chainmask(sc, hw->conf.ht.enabled); | ||
891 | |||
892 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
893 | "bssid %pM aid 0x%x\n", | ||
894 | sc->sc_curbssid, sc->sc_curaid); | ||
895 | |||
896 | pos = ath_get_channel(sc, curchan); | ||
897 | if (pos == -1) { | ||
898 | DPRINTF(sc, ATH_DBG_FATAL, | ||
899 | "Invalid channel: %d\n", curchan->center_freq); | ||
900 | return; | ||
901 | } | ||
902 | |||
903 | if (hw->conf.ht.enabled) { | ||
904 | int offset = | ||
905 | ath_sec_offset(bss_conf->ht.secondary_channel_offset); | ||
906 | sc->tx_chan_width = (bss_conf->ht.width_40_ok) ? | ||
907 | ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; | ||
908 | |||
909 | sc->sc_ah->ah_channels[pos].chanmode = | ||
910 | ath_get_extchanmode(sc, curchan, | ||
911 | offset, sc->tx_chan_width); | ||
912 | } else { | ||
913 | sc->sc_ah->ah_channels[pos].chanmode = | ||
914 | (curchan->band == IEEE80211_BAND_2GHZ) ? | ||
915 | CHANNEL_G : CHANNEL_A; | ||
916 | } | ||
917 | |||
918 | /* set h/w channel */ | ||
919 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | ||
920 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel: %d\n", | ||
921 | curchan->center_freq); | ||
922 | |||
923 | /* Start ANI */ | 862 | /* Start ANI */ |
924 | mod_timer(&sc->sc_ani.timer, | 863 | mod_timer(&sc->sc_ani.timer, |
925 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 864 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
@@ -2146,7 +2085,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2146 | struct ath_softc *sc = hw->priv; | 2085 | struct ath_softc *sc = hw->priv; |
2147 | struct ieee80211_conf *conf = &hw->conf; | 2086 | struct ieee80211_conf *conf = &hw->conf; |
2148 | 2087 | ||
2149 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 2088 | if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | |
2089 | IEEE80211_CONF_CHANGE_HT)) { | ||
2150 | struct ieee80211_channel *curchan = hw->conf.channel; | 2090 | struct ieee80211_channel *curchan = hw->conf.channel; |
2151 | int pos; | 2091 | int pos; |
2152 | 2092 | ||
@@ -2165,25 +2105,23 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2165 | (curchan->band == IEEE80211_BAND_2GHZ) ? | 2105 | (curchan->band == IEEE80211_BAND_2GHZ) ? |
2166 | CHANNEL_G : CHANNEL_A; | 2106 | CHANNEL_G : CHANNEL_A; |
2167 | 2107 | ||
2168 | if ((sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) && | 2108 | if (conf->ht.enabled) { |
2169 | (conf->ht.enabled)) { | 2109 | if (conf->ht.channel_type == NL80211_CHAN_HT40PLUS || |
2170 | sc->tx_chan_width = (!!conf->ht.sec_chan_offset) ? | 2110 | conf->ht.channel_type == NL80211_CHAN_HT40MINUS) |
2171 | ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; | 2111 | sc->tx_chan_width = ATH9K_HT_MACMODE_2040; |
2172 | 2112 | ||
2173 | sc->sc_ah->ah_channels[pos].chanmode = | 2113 | sc->sc_ah->ah_channels[pos].chanmode = |
2174 | ath_get_extchanmode(sc, curchan, | 2114 | ath_get_extchanmode(sc, curchan, |
2175 | conf->ht.sec_chan_offset, | 2115 | conf->ht.channel_type); |
2176 | sc->tx_chan_width); | ||
2177 | } | 2116 | } |
2178 | 2117 | ||
2179 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { | 2118 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { |
2180 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); | 2119 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); |
2181 | return -EINVAL; | 2120 | return -EINVAL; |
2182 | } | 2121 | } |
2183 | } | ||
2184 | 2122 | ||
2185 | if (changed & IEEE80211_CONF_CHANGE_HT) | ||
2186 | ath_update_chainmask(sc, conf->ht.enabled); | 2123 | ath_update_chainmask(sc, conf->ht.enabled); |
2124 | } | ||
2187 | 2125 | ||
2188 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2126 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
2189 | sc->sc_config.txpowlimit = 2 * conf->power_level; | 2127 | sc->sc_config.txpowlimit = 2 * conf->power_level; |
@@ -2417,9 +2355,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2417 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; | 2355 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; |
2418 | } | 2356 | } |
2419 | 2357 | ||
2420 | if (changed & BSS_CHANGED_HT) | ||
2421 | ath9k_ht_conf(sc, bss_conf); | ||
2422 | |||
2423 | if (changed & BSS_CHANGED_ASSOC) { | 2358 | if (changed & BSS_CHANGED_ASSOC) { |
2424 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", | 2359 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", |
2425 | bss_conf->assoc); | 2360 | bss_conf->assoc); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2f5e86e12916..bbc1c8052ffa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -515,19 +515,27 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
515 | iwl_conf->supported_chan_width = | 515 | iwl_conf->supported_chan_width = |
516 | !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); | 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 | /* If no above or below channel supplied disable FAT channel */ | 529 | /* If no above or below channel supplied disable FAT channel */ |
520 | if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && | 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) { | 531 | iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) |
522 | iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
523 | iwl_conf->supported_chan_width = 0; | 532 | iwl_conf->supported_chan_width = 0; |
524 | } | ||
525 | 533 | ||
526 | iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); | 534 | iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); |
527 | 535 | ||
528 | memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); | 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 | iwl_conf->ht_protection = | 539 | iwl_conf->ht_protection = |
532 | bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | 540 | bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; |
533 | iwl_conf->non_GF_STA_present = | 541 | iwl_conf->non_GF_STA_present = |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fd5a537ac51d..f83d69e813d3 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -495,11 +495,9 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
495 | } | 495 | } |
496 | 496 | ||
497 | if (changed & BSS_CHANGED_HT) { | 497 | if (changed & BSS_CHANGED_HT) { |
498 | printk(KERN_DEBUG " %s: HT: sec_ch_offs=%d width_40_ok=%d " | 498 | printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", |
499 | "op_mode=%d\n", | ||
500 | wiphy_name(hw->wiphy), | 499 | wiphy_name(hw->wiphy), |
501 | info->ht.secondary_channel_offset, | 500 | info->ht.operation_mode); |
502 | info->ht.width_40_ok, info->ht.operation_mode); | ||
503 | } | 501 | } |
504 | 502 | ||
505 | if (changed & BSS_CHANGED_BASIC_RATES) { | 503 | if (changed & BSS_CHANGED_BASIC_RATES) { |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 7501acfcfdc4..e86ed59f9ad5 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -201,13 +201,13 @@ enum nl80211_commands { | |||
201 | * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) | 201 | * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) |
202 | * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters | 202 | * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters |
203 | * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz | 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 | * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): | 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 | * this attribute) | 207 | * this attribute) |
208 | * NL80211_SEC_CHAN_DISABLED = HT20 only | 208 | * NL80211_CHAN_HT20 = HT20 only |
209 | * NL80211_SEC_CHAN_BELOW = secondary channel is below the primary channel | 209 | * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel |
210 | * NL80211_SEC_CHAN_ABOVE = secondary channel is above the primary channel | 210 | * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel |
211 | * | 211 | * |
212 | * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on | 212 | * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on |
213 | * @NL80211_ATTR_IFNAME: network interface name | 213 | * @NL80211_ATTR_IFNAME: network interface name |
@@ -344,7 +344,7 @@ enum nl80211_attrs { | |||
344 | 344 | ||
345 | NL80211_ATTR_WIPHY_TXQ_PARAMS, | 345 | NL80211_ATTR_WIPHY_TXQ_PARAMS, |
346 | NL80211_ATTR_WIPHY_FREQ, | 346 | NL80211_ATTR_WIPHY_FREQ, |
347 | NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET, | 347 | NL80211_ATTR_WIPHY_CHANNEL_TYPE, |
348 | 348 | ||
349 | /* add attributes here, update the policy in nl80211.c */ | 349 | /* add attributes here, update the policy in nl80211.c */ |
350 | 350 | ||
@@ -805,10 +805,10 @@ enum nl80211_txq_q { | |||
805 | NL80211_TXQ_Q_BK | 805 | NL80211_TXQ_Q_BK |
806 | }; | 806 | }; |
807 | 807 | ||
808 | enum nl80211_sec_chan_offset { | 808 | enum nl80211_channel_type { |
809 | NL80211_SEC_CHAN_NO_HT /* No HT */, | 809 | NL80211_CHAN_NO_HT, |
810 | NL80211_SEC_CHAN_DISABLED /* HT20 only */, | 810 | NL80211_CHAN_HT20, |
811 | NL80211_SEC_CHAN_BELOW /* HT40- */, | 811 | NL80211_CHAN_HT40MINUS, |
812 | NL80211_SEC_CHAN_ABOVE /* HT40+ */ | 812 | NL80211_CHAN_HT40PLUS |
813 | }; | 813 | }; |
814 | #endif /* __LINUX_NL80211_H */ | 814 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 65e03ac93109..23c0ab74ded6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -563,7 +563,7 @@ struct cfg80211_ops { | |||
563 | 563 | ||
564 | int (*set_channel)(struct wiphy *wiphy, | 564 | int (*set_channel)(struct wiphy *wiphy, |
565 | struct ieee80211_channel *chan, | 565 | struct ieee80211_channel *chan, |
566 | enum nl80211_sec_chan_offset); | 566 | enum nl80211_channel_type channel_type); |
567 | }; | 567 | }; |
568 | 568 | ||
569 | /* temporary wext handlers */ | 569 | /* temporary wext handlers */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 046ce692a906..22ae72c58d76 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -165,14 +165,9 @@ enum ieee80211_bss_change { | |||
165 | 165 | ||
166 | /** | 166 | /** |
167 | * struct ieee80211_bss_ht_conf - BSS's changing HT configuration | 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 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) | 168 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) |
172 | */ | 169 | */ |
173 | struct ieee80211_bss_ht_conf { | 170 | struct ieee80211_bss_ht_conf { |
174 | u8 secondary_channel_offset; | ||
175 | bool width_40_ok; | ||
176 | u16 operation_mode; | 171 | u16 operation_mode; |
177 | }; | 172 | }; |
178 | 173 | ||
@@ -508,9 +503,7 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) | |||
508 | 503 | ||
509 | struct ieee80211_ht_conf { | 504 | struct ieee80211_ht_conf { |
510 | bool enabled; | 505 | bool enabled; |
511 | int sec_chan_offset; /* 0 = HT40 disabled; -1 = HT40 enabled, secondary | 506 | enum nl80211_channel_type channel_type; |
512 | * channel below primary; 1 = HT40 enabled, | ||
513 | * secondary channel above primary */ | ||
514 | }; | 507 | }; |
515 | 508 | ||
516 | /** | 509 | /** |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 23b5eeaf7bc5..3ea0884c9432 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1122,12 +1122,12 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1122 | 1122 | ||
1123 | static int ieee80211_set_channel(struct wiphy *wiphy, | 1123 | static int ieee80211_set_channel(struct wiphy *wiphy, |
1124 | struct ieee80211_channel *chan, | 1124 | struct ieee80211_channel *chan, |
1125 | enum nl80211_sec_chan_offset sec_chan_offset) | 1125 | enum nl80211_channel_type channel_type) |
1126 | { | 1126 | { |
1127 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1127 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1128 | 1128 | ||
1129 | local->oper_channel = chan; | 1129 | local->oper_channel = chan; |
1130 | local->oper_sec_chan_offset = sec_chan_offset; | 1130 | local->oper_channel_type = channel_type; |
1131 | 1131 | ||
1132 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1132 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1133 | } | 1133 | } |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index a1eed7032c9b..5f510a13b9f0 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -98,6 +98,7 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
98 | struct ieee80211_bss_ht_conf ht; | 98 | struct ieee80211_bss_ht_conf ht; |
99 | u32 changed = 0; | 99 | u32 changed = 0; |
100 | bool enable_ht = true, ht_changed; | 100 | bool enable_ht = true, ht_changed; |
101 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
101 | 102 | ||
102 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 103 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
103 | 104 | ||
@@ -112,24 +113,36 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
112 | ieee80211_channel_to_frequency(hti->control_chan)) | 113 | ieee80211_channel_to_frequency(hti->control_chan)) |
113 | enable_ht = false; | 114 | enable_ht = false; |
114 | 115 | ||
115 | /* | 116 | if (enable_ht) { |
116 | * XXX: This is totally incorrect when there are multiple virtual | 117 | channel_type = NL80211_CHAN_HT20; |
117 | * interfaces, needs to be fixed later. | 118 | |
118 | */ | 119 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && |
119 | ht_changed = local->hw.conf.ht.enabled != enable_ht; | 120 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && |
121 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | ||
122 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
123 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
124 | channel_type = NL80211_CHAN_HT40PLUS; | ||
125 | break; | ||
126 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
127 | channel_type = NL80211_CHAN_HT40MINUS; | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
133 | ht_changed = local->hw.conf.ht.enabled != enable_ht || | ||
134 | channel_type != local->hw.conf.ht.channel_type; | ||
135 | |||
136 | local->oper_channel_type = channel_type; | ||
120 | local->hw.conf.ht.enabled = enable_ht; | 137 | local->hw.conf.ht.enabled = enable_ht; |
138 | |||
121 | if (ht_changed) | 139 | if (ht_changed) |
122 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); | 140 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); |
123 | 141 | ||
124 | /* disable HT */ | 142 | /* disable HT */ |
125 | if (!enable_ht) | 143 | if (!enable_ht) |
126 | return 0; | 144 | return 0; |
127 | ht.secondary_channel_offset = | 145 | |
128 | hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
129 | ht.width_40_ok = | ||
130 | !(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | ||
131 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && | ||
132 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY); | ||
133 | ht.operation_mode = le16_to_cpu(hti->operation_mode); | 146 | ht.operation_mode = le16_to_cpu(hti->operation_mode); |
134 | 147 | ||
135 | /* if bss configuration changed store the new one */ | 148 | /* if bss configuration changed store the new one */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6f59e11d7b33..a7dabaecfc72 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -625,7 +625,7 @@ struct ieee80211_local { | |||
625 | struct delayed_work scan_work; | 625 | struct delayed_work scan_work; |
626 | struct ieee80211_sub_if_data *scan_sdata; | 626 | struct ieee80211_sub_if_data *scan_sdata; |
627 | struct ieee80211_channel *oper_channel, *scan_channel; | 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 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 629 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
630 | size_t scan_ssid_len; | 630 | size_t scan_ssid_len; |
631 | struct list_head bss_list; | 631 | struct list_head bss_list; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6d8710327d14..a0371caf01ce 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -195,37 +195,30 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
195 | struct ieee80211_channel *chan; | 195 | struct ieee80211_channel *chan; |
196 | int ret = 0; | 196 | int ret = 0; |
197 | int power; | 197 | int power; |
198 | enum nl80211_sec_chan_offset sec_chan_offset; | 198 | enum nl80211_channel_type channel_type; |
199 | 199 | ||
200 | might_sleep(); | 200 | might_sleep(); |
201 | 201 | ||
202 | if (local->sw_scanning) { | 202 | if (local->sw_scanning) { |
203 | chan = local->scan_channel; | 203 | chan = local->scan_channel; |
204 | sec_chan_offset = NL80211_SEC_CHAN_NO_HT; | 204 | channel_type = NL80211_CHAN_NO_HT; |
205 | } else { | 205 | } else { |
206 | chan = local->oper_channel; | 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 | if (chan != local->hw.conf.channel || | 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 | local->hw.conf.channel = chan; | 212 | local->hw.conf.channel = chan; |
213 | switch (sec_chan_offset) { | 213 | local->hw.conf.ht.channel_type = channel_type; |
214 | case NL80211_SEC_CHAN_NO_HT: | 214 | switch (channel_type) { |
215 | case NL80211_CHAN_NO_HT: | ||
215 | local->hw.conf.ht.enabled = false; | 216 | local->hw.conf.ht.enabled = false; |
216 | local->hw.conf.ht.sec_chan_offset = 0; | ||
217 | break; | 217 | break; |
218 | case NL80211_SEC_CHAN_DISABLED: | 218 | case NL80211_CHAN_HT20: |
219 | case NL80211_CHAN_HT40MINUS: | ||
220 | case NL80211_CHAN_HT40PLUS: | ||
219 | local->hw.conf.ht.enabled = true; | 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 | break; | 222 | break; |
230 | } | 223 | } |
231 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 224 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 290b0017ef2e..e4d1fca5c72d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -858,6 +858,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
858 | rcu_read_unlock(); | 858 | rcu_read_unlock(); |
859 | 859 | ||
860 | local->hw.conf.ht.enabled = false; | 860 | local->hw.conf.ht.enabled = false; |
861 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
861 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); | 862 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); |
862 | 863 | ||
863 | ieee80211_bss_info_change_notify(sdata, changed); | 864 | ieee80211_bss_info_change_notify(sdata, changed); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 505d68f344ce..71a8391c54f6 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -641,7 +641,7 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | |||
641 | chan->flags & IEEE80211_CHAN_NO_IBSS) | 641 | chan->flags & IEEE80211_CHAN_NO_IBSS) |
642 | return ret; | 642 | return ret; |
643 | local->oper_channel = chan; | 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 | if (local->sw_scanning || local->hw_scanning) | 646 | if (local->sw_scanning || local->hw_scanning) |
647 | ret = 0; | 647 | ret = 0; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 93c9b983ce08..1e728fff474e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -60,7 +60,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
60 | .len = BUS_ID_SIZE-1 }, | 60 | .len = BUS_ID_SIZE-1 }, |
61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | 61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, |
62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, | 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 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, | 65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, |
66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, | 66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
@@ -362,8 +362,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
362 | } | 362 | } |
363 | 363 | ||
364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
365 | enum nl80211_sec_chan_offset sec_chan_offset = | 365 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
366 | NL80211_SEC_CHAN_NO_HT; | ||
367 | struct ieee80211_channel *chan; | 366 | struct ieee80211_channel *chan; |
368 | struct ieee80211_sta_ht_cap *ht_cap; | 367 | struct ieee80211_sta_ht_cap *ht_cap; |
369 | u32 freq, sec_freq; | 368 | u32 freq, sec_freq; |
@@ -375,13 +374,13 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
375 | 374 | ||
376 | result = -EINVAL; | 375 | result = -EINVAL; |
377 | 376 | ||
378 | if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) { | 377 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
379 | sec_chan_offset = nla_get_u32(info->attrs[ | 378 | channel_type = nla_get_u32(info->attrs[ |
380 | NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]); | 379 | NL80211_ATTR_WIPHY_CHANNEL_TYPE]); |
381 | if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && | 380 | if (channel_type != NL80211_CHAN_NO_HT && |
382 | sec_chan_offset != NL80211_SEC_CHAN_DISABLED && | 381 | channel_type != NL80211_CHAN_HT20 && |
383 | sec_chan_offset != NL80211_SEC_CHAN_BELOW && | 382 | channel_type != NL80211_CHAN_HT40PLUS && |
384 | sec_chan_offset != NL80211_SEC_CHAN_ABOVE) | 383 | channel_type != NL80211_CHAN_HT40MINUS) |
385 | goto bad_res; | 384 | goto bad_res; |
386 | } | 385 | } |
387 | 386 | ||
@@ -392,9 +391,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
392 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | 391 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) |
393 | goto bad_res; | 392 | goto bad_res; |
394 | 393 | ||
395 | if (sec_chan_offset == NL80211_SEC_CHAN_BELOW) | 394 | if (channel_type == NL80211_CHAN_HT40MINUS) |
396 | sec_freq = freq - 20; | 395 | sec_freq = freq - 20; |
397 | else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE) | 396 | else if (channel_type == NL80211_CHAN_HT40PLUS) |
398 | sec_freq = freq + 20; | 397 | sec_freq = freq + 20; |
399 | else | 398 | else |
400 | sec_freq = 0; | 399 | sec_freq = 0; |
@@ -402,7 +401,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
402 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; | 401 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; |
403 | 402 | ||
404 | /* no HT capabilities */ | 403 | /* no HT capabilities */ |
405 | if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && | 404 | if (channel_type != NL80211_CHAN_NO_HT && |
406 | !ht_cap->ht_supported) | 405 | !ht_cap->ht_supported) |
407 | goto bad_res; | 406 | goto bad_res; |
408 | 407 | ||
@@ -422,7 +421,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
422 | } | 421 | } |
423 | 422 | ||
424 | result = rdev->ops->set_channel(&rdev->wiphy, chan, | 423 | result = rdev->ops->set_channel(&rdev->wiphy, chan, |
425 | sec_chan_offset); | 424 | channel_type); |
426 | if (result) | 425 | if (result) |
427 | goto bad_res; | 426 | goto bad_res; |
428 | } | 427 | } |