diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/init.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 83 |
1 files changed, 56 insertions, 27 deletions
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index b78308c3c4d4..8c795488ebc3 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -175,6 +175,18 @@ static const struct ath_ops ath9k_common_ops = { | |||
175 | .write = ath9k_iowrite32, | 175 | .write = ath9k_iowrite32, |
176 | }; | 176 | }; |
177 | 177 | ||
178 | static int count_streams(unsigned int chainmask, int max) | ||
179 | { | ||
180 | int streams = 0; | ||
181 | |||
182 | do { | ||
183 | if (++streams == max) | ||
184 | break; | ||
185 | } while ((chainmask = chainmask & (chainmask - 1))); | ||
186 | |||
187 | return streams; | ||
188 | } | ||
189 | |||
178 | /**************************/ | 190 | /**************************/ |
179 | /* Initialization */ | 191 | /* Initialization */ |
180 | /**************************/ | 192 | /**************************/ |
@@ -182,8 +194,10 @@ static const struct ath_ops ath9k_common_ops = { | |||
182 | static void setup_ht_cap(struct ath_softc *sc, | 194 | static void setup_ht_cap(struct ath_softc *sc, |
183 | struct ieee80211_sta_ht_cap *ht_info) | 195 | struct ieee80211_sta_ht_cap *ht_info) |
184 | { | 196 | { |
185 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 197 | struct ath_hw *ah = sc->sc_ah; |
198 | struct ath_common *common = ath9k_hw_common(ah); | ||
186 | u8 tx_streams, rx_streams; | 199 | u8 tx_streams, rx_streams; |
200 | int i, max_streams; | ||
187 | 201 | ||
188 | ht_info->ht_supported = true; | 202 | ht_info->ht_supported = true; |
189 | ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | 203 | ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
@@ -191,28 +205,40 @@ static void setup_ht_cap(struct ath_softc *sc, | |||
191 | IEEE80211_HT_CAP_SGI_40 | | 205 | IEEE80211_HT_CAP_SGI_40 | |
192 | IEEE80211_HT_CAP_DSSSCCK40; | 206 | IEEE80211_HT_CAP_DSSSCCK40; |
193 | 207 | ||
208 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) | ||
209 | ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; | ||
210 | |||
194 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | 211 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; |
195 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | 212 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; |
196 | 213 | ||
214 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
215 | max_streams = 3; | ||
216 | else | ||
217 | max_streams = 2; | ||
218 | |||
219 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
220 | if (max_streams >= 2) | ||
221 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; | ||
222 | ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | ||
223 | } | ||
224 | |||
197 | /* set up supported mcs set */ | 225 | /* set up supported mcs set */ |
198 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | 226 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); |
199 | tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? | 227 | tx_streams = count_streams(common->tx_chainmask, max_streams); |
200 | 1 : 2; | 228 | rx_streams = count_streams(common->rx_chainmask, max_streams); |
201 | rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? | 229 | |
202 | 1 : 2; | 230 | ath_print(common, ATH_DBG_CONFIG, |
231 | "TX streams %d, RX streams: %d\n", | ||
232 | tx_streams, rx_streams); | ||
203 | 233 | ||
204 | if (tx_streams != rx_streams) { | 234 | if (tx_streams != rx_streams) { |
205 | ath_print(common, ATH_DBG_CONFIG, | ||
206 | "TX streams %d, RX streams: %d\n", | ||
207 | tx_streams, rx_streams); | ||
208 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | 235 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; |
209 | ht_info->mcs.tx_params |= ((tx_streams - 1) << | 236 | ht_info->mcs.tx_params |= ((tx_streams - 1) << |
210 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | 237 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); |
211 | } | 238 | } |
212 | 239 | ||
213 | ht_info->mcs.rx_mask[0] = 0xff; | 240 | for (i = 0; i < rx_streams; i++) |
214 | if (rx_streams >= 2) | 241 | ht_info->mcs.rx_mask[i] = 0xff; |
215 | ht_info->mcs.rx_mask[1] = 0xff; | ||
216 | 242 | ||
217 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; | 243 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; |
218 | } | 244 | } |
@@ -235,31 +261,37 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
235 | */ | 261 | */ |
236 | int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | 262 | int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, |
237 | struct list_head *head, const char *name, | 263 | struct list_head *head, const char *name, |
238 | int nbuf, int ndesc) | 264 | int nbuf, int ndesc, bool is_tx) |
239 | { | 265 | { |
240 | #define DS2PHYS(_dd, _ds) \ | 266 | #define DS2PHYS(_dd, _ds) \ |
241 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | 267 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) |
242 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | 268 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) |
243 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) | 269 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) |
244 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 270 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
245 | struct ath_desc *ds; | 271 | u8 *ds; |
246 | struct ath_buf *bf; | 272 | struct ath_buf *bf; |
247 | int i, bsize, error; | 273 | int i, bsize, error, desc_len; |
248 | 274 | ||
249 | ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", | 275 | ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", |
250 | name, nbuf, ndesc); | 276 | name, nbuf, ndesc); |
251 | 277 | ||
252 | INIT_LIST_HEAD(head); | 278 | INIT_LIST_HEAD(head); |
279 | |||
280 | if (is_tx) | ||
281 | desc_len = sc->sc_ah->caps.tx_desc_len; | ||
282 | else | ||
283 | desc_len = sizeof(struct ath_desc); | ||
284 | |||
253 | /* ath_desc must be a multiple of DWORDs */ | 285 | /* ath_desc must be a multiple of DWORDs */ |
254 | if ((sizeof(struct ath_desc) % 4) != 0) { | 286 | if ((desc_len % 4) != 0) { |
255 | ath_print(common, ATH_DBG_FATAL, | 287 | ath_print(common, ATH_DBG_FATAL, |
256 | "ath_desc not DWORD aligned\n"); | 288 | "ath_desc not DWORD aligned\n"); |
257 | BUG_ON((sizeof(struct ath_desc) % 4) != 0); | 289 | BUG_ON((desc_len % 4) != 0); |
258 | error = -ENOMEM; | 290 | error = -ENOMEM; |
259 | goto fail; | 291 | goto fail; |
260 | } | 292 | } |
261 | 293 | ||
262 | dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; | 294 | dd->dd_desc_len = desc_len * nbuf * ndesc; |
263 | 295 | ||
264 | /* | 296 | /* |
265 | * Need additional DMA memory because we can't use | 297 | * Need additional DMA memory because we can't use |
@@ -272,7 +304,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
272 | u32 dma_len; | 304 | u32 dma_len; |
273 | 305 | ||
274 | while (ndesc_skipped) { | 306 | while (ndesc_skipped) { |
275 | dma_len = ndesc_skipped * sizeof(struct ath_desc); | 307 | dma_len = ndesc_skipped * desc_len; |
276 | dd->dd_desc_len += dma_len; | 308 | dd->dd_desc_len += dma_len; |
277 | 309 | ||
278 | ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); | 310 | ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); |
@@ -286,7 +318,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
286 | error = -ENOMEM; | 318 | error = -ENOMEM; |
287 | goto fail; | 319 | goto fail; |
288 | } | 320 | } |
289 | ds = dd->dd_desc; | 321 | ds = (u8 *) dd->dd_desc; |
290 | ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", | 322 | ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", |
291 | name, ds, (u32) dd->dd_desc_len, | 323 | name, ds, (u32) dd->dd_desc_len, |
292 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | 324 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); |
@@ -300,7 +332,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
300 | } | 332 | } |
301 | dd->dd_bufptr = bf; | 333 | dd->dd_bufptr = bf; |
302 | 334 | ||
303 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { | 335 | for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) { |
304 | bf->bf_desc = ds; | 336 | bf->bf_desc = ds; |
305 | bf->bf_daddr = DS2PHYS(dd, ds); | 337 | bf->bf_daddr = DS2PHYS(dd, ds); |
306 | 338 | ||
@@ -316,7 +348,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
316 | ((caddr_t) dd->dd_desc + | 348 | ((caddr_t) dd->dd_desc + |
317 | dd->dd_desc_len)); | 349 | dd->dd_desc_len)); |
318 | 350 | ||
319 | ds += ndesc; | 351 | ds += (desc_len * ndesc); |
320 | bf->bf_desc = ds; | 352 | bf->bf_desc = ds; |
321 | bf->bf_daddr = DS2PHYS(dd, ds); | 353 | bf->bf_daddr = DS2PHYS(dd, ds); |
322 | } | 354 | } |
@@ -514,7 +546,7 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
514 | common->tx_chainmask = sc->sc_ah->caps.tx_chainmask; | 546 | common->tx_chainmask = sc->sc_ah->caps.tx_chainmask; |
515 | common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; | 547 | common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; |
516 | 548 | ||
517 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | 549 | ath9k_hw_set_diversity(sc->sc_ah, true); |
518 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); | 550 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); |
519 | 551 | ||
520 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 552 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) |
@@ -568,13 +600,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
568 | ath_read_cachesize(common, &csz); | 600 | ath_read_cachesize(common, &csz); |
569 | common->cachelsz = csz << 2; /* convert to bytes */ | 601 | common->cachelsz = csz << 2; /* convert to bytes */ |
570 | 602 | ||
603 | /* Initializes the hardware for all supported chipsets */ | ||
571 | ret = ath9k_hw_init(ah); | 604 | ret = ath9k_hw_init(ah); |
572 | if (ret) { | 605 | if (ret) |
573 | ath_print(common, ATH_DBG_FATAL, | ||
574 | "Unable to initialize hardware; " | ||
575 | "initialization status: %d\n", ret); | ||
576 | goto err_hw; | 606 | goto err_hw; |
577 | } | ||
578 | 607 | ||
579 | ret = ath9k_init_debug(ah); | 608 | ret = ath9k_init_debug(ah); |
580 | if (ret) { | 609 | if (ret) { |