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 /drivers | |
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>
Diffstat (limited to 'drivers')
-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 |
3 files changed, 44 insertions, 103 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) { |