aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2008-11-26 23:16:27 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-12-05 09:32:59 -0500
commite11602b7813502bf363c40cdb5a8c4b96d4bbc96 (patch)
treef5cf351d596f9e99dc6cdf83fb1faec9de0e18a5
parentcb3da8ccc464409e3b947557cdac4cd0b1241c4c (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.c60
-rw-r--r--drivers/net/wireless/ath9k/rc.c55
2 files changed, 91 insertions, 24 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 437e38a3c6d7..e05eb1f07894 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
625static u32 ath_get_extchanmode(struct ath_softc *sc, 627static 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
844static 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
844static void ath9k_bss_assoc_info(struct ath_softc *sc, 856static 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 93dfea897ff2..7c08583a7943 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
1307static 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
1307static void ath_rc_init(struct ath_softc *sc, 1339static 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 }