diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2008-11-26 23:16:27 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-12-05 09:32:59 -0500 |
commit | e11602b7813502bf363c40cdb5a8c4b96d4bbc96 (patch) | |
tree | f5cf351d596f9e99dc6cdf83fb1faec9de0e18a5 | |
parent | cb3da8ccc464409e3b947557cdac4cd0b1241c4c (diff) |
ath9k: Handle channel initialization for AP mode
Hostapd now passes the HT parameters through the config()
callback, use these to set the appropriate channel in AP mode.
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 | 60 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/rc.c | 55 |
2 files changed, 91 insertions, 24 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 437e38a3c6d..e05eb1f0789 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -622,35 +622,35 @@ static int ath_get_channel(struct ath_softc *sc, | |||
622 | return -1; | 622 | return -1; |
623 | } | 623 | } |
624 | 624 | ||
625 | /* ext_chan_offset: (-1, 0, 1) (below, none, above) */ | ||
626 | |||
625 | static u32 ath_get_extchanmode(struct ath_softc *sc, | 627 | static u32 ath_get_extchanmode(struct ath_softc *sc, |
626 | struct ieee80211_channel *chan, | 628 | struct ieee80211_channel *chan, |
627 | struct ieee80211_bss_conf *bss_conf) | 629 | int ext_chan_offset, |
630 | enum ath9k_ht_macmode tx_chan_width) | ||
628 | { | 631 | { |
629 | u32 chanmode = 0; | 632 | u32 chanmode = 0; |
630 | u8 ext_chan_offset = bss_conf->ht.secondary_channel_offset; | ||
631 | enum ath9k_ht_macmode tx_chan_width = (bss_conf->ht.width_40_ok) ? | ||
632 | ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; | ||
633 | 633 | ||
634 | switch (chan->band) { | 634 | switch (chan->band) { |
635 | case IEEE80211_BAND_2GHZ: | 635 | case IEEE80211_BAND_2GHZ: |
636 | if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) && | 636 | if ((ext_chan_offset == 0) && |
637 | (tx_chan_width == ATH9K_HT_MACMODE_20)) | 637 | (tx_chan_width == ATH9K_HT_MACMODE_20)) |
638 | chanmode = CHANNEL_G_HT20; | 638 | chanmode = CHANNEL_G_HT20; |
639 | if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) && | 639 | if ((ext_chan_offset == 1) && |
640 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 640 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) |
641 | chanmode = CHANNEL_G_HT40PLUS; | 641 | chanmode = CHANNEL_G_HT40PLUS; |
642 | if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) && | 642 | if ((ext_chan_offset == -1) && |
643 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 643 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) |
644 | chanmode = CHANNEL_G_HT40MINUS; | 644 | chanmode = CHANNEL_G_HT40MINUS; |
645 | break; | 645 | break; |
646 | case IEEE80211_BAND_5GHZ: | 646 | case IEEE80211_BAND_5GHZ: |
647 | if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) && | 647 | if ((ext_chan_offset == 0) && |
648 | (tx_chan_width == ATH9K_HT_MACMODE_20)) | 648 | (tx_chan_width == ATH9K_HT_MACMODE_20)) |
649 | chanmode = CHANNEL_A_HT20; | 649 | chanmode = CHANNEL_A_HT20; |
650 | if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) && | 650 | if ((ext_chan_offset == 1) && |
651 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 651 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) |
652 | chanmode = CHANNEL_A_HT40PLUS; | 652 | chanmode = CHANNEL_A_HT40PLUS; |
653 | if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) && | 653 | if ((ext_chan_offset == -1) && |
654 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 654 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) |
655 | chanmode = CHANNEL_A_HT40MINUS; | 655 | chanmode = CHANNEL_A_HT40MINUS; |
656 | break; | 656 | break; |
@@ -841,6 +841,18 @@ static void ath9k_ht_conf(struct ath_softc *sc, | |||
841 | } | 841 | } |
842 | } | 842 | } |
843 | 843 | ||
844 | static inline int ath_sec_offset(u8 ext_offset) | ||
845 | { | ||
846 | if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) | ||
847 | return 0; | ||
848 | else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | ||
849 | return 1; | ||
850 | else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
851 | return -1; | ||
852 | |||
853 | return 0; | ||
854 | } | ||
855 | |||
844 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | 856 | static void ath9k_bss_assoc_info(struct ath_softc *sc, |
845 | struct ieee80211_vif *vif, | 857 | struct ieee80211_vif *vif, |
846 | struct ieee80211_bss_conf *bss_conf) | 858 | struct ieee80211_bss_conf *bss_conf) |
@@ -892,13 +904,14 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
892 | } | 904 | } |
893 | 905 | ||
894 | if (hw->conf.ht.enabled) { | 906 | if (hw->conf.ht.enabled) { |
895 | sc->sc_ah->ah_channels[pos].chanmode = | 907 | int offset = |
896 | ath_get_extchanmode(sc, curchan, bss_conf); | 908 | ath_sec_offset(bss_conf->ht.secondary_channel_offset); |
909 | sc->tx_chan_width = (bss_conf->ht.width_40_ok) ? | ||
910 | ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; | ||
897 | 911 | ||
898 | if (bss_conf->ht.width_40_ok) | 912 | sc->sc_ah->ah_channels[pos].chanmode = |
899 | sc->tx_chan_width = ATH9K_HT_MACMODE_2040; | 913 | ath_get_extchanmode(sc, curchan, |
900 | else | 914 | offset, sc->tx_chan_width); |
901 | sc->tx_chan_width = ATH9K_HT_MACMODE_20; | ||
902 | } else { | 915 | } else { |
903 | sc->sc_ah->ah_channels[pos].chanmode = | 916 | sc->sc_ah->ah_channels[pos].chanmode = |
904 | (curchan->band == IEEE80211_BAND_2GHZ) ? | 917 | (curchan->band == IEEE80211_BAND_2GHZ) ? |
@@ -2171,9 +2184,22 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2171 | (curchan->band == IEEE80211_BAND_2GHZ) ? | 2184 | (curchan->band == IEEE80211_BAND_2GHZ) ? |
2172 | CHANNEL_G : CHANNEL_A; | 2185 | CHANNEL_G : CHANNEL_A; |
2173 | 2186 | ||
2174 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | 2187 | if ((sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) && |
2188 | (conf->ht.enabled)) { | ||
2189 | sc->tx_chan_width = (!!conf->ht.sec_chan_offset) ? | ||
2190 | ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; | ||
2191 | |||
2192 | sc->sc_ah->ah_channels[pos].chanmode = | ||
2193 | ath_get_extchanmode(sc, curchan, | ||
2194 | conf->ht.sec_chan_offset, | ||
2195 | sc->tx_chan_width); | ||
2196 | } | ||
2197 | |||
2198 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { | ||
2175 | DPRINTF(sc, ATH_DBG_FATAL, | 2199 | DPRINTF(sc, ATH_DBG_FATAL, |
2176 | "%s: Unable to set channel\n", __func__); | 2200 | "%s: Unable to set channel\n", __func__); |
2201 | return -EINVAL; | ||
2202 | } | ||
2177 | } | 2203 | } |
2178 | 2204 | ||
2179 | if (changed & IEEE80211_CONF_CHANGE_HT) | 2205 | if (changed & IEEE80211_CONF_CHANGE_HT) |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 93dfea897ff..7c08583a794 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -1304,6 +1304,38 @@ static void ath_rc_tx_status(struct ath_softc *sc, | |||
1304 | xretries, long_retry); | 1304 | xretries, long_retry); |
1305 | } | 1305 | } |
1306 | 1306 | ||
1307 | static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, | ||
1308 | enum ieee80211_band band, | ||
1309 | bool is_ht, bool is_cw_40) | ||
1310 | { | ||
1311 | int mode = 0; | ||
1312 | |||
1313 | switch(band) { | ||
1314 | case IEEE80211_BAND_2GHZ: | ||
1315 | mode = ATH9K_MODE_11G; | ||
1316 | if (is_ht) | ||
1317 | mode = ATH9K_MODE_11NG_HT20; | ||
1318 | if (is_cw_40) | ||
1319 | mode = ATH9K_MODE_11NG_HT40PLUS; | ||
1320 | break; | ||
1321 | case IEEE80211_BAND_5GHZ: | ||
1322 | mode = ATH9K_MODE_11A; | ||
1323 | if (is_ht) | ||
1324 | mode = ATH9K_MODE_11NA_HT20; | ||
1325 | if (is_cw_40) | ||
1326 | mode = ATH9K_MODE_11NA_HT40PLUS; | ||
1327 | break; | ||
1328 | default: | ||
1329 | DPRINTF(sc, ATH_DBG_RATE, "Invalid band\n"); | ||
1330 | return NULL; | ||
1331 | } | ||
1332 | |||
1333 | BUG_ON(mode >= ATH9K_MODE_MAX); | ||
1334 | |||
1335 | DPRINTF(sc, ATH_DBG_RATE, "Choosing rate table for mode: %d\n", mode); | ||
1336 | return sc->hw_rate_table[mode]; | ||
1337 | } | ||
1338 | |||
1307 | static void ath_rc_init(struct ath_softc *sc, | 1339 | static void ath_rc_init(struct ath_softc *sc, |
1308 | struct ath_rate_priv *ath_rc_priv, | 1340 | struct ath_rate_priv *ath_rc_priv, |
1309 | struct ieee80211_supported_band *sband, | 1341 | struct ieee80211_supported_band *sband, |
@@ -1314,16 +1346,25 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1314 | u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; | 1346 | u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; |
1315 | u8 i, j, k, hi = 0, hthi = 0; | 1347 | u8 i, j, k, hi = 0, hthi = 0; |
1316 | 1348 | ||
1317 | rate_table = sc->hw_rate_table[sc->sc_curmode]; | 1349 | /* FIXME: Adhoc */ |
1350 | if ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || | ||
1351 | (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)) { | ||
1352 | bool is_cw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1353 | rate_table = ath_choose_rate_table(sc, sband->band, | ||
1354 | sta->ht_cap.ht_supported, | ||
1355 | is_cw_40); | ||
1356 | } else if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { | ||
1357 | /* sc_curmode would be set on init through config() */ | ||
1358 | rate_table = sc->hw_rate_table[sc->sc_curmode]; | ||
1359 | } | ||
1318 | 1360 | ||
1319 | if (sta->ht_cap.ht_supported) { | 1361 | if (!rate_table) { |
1320 | if (sband->band == IEEE80211_BAND_2GHZ) | 1362 | DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n"); |
1321 | rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; | 1363 | return; |
1322 | else | 1364 | } |
1323 | rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; | ||
1324 | 1365 | ||
1366 | if (sta->ht_cap.ht_supported) { | ||
1325 | ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG); | 1367 | ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG); |
1326 | |||
1327 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | 1368 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) |
1328 | ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; | 1369 | ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; |
1329 | } | 1370 | } |