aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-04-19 13:57:34 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-20 11:50:54 -0400
commit3bb065a7420c90421d6bbea5f7cffe36bd79a048 (patch)
tree3a62f8d64abd83ffa55b11c0272ab69f5b58a481 /drivers
parentc666387682faaec7d7b4a8afd30b0b6bc0816ddb (diff)
ath9k: initialize the number of tx/rx streams correctly
AR9300 based hardware can 3x3 MCS rates, this should be set in the HT capabilities. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 5adc2e335cff..351538cd8e4c 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -173,6 +173,18 @@ static const struct ath_ops ath9k_common_ops = {
173 .write = ath9k_iowrite32, 173 .write = ath9k_iowrite32,
174}; 174};
175 175
176static int count_streams(unsigned int chainmask, int max)
177{
178 int streams = 0;
179
180 do {
181 if (++streams == max)
182 break;
183 } while ((chainmask = chainmask & (chainmask - 1)));
184
185 return streams;
186}
187
176/**************************/ 188/**************************/
177/* Initialization */ 189/* Initialization */
178/**************************/ 190/**************************/
@@ -180,8 +192,10 @@ static const struct ath_ops ath9k_common_ops = {
180static void setup_ht_cap(struct ath_softc *sc, 192static void setup_ht_cap(struct ath_softc *sc,
181 struct ieee80211_sta_ht_cap *ht_info) 193 struct ieee80211_sta_ht_cap *ht_info)
182{ 194{
183 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 195 struct ath_hw *ah = sc->sc_ah;
196 struct ath_common *common = ath9k_hw_common(ah);
184 u8 tx_streams, rx_streams; 197 u8 tx_streams, rx_streams;
198 int i, max_streams;
185 199
186 ht_info->ht_supported = true; 200 ht_info->ht_supported = true;
187 ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 201 ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
@@ -195,25 +209,28 @@ static void setup_ht_cap(struct ath_softc *sc,
195 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; 209 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
196 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; 210 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
197 211
212 if (AR_SREV_9300_20_OR_LATER(ah))
213 max_streams = 3;
214 else
215 max_streams = 2;
216
198 /* set up supported mcs set */ 217 /* set up supported mcs set */
199 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); 218 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
200 tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? 219 tx_streams = count_streams(common->tx_chainmask, max_streams);
201 1 : 2; 220 rx_streams = count_streams(common->rx_chainmask, max_streams);
202 rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? 221
203 1 : 2; 222 ath_print(common, ATH_DBG_CONFIG,
223 "TX streams %d, RX streams: %d\n",
224 tx_streams, rx_streams);
204 225
205 if (tx_streams != rx_streams) { 226 if (tx_streams != rx_streams) {
206 ath_print(common, ATH_DBG_CONFIG,
207 "TX streams %d, RX streams: %d\n",
208 tx_streams, rx_streams);
209 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; 227 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
210 ht_info->mcs.tx_params |= ((tx_streams - 1) << 228 ht_info->mcs.tx_params |= ((tx_streams - 1) <<
211 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); 229 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
212 } 230 }
213 231
214 ht_info->mcs.rx_mask[0] = 0xff; 232 for (i = 0; i < rx_streams; i++)
215 if (rx_streams >= 2) 233 ht_info->mcs.rx_mask[i] = 0xff;
216 ht_info->mcs.rx_mask[1] = 0xff;
217 234
218 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; 235 ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
219} 236}