aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2008-11-24 01:38:35 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-11-26 09:47:49 -0500
commit99405f930fda280c9114b15e178902cd204f967f (patch)
treed7950d3aa154803280c091b3c5331a7ca96c8678
parentff37e337beb838d4c2540fa93b2c4c632ee17750 (diff)
ath9k: Use proper TX channel width for setting channels
The TX channel width of the BSS can be obtained only after association. In all cases, default to HT20 if HT is enabled, and set chan width to HT40 only if the BSS supports it. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath9k/core.h7
-rw-r--r--drivers/net/wireless/ath9k/hw.c3
-rw-r--r--drivers/net/wireless/ath9k/main.c117
-rw-r--r--drivers/net/wireless/ath9k/xmit.c2
4 files changed, 60 insertions, 69 deletions
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index 21ee0c240528..f0c54377dfe6 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -633,11 +633,6 @@ enum PROT_MODE {
633 PROT_M_CTSONLY 633 PROT_M_CTSONLY
634}; 634};
635 635
636struct ath_ht_info {
637 enum ath9k_ht_macmode tx_chan_width;
638 u8 ext_chan_offset;
639};
640
641#define SC_OP_INVALID BIT(0) 636#define SC_OP_INVALID BIT(0)
642#define SC_OP_BEACONS BIT(1) 637#define SC_OP_BEACONS BIT(1)
643#define SC_OP_RXAGGR BIT(2) 638#define SC_OP_RXAGGR BIT(2)
@@ -691,8 +686,8 @@ struct ath_softc {
691 u8 sc_rxotherant; /* rx's on non-default antenna */ 686 u8 sc_rxotherant; /* rx's on non-default antenna */
692 687
693 struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ 688 struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
694 struct ath_ht_info sc_ht_info;
695 enum ath9k_ht_extprotspacing sc_ht_extprotspacing; 689 enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
690 enum ath9k_ht_macmode tx_chan_width;
696 691
697#ifdef CONFIG_SLOW_ANT_DIV 692#ifdef CONFIG_SLOW_ANT_DIV
698 struct ath_antdiv sc_antdiv; 693 struct ath_antdiv sc_antdiv;
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index 10f6c08f6eb2..6eef10477896 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -2232,8 +2232,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
2232 ((chan->channelFlags & CHANNEL_ALL) == 2232 ((chan->channelFlags & CHANNEL_ALL) ==
2233 (ah->ah_curchan->channelFlags & CHANNEL_ALL)) && 2233 (ah->ah_curchan->channelFlags & CHANNEL_ALL)) &&
2234 (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && 2234 (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
2235 !IS_CHAN_A_5MHZ_SPACED(ah-> 2235 !IS_CHAN_A_5MHZ_SPACED(ah->ah_curchan)))) {
2236 ah_curchan)))) {
2237 2236
2238 if (ath9k_hw_channel_change(ah, chan, macmode)) { 2237 if (ath9k_hw_channel_change(ah, chan, macmode)) {
2239 ath9k_hw_loadnf(ah, ah->ah_curchan); 2238 ath9k_hw_loadnf(ah, ah->ah_curchan);
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index f226a4daef75..437e38a3c6d7 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -260,15 +260,6 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
260 if (sc->sc_flags & SC_OP_INVALID) 260 if (sc->sc_flags & SC_OP_INVALID)
261 return -EIO; 261 return -EIO;
262 262
263 DPRINTF(sc, ATH_DBG_CONFIG,
264 "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n",
265 __func__,
266 ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel,
267 sc->sc_ah->ah_curchan->channelFlags),
268 sc->sc_ah->ah_curchan->channel,
269 ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags),
270 hchan->channel, hchan->channelFlags);
271
272 if (hchan->channel != sc->sc_ah->ah_curchan->channel || 263 if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
273 hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags || 264 hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
274 (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) || 265 (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
@@ -294,8 +285,14 @@ static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
294 if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) 285 if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
295 fastcc = false; 286 fastcc = false;
296 287
288 DPRINTF(sc, ATH_DBG_CONFIG,
289 "%s: (%u MHz) -> (%u MHz), cflags:%x, chanwidth: %d\n",
290 __func__,
291 sc->sc_ah->ah_curchan->channel,
292 hchan->channel, hchan->channelFlags, sc->tx_chan_width);
293
297 spin_lock_bh(&sc->sc_resetlock); 294 spin_lock_bh(&sc->sc_resetlock);
298 if (!ath9k_hw_reset(ah, hchan, sc->sc_ht_info.tx_chan_width, 295 if (!ath9k_hw_reset(ah, hchan, sc->tx_chan_width,
299 sc->sc_tx_chainmask, sc->sc_rx_chainmask, 296 sc->sc_tx_chainmask, sc->sc_rx_chainmask,
300 sc->sc_ht_extprotspacing, fastcc, &status)) { 297 sc->sc_ht_extprotspacing, fastcc, &status)) {
301 DPRINTF(sc, ATH_DBG_FATAL, 298 DPRINTF(sc, ATH_DBG_FATAL,
@@ -626,11 +623,13 @@ static int ath_get_channel(struct ath_softc *sc,
626} 623}
627 624
628static u32 ath_get_extchanmode(struct ath_softc *sc, 625static u32 ath_get_extchanmode(struct ath_softc *sc,
629 struct ieee80211_channel *chan) 626 struct ieee80211_channel *chan,
627 struct ieee80211_bss_conf *bss_conf)
630{ 628{
631 u32 chanmode = 0; 629 u32 chanmode = 0;
632 u8 ext_chan_offset = sc->sc_ht_info.ext_chan_offset; 630 u8 ext_chan_offset = bss_conf->ht.secondary_channel_offset;
633 enum ath9k_ht_macmode tx_chan_width = sc->sc_ht_info.tx_chan_width; 631 enum ath9k_ht_macmode tx_chan_width = (bss_conf->ht.width_40_ok) ?
632 ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20;
634 633
635 switch (chan->band) { 634 switch (chan->band) {
636 case IEEE80211_BAND_2GHZ: 635 case IEEE80211_BAND_2GHZ:
@@ -828,17 +827,17 @@ static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info)
828static void ath9k_ht_conf(struct ath_softc *sc, 827static void ath9k_ht_conf(struct ath_softc *sc,
829 struct ieee80211_bss_conf *bss_conf) 828 struct ieee80211_bss_conf *bss_conf)
830{ 829{
831 struct ath_ht_info *ht_info = &sc->sc_ht_info;
832
833 if (sc->hw->conf.ht.enabled) { 830 if (sc->hw->conf.ht.enabled) {
834 ht_info->ext_chan_offset = bss_conf->ht.secondary_channel_offset;
835
836 if (bss_conf->ht.width_40_ok) 831 if (bss_conf->ht.width_40_ok)
837 ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; 832 sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
838 else 833 else
839 ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; 834 sc->tx_chan_width = ATH9K_HT_MACMODE_20;
840 835
841 ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); 836 ath9k_hw_set11nmac2040(sc->sc_ah, sc->tx_chan_width);
837
838 DPRINTF(sc, ATH_DBG_CONFIG,
839 "%s: BSS Changed HT, chanwidth: %d\n",
840 __func__, sc->tx_chan_width);
842 } 841 }
843} 842}
844 843
@@ -892,26 +891,30 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
892 return; 891 return;
893 } 892 }
894 893
895 if (hw->conf.ht.enabled) 894 if (hw->conf.ht.enabled) {
896 sc->sc_ah->ah_channels[pos].chanmode = 895 sc->sc_ah->ah_channels[pos].chanmode =
897 ath_get_extchanmode(sc, curchan); 896 ath_get_extchanmode(sc, curchan, bss_conf);
898 else 897
898 if (bss_conf->ht.width_40_ok)
899 sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
900 else
901 sc->tx_chan_width = ATH9K_HT_MACMODE_20;
902 } else {
899 sc->sc_ah->ah_channels[pos].chanmode = 903 sc->sc_ah->ah_channels[pos].chanmode =
900 (curchan->band == IEEE80211_BAND_2GHZ) ? 904 (curchan->band == IEEE80211_BAND_2GHZ) ?
901 CHANNEL_G : CHANNEL_A; 905 CHANNEL_G : CHANNEL_A;
906 }
902 907
903 /* set h/w channel */ 908 /* set h/w channel */
904 if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) 909 if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
905 DPRINTF(sc, ATH_DBG_FATAL, 910 DPRINTF(sc, ATH_DBG_FATAL,
906 "%s: Unable to set channel\n", 911 "%s: Unable to set channel\n", __func__);
907 __func__);
908 /* Start ANI */ 912 /* Start ANI */
909 mod_timer(&sc->sc_ani.timer, 913 mod_timer(&sc->sc_ani.timer,
910 jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); 914 jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
911 915
912 } else { 916 } else {
913 DPRINTF(sc, ATH_DBG_CONFIG, 917 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info DISSOC\n", __func__);
914 "%s: Bss Info DISSOC\n", __func__);
915 sc->sc_curaid = 0; 918 sc->sc_curaid = 0;
916 } 919 }
917} 920}
@@ -1044,7 +1047,7 @@ static void ath_radio_enable(struct ath_softc *sc)
1044 1047
1045 spin_lock_bh(&sc->sc_resetlock); 1048 spin_lock_bh(&sc->sc_resetlock);
1046 if (!ath9k_hw_reset(ah, ah->ah_curchan, 1049 if (!ath9k_hw_reset(ah, ah->ah_curchan,
1047 sc->sc_ht_info.tx_chan_width, 1050 sc->tx_chan_width,
1048 sc->sc_tx_chainmask, 1051 sc->sc_tx_chainmask,
1049 sc->sc_rx_chainmask, 1052 sc->sc_rx_chainmask,
1050 sc->sc_ht_extprotspacing, 1053 sc->sc_ht_extprotspacing,
@@ -1102,7 +1105,7 @@ static void ath_radio_disable(struct ath_softc *sc)
1102 1105
1103 spin_lock_bh(&sc->sc_resetlock); 1106 spin_lock_bh(&sc->sc_resetlock);
1104 if (!ath9k_hw_reset(ah, ah->ah_curchan, 1107 if (!ath9k_hw_reset(ah, ah->ah_curchan,
1105 sc->sc_ht_info.tx_chan_width, 1108 sc->tx_chan_width,
1106 sc->sc_tx_chainmask, 1109 sc->sc_tx_chainmask,
1107 sc->sc_rx_chainmask, 1110 sc->sc_rx_chainmask,
1108 sc->sc_ht_extprotspacing, 1111 sc->sc_ht_extprotspacing,
@@ -1636,7 +1639,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
1636 1639
1637 spin_lock_bh(&sc->sc_resetlock); 1640 spin_lock_bh(&sc->sc_resetlock);
1638 if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, 1641 if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan,
1639 sc->sc_ht_info.tx_chan_width, 1642 sc->tx_chan_width,
1640 sc->sc_tx_chainmask, sc->sc_rx_chainmask, 1643 sc->sc_tx_chainmask, sc->sc_rx_chainmask,
1641 sc->sc_ht_extprotspacing, false, &status)) { 1644 sc->sc_ht_extprotspacing, false, &status)) {
1642 DPRINTF(sc, ATH_DBG_FATAL, 1645 DPRINTF(sc, ATH_DBG_FATAL,
@@ -1864,8 +1867,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
1864 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with " 1867 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with "
1865 "initial channel: %d MHz\n", __func__, curchan->center_freq); 1868 "initial channel: %d MHz\n", __func__, curchan->center_freq);
1866 1869
1867 memset(&sc->sc_ht_info, 0, sizeof(struct ath_ht_info));
1868
1869 /* setup initial channel */ 1870 /* setup initial channel */
1870 1871
1871 pos = ath_get_channel(sc, curchan); 1872 pos = ath_get_channel(sc, curchan);
@@ -1875,6 +1876,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
1875 goto error; 1876 goto error;
1876 } 1877 }
1877 1878
1879 sc->tx_chan_width = ATH9K_HT_MACMODE_20;
1878 sc->sc_ah->ah_channels[pos].chanmode = 1880 sc->sc_ah->ah_channels[pos].chanmode =
1879 (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; 1881 (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
1880 init_channel = &sc->sc_ah->ah_channels[pos]; 1882 init_channel = &sc->sc_ah->ah_channels[pos];
@@ -1891,7 +1893,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
1891 */ 1893 */
1892 spin_lock_bh(&sc->sc_resetlock); 1894 spin_lock_bh(&sc->sc_resetlock);
1893 if (!ath9k_hw_reset(sc->sc_ah, init_channel, 1895 if (!ath9k_hw_reset(sc->sc_ah, init_channel,
1894 sc->sc_ht_info.tx_chan_width, 1896 sc->tx_chan_width,
1895 sc->sc_tx_chainmask, sc->sc_rx_chainmask, 1897 sc->sc_tx_chainmask, sc->sc_rx_chainmask,
1896 sc->sc_ht_extprotspacing, false, &status)) { 1898 sc->sc_ht_extprotspacing, false, &status)) {
1897 DPRINTF(sc, ATH_DBG_FATAL, 1899 DPRINTF(sc, ATH_DBG_FATAL,
@@ -2149,39 +2151,37 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
2149static int ath9k_config(struct ieee80211_hw *hw, u32 changed) 2151static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
2150{ 2152{
2151 struct ath_softc *sc = hw->priv; 2153 struct ath_softc *sc = hw->priv;
2152 struct ieee80211_channel *curchan = hw->conf.channel;
2153 struct ieee80211_conf *conf = &hw->conf; 2154 struct ieee80211_conf *conf = &hw->conf;
2154 int pos;
2155
2156 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
2157 __func__,
2158 curchan->center_freq);
2159 2155
2160 /* Update chainmask */ 2156 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
2161 ath_update_chainmask(sc, conf->ht.enabled); 2157 struct ieee80211_channel *curchan = hw->conf.channel;
2158 int pos;
2162 2159
2163 pos = ath_get_channel(sc, curchan); 2160 DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
2164 if (pos == -1) { 2161 __func__, curchan->center_freq);
2165 DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
2166 return -EINVAL;
2167 }
2168 2162
2169 sc->sc_ah->ah_channels[pos].chanmode = 2163 pos = ath_get_channel(sc, curchan);
2170 (curchan->band == IEEE80211_BAND_2GHZ) ? 2164 if (pos == -1) {
2171 CHANNEL_G : CHANNEL_A; 2165 DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
2166 return -EINVAL;
2167 }
2172 2168
2173 if (sc->sc_curaid && hw->conf.ht.enabled) 2169 sc->tx_chan_width = ATH9K_HT_MACMODE_20;
2174 sc->sc_ah->ah_channels[pos].chanmode = 2170 sc->sc_ah->ah_channels[pos].chanmode =
2175 ath_get_extchanmode(sc, curchan); 2171 (curchan->band == IEEE80211_BAND_2GHZ) ?
2172 CHANNEL_G : CHANNEL_A;
2173
2174 if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
2175 DPRINTF(sc, ATH_DBG_FATAL,
2176 "%s: Unable to set channel\n", __func__);
2177 }
2178
2179 if (changed & IEEE80211_CONF_CHANGE_HT)
2180 ath_update_chainmask(sc, conf->ht.enabled);
2176 2181
2177 if (changed & IEEE80211_CONF_CHANGE_POWER) 2182 if (changed & IEEE80211_CONF_CHANGE_POWER)
2178 sc->sc_config.txpowlimit = 2 * conf->power_level; 2183 sc->sc_config.txpowlimit = 2 * conf->power_level;
2179 2184
2180 /* set h/w channel */
2181 if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
2182 DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n",
2183 __func__);
2184
2185 return 0; 2185 return 0;
2186} 2186}
2187 2187
@@ -2421,11 +2421,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
2421 sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; 2421 sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
2422 } 2422 }
2423 2423
2424 if (changed & BSS_CHANGED_HT) { 2424 if (changed & BSS_CHANGED_HT)
2425 DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT\n",
2426 __func__);
2427 ath9k_ht_conf(sc, bss_conf); 2425 ath9k_ht_conf(sc, bss_conf);
2428 }
2429 2426
2430 if (changed & BSS_CHANGED_ASSOC) { 2427 if (changed & BSS_CHANGED_ASSOC) {
2431 DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n", 2428 DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 3de60c51e5f2..413fbdd38ab6 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -1148,7 +1148,7 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
1148 spin_lock_bh(&sc->sc_resetlock); 1148 spin_lock_bh(&sc->sc_resetlock);
1149 if (!ath9k_hw_reset(ah, 1149 if (!ath9k_hw_reset(ah,
1150 sc->sc_ah->ah_curchan, 1150 sc->sc_ah->ah_curchan,
1151 sc->sc_ht_info.tx_chan_width, 1151 sc->tx_chan_width,
1152 sc->sc_tx_chainmask, sc->sc_rx_chainmask, 1152 sc->sc_tx_chainmask, sc->sc_rx_chainmask,
1153 sc->sc_ht_extprotspacing, true, &status)) { 1153 sc->sc_ht_extprotspacing, true, &status)) {
1154 1154