diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/recv.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 1014 |
1 files changed, 839 insertions, 175 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a3fc987ebab0..07e35e59c9e3 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -19,31 +19,46 @@ | |||
19 | 19 | ||
20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) | 20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) |
21 | 21 | ||
22 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 22 | static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, |
23 | int mindelta, int main_rssi_avg, | ||
24 | int alt_rssi_avg, int pkt_count) | ||
23 | { | 25 | { |
24 | return sc->ps_enabled && | 26 | return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && |
25 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); | 27 | (alt_rssi_avg > main_rssi_avg + maxdelta)) || |
28 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | ||
26 | } | 29 | } |
27 | 30 | ||
28 | static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, | 31 | static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, |
29 | struct ieee80211_hdr *hdr) | 32 | int curr_main_set, int curr_alt_set, |
33 | int alt_rssi_avg, int main_rssi_avg) | ||
30 | { | 34 | { |
31 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | 35 | bool result = false; |
32 | int i; | 36 | switch (div_group) { |
33 | 37 | case 0: | |
34 | spin_lock_bh(&sc->wiphy_lock); | 38 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) |
35 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 39 | result = true; |
36 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 40 | break; |
37 | if (aphy == NULL) | 41 | case 1: |
38 | continue; | 42 | if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && |
39 | if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr) | 43 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && |
40 | == 0) { | 44 | (alt_rssi_avg >= (main_rssi_avg - 5))) || |
41 | hw = aphy->hw; | 45 | ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && |
42 | break; | 46 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && |
43 | } | 47 | (alt_rssi_avg >= (main_rssi_avg - 2)))) && |
48 | (alt_rssi_avg >= 4)) | ||
49 | result = true; | ||
50 | else | ||
51 | result = false; | ||
52 | break; | ||
44 | } | 53 | } |
45 | spin_unlock_bh(&sc->wiphy_lock); | 54 | |
46 | return hw; | 55 | return result; |
56 | } | ||
57 | |||
58 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | ||
59 | { | ||
60 | return sc->ps_enabled && | ||
61 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); | ||
47 | } | 62 | } |
48 | 63 | ||
49 | /* | 64 | /* |
@@ -87,7 +102,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
87 | *sc->rx.rxlink = bf->bf_daddr; | 102 | *sc->rx.rxlink = bf->bf_daddr; |
88 | 103 | ||
89 | sc->rx.rxlink = &ds->ds_link; | 104 | sc->rx.rxlink = &ds->ds_link; |
90 | ath9k_hw_rxena(ah); | ||
91 | } | 105 | } |
92 | 106 | ||
93 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) | 107 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) |
@@ -110,8 +124,7 @@ static void ath_opmode_init(struct ath_softc *sc) | |||
110 | ath9k_hw_setrxfilter(ah, rfilt); | 124 | ath9k_hw_setrxfilter(ah, rfilt); |
111 | 125 | ||
112 | /* configure bssid mask */ | 126 | /* configure bssid mask */ |
113 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 127 | ath_hw_setbssidmask(common); |
114 | ath_hw_setbssidmask(common); | ||
115 | 128 | ||
116 | /* configure operational mode */ | 129 | /* configure operational mode */ |
117 | ath9k_hw_setopmode(ah); | 130 | ath9k_hw_setopmode(ah); |
@@ -157,7 +170,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc, | |||
157 | u32 nbuf = 0; | 170 | u32 nbuf = 0; |
158 | 171 | ||
159 | if (list_empty(&sc->rx.rxbuf)) { | 172 | if (list_empty(&sc->rx.rxbuf)) { |
160 | ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n"); | 173 | ath_dbg(common, ATH_DBG_QUEUE, "No free rx buf available\n"); |
161 | return; | 174 | return; |
162 | } | 175 | } |
163 | 176 | ||
@@ -222,11 +235,6 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
222 | int error = 0, i; | 235 | int error = 0, i; |
223 | u32 size; | 236 | u32 size; |
224 | 237 | ||
225 | |||
226 | common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN + | ||
227 | ah->caps.rx_status_len, | ||
228 | min(common->cachelsz, (u16)64)); | ||
229 | |||
230 | ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - | 238 | ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - |
231 | ah->caps.rx_status_len); | 239 | ah->caps.rx_status_len); |
232 | 240 | ||
@@ -260,7 +268,8 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
260 | bf->bf_buf_addr))) { | 268 | bf->bf_buf_addr))) { |
261 | dev_kfree_skb_any(skb); | 269 | dev_kfree_skb_any(skb); |
262 | bf->bf_mpdu = NULL; | 270 | bf->bf_mpdu = NULL; |
263 | ath_print(common, ATH_DBG_FATAL, | 271 | bf->bf_buf_addr = 0; |
272 | ath_err(common, | ||
264 | "dma_mapping_error() on RX init\n"); | 273 | "dma_mapping_error() on RX init\n"); |
265 | error = -ENOMEM; | 274 | error = -ENOMEM; |
266 | goto rx_init_fail; | 275 | goto rx_init_fail; |
@@ -288,19 +297,17 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
288 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP, | 297 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP, |
289 | sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize); | 298 | sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize); |
290 | 299 | ||
291 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
292 | |||
293 | ath_opmode_init(sc); | 300 | ath_opmode_init(sc); |
294 | 301 | ||
295 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING)); | 302 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); |
303 | |||
304 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
296 | } | 305 | } |
297 | 306 | ||
298 | static void ath_edma_stop_recv(struct ath_softc *sc) | 307 | static void ath_edma_stop_recv(struct ath_softc *sc) |
299 | { | 308 | { |
300 | spin_lock_bh(&sc->rx.rxbuflock); | ||
301 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); | 309 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); |
302 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); | 310 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); |
303 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
304 | } | 311 | } |
305 | 312 | ||
306 | int ath_rx_init(struct ath_softc *sc, int nbufs) | 313 | int ath_rx_init(struct ath_softc *sc, int nbufs) |
@@ -310,27 +317,27 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
310 | struct ath_buf *bf; | 317 | struct ath_buf *bf; |
311 | int error = 0; | 318 | int error = 0; |
312 | 319 | ||
313 | spin_lock_init(&sc->rx.rxflushlock); | 320 | spin_lock_init(&sc->sc_pcu_lock); |
314 | sc->sc_flags &= ~SC_OP_RXFLUSH; | 321 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
315 | spin_lock_init(&sc->rx.rxbuflock); | 322 | spin_lock_init(&sc->rx.rxbuflock); |
316 | 323 | ||
324 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + | ||
325 | sc->sc_ah->caps.rx_status_len; | ||
326 | |||
317 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 327 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
318 | return ath_rx_edma_init(sc, nbufs); | 328 | return ath_rx_edma_init(sc, nbufs); |
319 | } else { | 329 | } else { |
320 | common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, | 330 | ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", |
321 | min(common->cachelsz, (u16)64)); | 331 | common->cachelsz, common->rx_bufsize); |
322 | |||
323 | ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", | ||
324 | common->cachelsz, common->rx_bufsize); | ||
325 | 332 | ||
326 | /* Initialize rx descriptors */ | 333 | /* Initialize rx descriptors */ |
327 | 334 | ||
328 | error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, | 335 | error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, |
329 | "rx", nbufs, 1, 0); | 336 | "rx", nbufs, 1, 0); |
330 | if (error != 0) { | 337 | if (error != 0) { |
331 | ath_print(common, ATH_DBG_FATAL, | 338 | ath_err(common, |
332 | "failed to allocate rx descriptors: %d\n", | 339 | "failed to allocate rx descriptors: %d\n", |
333 | error); | 340 | error); |
334 | goto err; | 341 | goto err; |
335 | } | 342 | } |
336 | 343 | ||
@@ -350,12 +357,12 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
350 | bf->bf_buf_addr))) { | 357 | bf->bf_buf_addr))) { |
351 | dev_kfree_skb_any(skb); | 358 | dev_kfree_skb_any(skb); |
352 | bf->bf_mpdu = NULL; | 359 | bf->bf_mpdu = NULL; |
353 | ath_print(common, ATH_DBG_FATAL, | 360 | bf->bf_buf_addr = 0; |
354 | "dma_mapping_error() on RX init\n"); | 361 | ath_err(common, |
362 | "dma_mapping_error() on RX init\n"); | ||
355 | error = -ENOMEM; | 363 | error = -ENOMEM; |
356 | goto err; | 364 | goto err; |
357 | } | 365 | } |
358 | bf->bf_dmacontext = bf->bf_buf_addr; | ||
359 | } | 366 | } |
360 | sc->rx.rxlink = NULL; | 367 | sc->rx.rxlink = NULL; |
361 | } | 368 | } |
@@ -385,6 +392,8 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
385 | common->rx_bufsize, | 392 | common->rx_bufsize, |
386 | DMA_FROM_DEVICE); | 393 | DMA_FROM_DEVICE); |
387 | dev_kfree_skb(skb); | 394 | dev_kfree_skb(skb); |
395 | bf->bf_buf_addr = 0; | ||
396 | bf->bf_mpdu = NULL; | ||
388 | } | 397 | } |
389 | } | 398 | } |
390 | 399 | ||
@@ -422,8 +431,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
422 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | 431 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
423 | | ATH9K_RX_FILTER_MCAST; | 432 | | ATH9K_RX_FILTER_MCAST; |
424 | 433 | ||
425 | /* If not a STA, enable processing of Probe Requests */ | 434 | if (sc->rx.rxfilter & FIF_PROBE_REQ) |
426 | if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) | ||
427 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | 435 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; |
428 | 436 | ||
429 | /* | 437 | /* |
@@ -431,32 +439,27 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
431 | * mode interface or when in monitor mode. AP mode does not need this | 439 | * mode interface or when in monitor mode. AP mode does not need this |
432 | * since it receives all in-BSS frames anyway. | 440 | * since it receives all in-BSS frames anyway. |
433 | */ | 441 | */ |
434 | if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && | 442 | if (sc->sc_ah->is_monitoring) |
435 | (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || | ||
436 | (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) | ||
437 | rfilt |= ATH9K_RX_FILTER_PROM; | 443 | rfilt |= ATH9K_RX_FILTER_PROM; |
438 | 444 | ||
439 | if (sc->rx.rxfilter & FIF_CONTROL) | 445 | if (sc->rx.rxfilter & FIF_CONTROL) |
440 | rfilt |= ATH9K_RX_FILTER_CONTROL; | 446 | rfilt |= ATH9K_RX_FILTER_CONTROL; |
441 | 447 | ||
442 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && | 448 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && |
449 | (sc->nvifs <= 1) && | ||
443 | !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) | 450 | !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) |
444 | rfilt |= ATH9K_RX_FILTER_MYBEACON; | 451 | rfilt |= ATH9K_RX_FILTER_MYBEACON; |
445 | else | 452 | else |
446 | rfilt |= ATH9K_RX_FILTER_BEACON; | 453 | rfilt |= ATH9K_RX_FILTER_BEACON; |
447 | 454 | ||
448 | if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) || | 455 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || |
449 | AR_SREV_9285_10_OR_LATER(sc->sc_ah)) && | ||
450 | (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && | ||
451 | (sc->rx.rxfilter & FIF_PSPOLL)) | 456 | (sc->rx.rxfilter & FIF_PSPOLL)) |
452 | rfilt |= ATH9K_RX_FILTER_PSPOLL; | 457 | rfilt |= ATH9K_RX_FILTER_PSPOLL; |
453 | 458 | ||
454 | if (conf_is_ht(&sc->hw->conf)) | 459 | if (conf_is_ht(&sc->hw->conf)) |
455 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | 460 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; |
456 | 461 | ||
457 | if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) { | 462 | if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) { |
458 | /* TODO: only needed if more than one BSSID is in use in | ||
459 | * station/adhoc mode */ | ||
460 | /* The following may also be needed for other older chips */ | 463 | /* The following may also be needed for other older chips */ |
461 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) | 464 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) |
462 | rfilt |= ATH9K_RX_FILTER_PROM; | 465 | rfilt |= ATH9K_RX_FILTER_PROM; |
@@ -496,9 +499,10 @@ int ath_startrecv(struct ath_softc *sc) | |||
496 | ath9k_hw_rxena(ah); | 499 | ath9k_hw_rxena(ah); |
497 | 500 | ||
498 | start_recv: | 501 | start_recv: |
499 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
500 | ath_opmode_init(sc); | 502 | ath_opmode_init(sc); |
501 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING)); | 503 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); |
504 | |||
505 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
502 | 506 | ||
503 | return 0; | 507 | return 0; |
504 | } | 508 | } |
@@ -506,29 +510,36 @@ start_recv: | |||
506 | bool ath_stoprecv(struct ath_softc *sc) | 510 | bool ath_stoprecv(struct ath_softc *sc) |
507 | { | 511 | { |
508 | struct ath_hw *ah = sc->sc_ah; | 512 | struct ath_hw *ah = sc->sc_ah; |
509 | bool stopped; | 513 | bool stopped, reset = false; |
510 | 514 | ||
511 | ath9k_hw_stoppcurecv(ah); | 515 | spin_lock_bh(&sc->rx.rxbuflock); |
516 | ath9k_hw_abortpcurecv(ah); | ||
512 | ath9k_hw_setrxfilter(ah, 0); | 517 | ath9k_hw_setrxfilter(ah, 0); |
513 | stopped = ath9k_hw_stopdmarecv(ah); | 518 | stopped = ath9k_hw_stopdmarecv(ah, &reset); |
514 | 519 | ||
515 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 520 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
516 | ath_edma_stop_recv(sc); | 521 | ath_edma_stop_recv(sc); |
517 | else | 522 | else |
518 | sc->rx.rxlink = NULL; | 523 | sc->rx.rxlink = NULL; |
524 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
519 | 525 | ||
520 | return stopped; | 526 | if (!(ah->ah_flags & AH_UNPLUGGED) && |
527 | unlikely(!stopped)) { | ||
528 | ath_err(ath9k_hw_common(sc->sc_ah), | ||
529 | "Could not stop RX, we could be " | ||
530 | "confusing the DMA engine when we start RX up\n"); | ||
531 | ATH_DBG_WARN_ON_ONCE(!stopped); | ||
532 | } | ||
533 | return stopped && !reset; | ||
521 | } | 534 | } |
522 | 535 | ||
523 | void ath_flushrecv(struct ath_softc *sc) | 536 | void ath_flushrecv(struct ath_softc *sc) |
524 | { | 537 | { |
525 | spin_lock_bh(&sc->rx.rxflushlock); | ||
526 | sc->sc_flags |= SC_OP_RXFLUSH; | 538 | sc->sc_flags |= SC_OP_RXFLUSH; |
527 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 539 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
528 | ath_rx_tasklet(sc, 1, true); | 540 | ath_rx_tasklet(sc, 1, true); |
529 | ath_rx_tasklet(sc, 1, false); | 541 | ath_rx_tasklet(sc, 1, false); |
530 | sc->sc_flags &= ~SC_OP_RXFLUSH; | 542 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
531 | spin_unlock_bh(&sc->rx.rxflushlock); | ||
532 | } | 543 | } |
533 | 544 | ||
534 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) | 545 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) |
@@ -572,17 +583,23 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
572 | return; | 583 | return; |
573 | 584 | ||
574 | mgmt = (struct ieee80211_mgmt *)skb->data; | 585 | mgmt = (struct ieee80211_mgmt *)skb->data; |
575 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) | 586 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) { |
587 | /* TODO: This doesn't work well if you have stations | ||
588 | * associated to two different APs because curbssid | ||
589 | * is just the last AP that any of the stations associated | ||
590 | * with. | ||
591 | */ | ||
576 | return; /* not from our current AP */ | 592 | return; /* not from our current AP */ |
593 | } | ||
577 | 594 | ||
578 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; | 595 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; |
579 | 596 | ||
580 | if (sc->ps_flags & PS_BEACON_SYNC) { | 597 | if (sc->ps_flags & PS_BEACON_SYNC) { |
581 | sc->ps_flags &= ~PS_BEACON_SYNC; | 598 | sc->ps_flags &= ~PS_BEACON_SYNC; |
582 | ath_print(common, ATH_DBG_PS, | 599 | ath_dbg(common, ATH_DBG_PS, |
583 | "Reconfigure Beacon timers based on " | 600 | "Reconfigure Beacon timers based on timestamp from the AP\n"); |
584 | "timestamp from the AP\n"); | 601 | ath_set_beacon(sc); |
585 | ath_beacon_config(sc, NULL); | 602 | sc->ps_flags &= ~PS_TSFOOR_SYNC; |
586 | } | 603 | } |
587 | 604 | ||
588 | if (ath_beacon_dtim_pending_cab(skb)) { | 605 | if (ath_beacon_dtim_pending_cab(skb)) { |
@@ -593,8 +610,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
593 | * a backup trigger for returning into NETWORK SLEEP state, | 610 | * a backup trigger for returning into NETWORK SLEEP state, |
594 | * so we are waiting for it as well. | 611 | * so we are waiting for it as well. |
595 | */ | 612 | */ |
596 | ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating " | 613 | ath_dbg(common, ATH_DBG_PS, |
597 | "buffered broadcast/multicast frame(s)\n"); | 614 | "Received DTIM beacon indicating buffered broadcast/multicast frame(s)\n"); |
598 | sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON; | 615 | sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON; |
599 | return; | 616 | return; |
600 | } | 617 | } |
@@ -606,8 +623,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
606 | * been delivered. | 623 | * been delivered. |
607 | */ | 624 | */ |
608 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; | 625 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; |
609 | ath_print(common, ATH_DBG_PS, | 626 | ath_dbg(common, ATH_DBG_PS, |
610 | "PS wait for CAB frames timed out\n"); | 627 | "PS wait for CAB frames timed out\n"); |
611 | } | 628 | } |
612 | } | 629 | } |
613 | 630 | ||
@@ -631,16 +648,15 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
631 | * No more broadcast/multicast frames to be received at this | 648 | * No more broadcast/multicast frames to be received at this |
632 | * point. | 649 | * point. |
633 | */ | 650 | */ |
634 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; | 651 | sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON); |
635 | ath_print(common, ATH_DBG_PS, | 652 | ath_dbg(common, ATH_DBG_PS, |
636 | "All PS CAB frames received, back to sleep\n"); | 653 | "All PS CAB frames received, back to sleep\n"); |
637 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && | 654 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && |
638 | !is_multicast_ether_addr(hdr->addr1) && | 655 | !is_multicast_ether_addr(hdr->addr1) && |
639 | !ieee80211_has_morefrags(hdr->frame_control)) { | 656 | !ieee80211_has_morefrags(hdr->frame_control)) { |
640 | sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; | 657 | sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; |
641 | ath_print(common, ATH_DBG_PS, | 658 | ath_dbg(common, ATH_DBG_PS, |
642 | "Going back to sleep after having received " | 659 | "Going back to sleep after having received PS-Poll data (0x%lx)\n", |
643 | "PS-Poll data (0x%lx)\n", | ||
644 | sc->ps_flags & (PS_WAIT_FOR_BEACON | | 660 | sc->ps_flags & (PS_WAIT_FOR_BEACON | |
645 | PS_WAIT_FOR_CAB | | 661 | PS_WAIT_FOR_CAB | |
646 | PS_WAIT_FOR_PSPOLL_DATA | | 662 | PS_WAIT_FOR_PSPOLL_DATA | |
@@ -648,38 +664,6 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
648 | } | 664 | } |
649 | } | 665 | } |
650 | 666 | ||
651 | static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, | ||
652 | struct ath_softc *sc, struct sk_buff *skb, | ||
653 | struct ieee80211_rx_status *rxs) | ||
654 | { | ||
655 | struct ieee80211_hdr *hdr; | ||
656 | |||
657 | hdr = (struct ieee80211_hdr *)skb->data; | ||
658 | |||
659 | /* Send the frame to mac80211 */ | ||
660 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
661 | int i; | ||
662 | /* | ||
663 | * Deliver broadcast/multicast frames to all suitable | ||
664 | * virtual wiphys. | ||
665 | */ | ||
666 | /* TODO: filter based on channel configuration */ | ||
667 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
668 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
669 | struct sk_buff *nskb; | ||
670 | if (aphy == NULL) | ||
671 | continue; | ||
672 | nskb = skb_copy(skb, GFP_ATOMIC); | ||
673 | if (!nskb) | ||
674 | continue; | ||
675 | ieee80211_rx(aphy->hw, nskb); | ||
676 | } | ||
677 | ieee80211_rx(sc->hw, skb); | ||
678 | } else | ||
679 | /* Deliver unicast frames based on receiver address */ | ||
680 | ieee80211_rx(hw, skb); | ||
681 | } | ||
682 | |||
683 | static bool ath_edma_get_buffers(struct ath_softc *sc, | 667 | static bool ath_edma_get_buffers(struct ath_softc *sc, |
684 | enum ath9k_rx_qtype qtype) | 668 | enum ath9k_rx_qtype qtype) |
685 | { | 669 | { |
@@ -829,6 +813,10 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
829 | struct ath_rx_status *rx_stats, | 813 | struct ath_rx_status *rx_stats, |
830 | bool *decrypt_error) | 814 | bool *decrypt_error) |
831 | { | 815 | { |
816 | #define is_mc_or_valid_tkip_keyix ((is_mc || \ | ||
817 | (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \ | ||
818 | test_bit(rx_stats->rs_keyix, common->tkip_keymap)))) | ||
819 | |||
832 | struct ath_hw *ah = common->ah; | 820 | struct ath_hw *ah = common->ah; |
833 | __le16 fc; | 821 | __le16 fc; |
834 | u8 rx_status_len = ah->caps.rx_status_len; | 822 | u8 rx_status_len = ah->caps.rx_status_len; |
@@ -845,15 +833,9 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
845 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) | 833 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) |
846 | return false; | 834 | return false; |
847 | 835 | ||
848 | /* | 836 | /* Only use error bits from the last fragment */ |
849 | * rs_more indicates chained descriptors which can be used | ||
850 | * to link buffers together for a sort of scatter-gather | ||
851 | * operation. | ||
852 | * reject the frame, we don't support scatter-gather yet and | ||
853 | * the frame is probably corrupt anyway | ||
854 | */ | ||
855 | if (rx_stats->rs_more) | 837 | if (rx_stats->rs_more) |
856 | return false; | 838 | return true; |
857 | 839 | ||
858 | /* | 840 | /* |
859 | * The rx_stats->rs_status will not be set until the end of the | 841 | * The rx_stats->rs_status will not be set until the end of the |
@@ -870,22 +852,28 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
870 | if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { | 852 | if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { |
871 | *decrypt_error = true; | 853 | *decrypt_error = true; |
872 | } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { | 854 | } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { |
873 | if (ieee80211_is_ctl(fc)) | 855 | bool is_mc; |
874 | /* | 856 | /* |
875 | * Sometimes, we get invalid | 857 | * The MIC error bit is only valid if the frame |
876 | * MIC failures on valid control frames. | 858 | * is not a control frame or fragment, and it was |
877 | * Remove these mic errors. | 859 | * decrypted using a valid TKIP key. |
878 | */ | 860 | */ |
879 | rx_stats->rs_status &= ~ATH9K_RXERR_MIC; | 861 | is_mc = !!is_multicast_ether_addr(hdr->addr1); |
880 | else | 862 | |
863 | if (!ieee80211_is_ctl(fc) && | ||
864 | !ieee80211_has_morefrags(fc) && | ||
865 | !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && | ||
866 | is_mc_or_valid_tkip_keyix) | ||
881 | rxs->flag |= RX_FLAG_MMIC_ERROR; | 867 | rxs->flag |= RX_FLAG_MMIC_ERROR; |
868 | else | ||
869 | rx_stats->rs_status &= ~ATH9K_RXERR_MIC; | ||
882 | } | 870 | } |
883 | /* | 871 | /* |
884 | * Reject error frames with the exception of | 872 | * Reject error frames with the exception of |
885 | * decryption and MIC failures. For monitor mode, | 873 | * decryption and MIC failures. For monitor mode, |
886 | * we also ignore the CRC error. | 874 | * we also ignore the CRC error. |
887 | */ | 875 | */ |
888 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | 876 | if (ah->is_monitoring) { |
889 | if (rx_stats->rs_status & | 877 | if (rx_stats->rs_status & |
890 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | 878 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | |
891 | ATH9K_RXERR_CRC)) | 879 | ATH9K_RXERR_CRC)) |
@@ -939,8 +927,9 @@ static int ath9k_process_rate(struct ath_common *common, | |||
939 | * No valid hardware bitrate found -- we should not get here | 927 | * No valid hardware bitrate found -- we should not get here |
940 | * because hardware has already validated this frame as OK. | 928 | * because hardware has already validated this frame as OK. |
941 | */ | 929 | */ |
942 | ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " | 930 | ath_dbg(common, ATH_DBG_XMIT, |
943 | "0x%02x using 1 Mbit\n", rx_stats->rs_rate); | 931 | "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", |
932 | rx_stats->rs_rate); | ||
944 | 933 | ||
945 | return -EINVAL; | 934 | return -EINVAL; |
946 | } | 935 | } |
@@ -950,32 +939,30 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
950 | struct ieee80211_hdr *hdr, | 939 | struct ieee80211_hdr *hdr, |
951 | struct ath_rx_status *rx_stats) | 940 | struct ath_rx_status *rx_stats) |
952 | { | 941 | { |
942 | struct ath_softc *sc = hw->priv; | ||
953 | struct ath_hw *ah = common->ah; | 943 | struct ath_hw *ah = common->ah; |
954 | struct ieee80211_sta *sta; | 944 | int last_rssi; |
955 | struct ath_node *an; | ||
956 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
957 | __le16 fc; | 945 | __le16 fc; |
958 | 946 | ||
959 | fc = hdr->frame_control; | 947 | if ((ah->opmode != NL80211_IFTYPE_STATION) && |
948 | (ah->opmode != NL80211_IFTYPE_ADHOC)) | ||
949 | return; | ||
960 | 950 | ||
961 | rcu_read_lock(); | 951 | fc = hdr->frame_control; |
962 | /* | 952 | if (!ieee80211_is_beacon(fc) || |
963 | * XXX: use ieee80211_find_sta! This requires quite a bit of work | 953 | compare_ether_addr(hdr->addr3, common->curbssid)) { |
964 | * under the current ath9k virtual wiphy implementation as we have | 954 | /* TODO: This doesn't work well if you have stations |
965 | * no way of tying a vif to wiphy. Typically vifs are attached to | 955 | * associated to two different APs because curbssid |
966 | * at least one sdata of a wiphy on mac80211 but with ath9k virtual | 956 | * is just the last AP that any of the stations associated |
967 | * wiphy you'd have to iterate over every wiphy and each sdata. | 957 | * with. |
968 | */ | 958 | */ |
969 | sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); | 959 | return; |
970 | if (sta) { | ||
971 | an = (struct ath_node *) sta->drv_priv; | ||
972 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && | ||
973 | !rx_stats->rs_moreaggr) | ||
974 | ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); | ||
975 | last_rssi = an->last_rssi; | ||
976 | } | 960 | } |
977 | rcu_read_unlock(); | ||
978 | 961 | ||
962 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) | ||
963 | ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); | ||
964 | |||
965 | last_rssi = sc->last_rssi; | ||
979 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 966 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
980 | rx_stats->rs_rssi = ATH_EP_RND(last_rssi, | 967 | rx_stats->rs_rssi = ATH_EP_RND(last_rssi, |
981 | ATH_RSSI_EP_MULTIPLIER); | 968 | ATH_RSSI_EP_MULTIPLIER); |
@@ -983,8 +970,7 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
983 | rx_stats->rs_rssi = 0; | 970 | rx_stats->rs_rssi = 0; |
984 | 971 | ||
985 | /* Update Beacon RSSI, this is used by ANI. */ | 972 | /* Update Beacon RSSI, this is used by ANI. */ |
986 | if (ieee80211_is_beacon(fc)) | 973 | ah->stats.avgbrssi = rx_stats->rs_rssi; |
987 | ah->stats.avgbrssi = rx_stats->rs_rssi; | ||
988 | } | 974 | } |
989 | 975 | ||
990 | /* | 976 | /* |
@@ -1008,6 +994,10 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
1008 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) | 994 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) |
1009 | return -EINVAL; | 995 | return -EINVAL; |
1010 | 996 | ||
997 | /* Only use status info from the last fragment */ | ||
998 | if (rx_stats->rs_more) | ||
999 | return 0; | ||
1000 | |||
1011 | ath9k_process_rssi(common, hw, hdr, rx_stats); | 1001 | ath9k_process_rssi(common, hw, hdr, rx_stats); |
1012 | 1002 | ||
1013 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) | 1003 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) |
@@ -1017,7 +1007,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
1017 | rx_status->freq = hw->conf.channel->center_freq; | 1007 | rx_status->freq = hw->conf.channel->center_freq; |
1018 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; | 1008 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; |
1019 | rx_status->antenna = rx_stats->rs_antenna; | 1009 | rx_status->antenna = rx_stats->rs_antenna; |
1020 | rx_status->flag |= RX_FLAG_TSFT; | 1010 | rx_status->flag |= RX_FLAG_MACTIME_MPDU; |
1021 | 1011 | ||
1022 | return 0; | 1012 | return 0; |
1023 | } | 1013 | } |
@@ -1073,19 +1063,641 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, | |||
1073 | rxs->flag &= ~RX_FLAG_DECRYPTED; | 1063 | rxs->flag &= ~RX_FLAG_DECRYPTED; |
1074 | } | 1064 | } |
1075 | 1065 | ||
1066 | static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, | ||
1067 | struct ath_hw_antcomb_conf ant_conf, | ||
1068 | int main_rssi_avg) | ||
1069 | { | ||
1070 | antcomb->quick_scan_cnt = 0; | ||
1071 | |||
1072 | if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1073 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1074 | else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1075 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1076 | |||
1077 | switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { | ||
1078 | case (0x10): /* LNA2 A-B */ | ||
1079 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1080 | antcomb->first_quick_scan_conf = | ||
1081 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1082 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1083 | break; | ||
1084 | case (0x20): /* LNA1 A-B */ | ||
1085 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1086 | antcomb->first_quick_scan_conf = | ||
1087 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1088 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1089 | break; | ||
1090 | case (0x21): /* LNA1 LNA2 */ | ||
1091 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1092 | antcomb->first_quick_scan_conf = | ||
1093 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1094 | antcomb->second_quick_scan_conf = | ||
1095 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1096 | break; | ||
1097 | case (0x12): /* LNA2 LNA1 */ | ||
1098 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1099 | antcomb->first_quick_scan_conf = | ||
1100 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1101 | antcomb->second_quick_scan_conf = | ||
1102 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1103 | break; | ||
1104 | case (0x13): /* LNA2 A+B */ | ||
1105 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1106 | antcomb->first_quick_scan_conf = | ||
1107 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1108 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1109 | break; | ||
1110 | case (0x23): /* LNA1 A+B */ | ||
1111 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1112 | antcomb->first_quick_scan_conf = | ||
1113 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1114 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1115 | break; | ||
1116 | default: | ||
1117 | break; | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1121 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | ||
1122 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
1123 | int main_rssi_avg, int alt_rssi_avg, | ||
1124 | int alt_ratio) | ||
1125 | { | ||
1126 | /* alt_good */ | ||
1127 | switch (antcomb->quick_scan_cnt) { | ||
1128 | case 0: | ||
1129 | /* set alt to main, and alt to first conf */ | ||
1130 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1131 | div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; | ||
1132 | break; | ||
1133 | case 1: | ||
1134 | /* set alt to main, and alt to first conf */ | ||
1135 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1136 | div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
1137 | antcomb->rssi_first = main_rssi_avg; | ||
1138 | antcomb->rssi_second = alt_rssi_avg; | ||
1139 | |||
1140 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1141 | /* main is LNA1 */ | ||
1142 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1143 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1144 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1145 | main_rssi_avg, alt_rssi_avg, | ||
1146 | antcomb->total_pkt_count)) | ||
1147 | antcomb->first_ratio = true; | ||
1148 | else | ||
1149 | antcomb->first_ratio = false; | ||
1150 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1151 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1152 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1153 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1154 | main_rssi_avg, alt_rssi_avg, | ||
1155 | antcomb->total_pkt_count)) | ||
1156 | antcomb->first_ratio = true; | ||
1157 | else | ||
1158 | antcomb->first_ratio = false; | ||
1159 | } else { | ||
1160 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1161 | (alt_rssi_avg > main_rssi_avg + | ||
1162 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1163 | (alt_rssi_avg > main_rssi_avg)) && | ||
1164 | (antcomb->total_pkt_count > 50)) | ||
1165 | antcomb->first_ratio = true; | ||
1166 | else | ||
1167 | antcomb->first_ratio = false; | ||
1168 | } | ||
1169 | break; | ||
1170 | case 2: | ||
1171 | antcomb->alt_good = false; | ||
1172 | antcomb->scan_not_start = false; | ||
1173 | antcomb->scan = false; | ||
1174 | antcomb->rssi_first = main_rssi_avg; | ||
1175 | antcomb->rssi_third = alt_rssi_avg; | ||
1176 | |||
1177 | if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1178 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1179 | else if (antcomb->second_quick_scan_conf == | ||
1180 | ATH_ANT_DIV_COMB_LNA2) | ||
1181 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1182 | else if (antcomb->second_quick_scan_conf == | ||
1183 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { | ||
1184 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1185 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1186 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1187 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1188 | } | ||
1189 | |||
1190 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | ||
1191 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) | ||
1192 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1193 | else | ||
1194 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1195 | |||
1196 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1197 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1198 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1199 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1200 | main_rssi_avg, alt_rssi_avg, | ||
1201 | antcomb->total_pkt_count)) | ||
1202 | antcomb->second_ratio = true; | ||
1203 | else | ||
1204 | antcomb->second_ratio = false; | ||
1205 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1206 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1207 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1208 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1209 | main_rssi_avg, alt_rssi_avg, | ||
1210 | antcomb->total_pkt_count)) | ||
1211 | antcomb->second_ratio = true; | ||
1212 | else | ||
1213 | antcomb->second_ratio = false; | ||
1214 | } else { | ||
1215 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1216 | (alt_rssi_avg > main_rssi_avg + | ||
1217 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1218 | (alt_rssi_avg > main_rssi_avg)) && | ||
1219 | (antcomb->total_pkt_count > 50)) | ||
1220 | antcomb->second_ratio = true; | ||
1221 | else | ||
1222 | antcomb->second_ratio = false; | ||
1223 | } | ||
1224 | |||
1225 | /* set alt to the conf with maximun ratio */ | ||
1226 | if (antcomb->first_ratio && antcomb->second_ratio) { | ||
1227 | if (antcomb->rssi_second > antcomb->rssi_third) { | ||
1228 | /* first alt*/ | ||
1229 | if ((antcomb->first_quick_scan_conf == | ||
1230 | ATH_ANT_DIV_COMB_LNA1) || | ||
1231 | (antcomb->first_quick_scan_conf == | ||
1232 | ATH_ANT_DIV_COMB_LNA2)) | ||
1233 | /* Set alt LNA1 or LNA2*/ | ||
1234 | if (div_ant_conf->main_lna_conf == | ||
1235 | ATH_ANT_DIV_COMB_LNA2) | ||
1236 | div_ant_conf->alt_lna_conf = | ||
1237 | ATH_ANT_DIV_COMB_LNA1; | ||
1238 | else | ||
1239 | div_ant_conf->alt_lna_conf = | ||
1240 | ATH_ANT_DIV_COMB_LNA2; | ||
1241 | else | ||
1242 | /* Set alt to A+B or A-B */ | ||
1243 | div_ant_conf->alt_lna_conf = | ||
1244 | antcomb->first_quick_scan_conf; | ||
1245 | } else if ((antcomb->second_quick_scan_conf == | ||
1246 | ATH_ANT_DIV_COMB_LNA1) || | ||
1247 | (antcomb->second_quick_scan_conf == | ||
1248 | ATH_ANT_DIV_COMB_LNA2)) { | ||
1249 | /* Set alt LNA1 or LNA2 */ | ||
1250 | if (div_ant_conf->main_lna_conf == | ||
1251 | ATH_ANT_DIV_COMB_LNA2) | ||
1252 | div_ant_conf->alt_lna_conf = | ||
1253 | ATH_ANT_DIV_COMB_LNA1; | ||
1254 | else | ||
1255 | div_ant_conf->alt_lna_conf = | ||
1256 | ATH_ANT_DIV_COMB_LNA2; | ||
1257 | } else { | ||
1258 | /* Set alt to A+B or A-B */ | ||
1259 | div_ant_conf->alt_lna_conf = | ||
1260 | antcomb->second_quick_scan_conf; | ||
1261 | } | ||
1262 | } else if (antcomb->first_ratio) { | ||
1263 | /* first alt */ | ||
1264 | if ((antcomb->first_quick_scan_conf == | ||
1265 | ATH_ANT_DIV_COMB_LNA1) || | ||
1266 | (antcomb->first_quick_scan_conf == | ||
1267 | ATH_ANT_DIV_COMB_LNA2)) | ||
1268 | /* Set alt LNA1 or LNA2 */ | ||
1269 | if (div_ant_conf->main_lna_conf == | ||
1270 | ATH_ANT_DIV_COMB_LNA2) | ||
1271 | div_ant_conf->alt_lna_conf = | ||
1272 | ATH_ANT_DIV_COMB_LNA1; | ||
1273 | else | ||
1274 | div_ant_conf->alt_lna_conf = | ||
1275 | ATH_ANT_DIV_COMB_LNA2; | ||
1276 | else | ||
1277 | /* Set alt to A+B or A-B */ | ||
1278 | div_ant_conf->alt_lna_conf = | ||
1279 | antcomb->first_quick_scan_conf; | ||
1280 | } else if (antcomb->second_ratio) { | ||
1281 | /* second alt */ | ||
1282 | if ((antcomb->second_quick_scan_conf == | ||
1283 | ATH_ANT_DIV_COMB_LNA1) || | ||
1284 | (antcomb->second_quick_scan_conf == | ||
1285 | ATH_ANT_DIV_COMB_LNA2)) | ||
1286 | /* Set alt LNA1 or LNA2 */ | ||
1287 | if (div_ant_conf->main_lna_conf == | ||
1288 | ATH_ANT_DIV_COMB_LNA2) | ||
1289 | div_ant_conf->alt_lna_conf = | ||
1290 | ATH_ANT_DIV_COMB_LNA1; | ||
1291 | else | ||
1292 | div_ant_conf->alt_lna_conf = | ||
1293 | ATH_ANT_DIV_COMB_LNA2; | ||
1294 | else | ||
1295 | /* Set alt to A+B or A-B */ | ||
1296 | div_ant_conf->alt_lna_conf = | ||
1297 | antcomb->second_quick_scan_conf; | ||
1298 | } else { | ||
1299 | /* main is largest */ | ||
1300 | if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
1301 | (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
1302 | /* Set alt LNA1 or LNA2 */ | ||
1303 | if (div_ant_conf->main_lna_conf == | ||
1304 | ATH_ANT_DIV_COMB_LNA2) | ||
1305 | div_ant_conf->alt_lna_conf = | ||
1306 | ATH_ANT_DIV_COMB_LNA1; | ||
1307 | else | ||
1308 | div_ant_conf->alt_lna_conf = | ||
1309 | ATH_ANT_DIV_COMB_LNA2; | ||
1310 | else | ||
1311 | /* Set alt to A+B or A-B */ | ||
1312 | div_ant_conf->alt_lna_conf = antcomb->main_conf; | ||
1313 | } | ||
1314 | break; | ||
1315 | default: | ||
1316 | break; | ||
1317 | } | ||
1318 | } | ||
1319 | |||
1320 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | ||
1321 | struct ath_ant_comb *antcomb, int alt_ratio) | ||
1322 | { | ||
1323 | if (ant_conf->div_group == 0) { | ||
1324 | /* Adjust the fast_div_bias based on main and alt lna conf */ | ||
1325 | switch ((ant_conf->main_lna_conf << 4) | | ||
1326 | ant_conf->alt_lna_conf) { | ||
1327 | case (0x01): /* A-B LNA2 */ | ||
1328 | ant_conf->fast_div_bias = 0x3b; | ||
1329 | break; | ||
1330 | case (0x02): /* A-B LNA1 */ | ||
1331 | ant_conf->fast_div_bias = 0x3d; | ||
1332 | break; | ||
1333 | case (0x03): /* A-B A+B */ | ||
1334 | ant_conf->fast_div_bias = 0x1; | ||
1335 | break; | ||
1336 | case (0x10): /* LNA2 A-B */ | ||
1337 | ant_conf->fast_div_bias = 0x7; | ||
1338 | break; | ||
1339 | case (0x12): /* LNA2 LNA1 */ | ||
1340 | ant_conf->fast_div_bias = 0x2; | ||
1341 | break; | ||
1342 | case (0x13): /* LNA2 A+B */ | ||
1343 | ant_conf->fast_div_bias = 0x7; | ||
1344 | break; | ||
1345 | case (0x20): /* LNA1 A-B */ | ||
1346 | ant_conf->fast_div_bias = 0x6; | ||
1347 | break; | ||
1348 | case (0x21): /* LNA1 LNA2 */ | ||
1349 | ant_conf->fast_div_bias = 0x0; | ||
1350 | break; | ||
1351 | case (0x23): /* LNA1 A+B */ | ||
1352 | ant_conf->fast_div_bias = 0x6; | ||
1353 | break; | ||
1354 | case (0x30): /* A+B A-B */ | ||
1355 | ant_conf->fast_div_bias = 0x1; | ||
1356 | break; | ||
1357 | case (0x31): /* A+B LNA2 */ | ||
1358 | ant_conf->fast_div_bias = 0x3b; | ||
1359 | break; | ||
1360 | case (0x32): /* A+B LNA1 */ | ||
1361 | ant_conf->fast_div_bias = 0x3d; | ||
1362 | break; | ||
1363 | default: | ||
1364 | break; | ||
1365 | } | ||
1366 | } else if (ant_conf->div_group == 2) { | ||
1367 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
1368 | switch ((ant_conf->main_lna_conf << 4) | | ||
1369 | ant_conf->alt_lna_conf) { | ||
1370 | case (0x01): /* A-B LNA2 */ | ||
1371 | ant_conf->fast_div_bias = 0x1; | ||
1372 | ant_conf->main_gaintb = 0; | ||
1373 | ant_conf->alt_gaintb = 0; | ||
1374 | break; | ||
1375 | case (0x02): /* A-B LNA1 */ | ||
1376 | ant_conf->fast_div_bias = 0x1; | ||
1377 | ant_conf->main_gaintb = 0; | ||
1378 | ant_conf->alt_gaintb = 0; | ||
1379 | break; | ||
1380 | case (0x03): /* A-B A+B */ | ||
1381 | ant_conf->fast_div_bias = 0x1; | ||
1382 | ant_conf->main_gaintb = 0; | ||
1383 | ant_conf->alt_gaintb = 0; | ||
1384 | break; | ||
1385 | case (0x10): /* LNA2 A-B */ | ||
1386 | if (!(antcomb->scan) && | ||
1387 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1388 | ant_conf->fast_div_bias = 0x1; | ||
1389 | else | ||
1390 | ant_conf->fast_div_bias = 0x2; | ||
1391 | ant_conf->main_gaintb = 0; | ||
1392 | ant_conf->alt_gaintb = 0; | ||
1393 | break; | ||
1394 | case (0x12): /* LNA2 LNA1 */ | ||
1395 | ant_conf->fast_div_bias = 0x1; | ||
1396 | ant_conf->main_gaintb = 0; | ||
1397 | ant_conf->alt_gaintb = 0; | ||
1398 | break; | ||
1399 | case (0x13): /* LNA2 A+B */ | ||
1400 | if (!(antcomb->scan) && | ||
1401 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1402 | ant_conf->fast_div_bias = 0x1; | ||
1403 | else | ||
1404 | ant_conf->fast_div_bias = 0x2; | ||
1405 | ant_conf->main_gaintb = 0; | ||
1406 | ant_conf->alt_gaintb = 0; | ||
1407 | break; | ||
1408 | case (0x20): /* LNA1 A-B */ | ||
1409 | if (!(antcomb->scan) && | ||
1410 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1411 | ant_conf->fast_div_bias = 0x1; | ||
1412 | else | ||
1413 | ant_conf->fast_div_bias = 0x2; | ||
1414 | ant_conf->main_gaintb = 0; | ||
1415 | ant_conf->alt_gaintb = 0; | ||
1416 | break; | ||
1417 | case (0x21): /* LNA1 LNA2 */ | ||
1418 | ant_conf->fast_div_bias = 0x1; | ||
1419 | ant_conf->main_gaintb = 0; | ||
1420 | ant_conf->alt_gaintb = 0; | ||
1421 | break; | ||
1422 | case (0x23): /* LNA1 A+B */ | ||
1423 | if (!(antcomb->scan) && | ||
1424 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1425 | ant_conf->fast_div_bias = 0x1; | ||
1426 | else | ||
1427 | ant_conf->fast_div_bias = 0x2; | ||
1428 | ant_conf->main_gaintb = 0; | ||
1429 | ant_conf->alt_gaintb = 0; | ||
1430 | break; | ||
1431 | case (0x30): /* A+B A-B */ | ||
1432 | ant_conf->fast_div_bias = 0x1; | ||
1433 | ant_conf->main_gaintb = 0; | ||
1434 | ant_conf->alt_gaintb = 0; | ||
1435 | break; | ||
1436 | case (0x31): /* A+B LNA2 */ | ||
1437 | ant_conf->fast_div_bias = 0x1; | ||
1438 | ant_conf->main_gaintb = 0; | ||
1439 | ant_conf->alt_gaintb = 0; | ||
1440 | break; | ||
1441 | case (0x32): /* A+B LNA1 */ | ||
1442 | ant_conf->fast_div_bias = 0x1; | ||
1443 | ant_conf->main_gaintb = 0; | ||
1444 | ant_conf->alt_gaintb = 0; | ||
1445 | break; | ||
1446 | default: | ||
1447 | break; | ||
1448 | } | ||
1449 | |||
1450 | } | ||
1451 | |||
1452 | } | ||
1453 | |||
1454 | /* Antenna diversity and combining */ | ||
1455 | static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | ||
1456 | { | ||
1457 | struct ath_hw_antcomb_conf div_ant_conf; | ||
1458 | struct ath_ant_comb *antcomb = &sc->ant_comb; | ||
1459 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; | ||
1460 | int curr_main_set; | ||
1461 | int main_rssi = rs->rs_rssi_ctl0; | ||
1462 | int alt_rssi = rs->rs_rssi_ctl1; | ||
1463 | int rx_ant_conf, main_ant_conf; | ||
1464 | bool short_scan = false; | ||
1465 | |||
1466 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | ||
1467 | ATH_ANT_RX_MASK; | ||
1468 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | ||
1469 | ATH_ANT_RX_MASK; | ||
1470 | |||
1471 | /* Record packet only when both main_rssi and alt_rssi is positive */ | ||
1472 | if (main_rssi > 0 && alt_rssi > 0) { | ||
1473 | antcomb->total_pkt_count++; | ||
1474 | antcomb->main_total_rssi += main_rssi; | ||
1475 | antcomb->alt_total_rssi += alt_rssi; | ||
1476 | if (main_ant_conf == rx_ant_conf) | ||
1477 | antcomb->main_recv_cnt++; | ||
1478 | else | ||
1479 | antcomb->alt_recv_cnt++; | ||
1480 | } | ||
1481 | |||
1482 | /* Short scan check */ | ||
1483 | if (antcomb->scan && antcomb->alt_good) { | ||
1484 | if (time_after(jiffies, antcomb->scan_start_time + | ||
1485 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | ||
1486 | short_scan = true; | ||
1487 | else | ||
1488 | if (antcomb->total_pkt_count == | ||
1489 | ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
1490 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1491 | antcomb->total_pkt_count); | ||
1492 | if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
1493 | short_scan = true; | ||
1494 | } | ||
1495 | } | ||
1496 | |||
1497 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || | ||
1498 | rs->rs_moreaggr) && !short_scan) | ||
1499 | return; | ||
1500 | |||
1501 | if (antcomb->total_pkt_count) { | ||
1502 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1503 | antcomb->total_pkt_count); | ||
1504 | main_rssi_avg = (antcomb->main_total_rssi / | ||
1505 | antcomb->total_pkt_count); | ||
1506 | alt_rssi_avg = (antcomb->alt_total_rssi / | ||
1507 | antcomb->total_pkt_count); | ||
1508 | } | ||
1509 | |||
1510 | |||
1511 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); | ||
1512 | curr_alt_set = div_ant_conf.alt_lna_conf; | ||
1513 | curr_main_set = div_ant_conf.main_lna_conf; | ||
1514 | |||
1515 | antcomb->count++; | ||
1516 | |||
1517 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { | ||
1518 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
1519 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, | ||
1520 | main_rssi_avg); | ||
1521 | antcomb->alt_good = true; | ||
1522 | } else { | ||
1523 | antcomb->alt_good = false; | ||
1524 | } | ||
1525 | |||
1526 | antcomb->count = 0; | ||
1527 | antcomb->scan = true; | ||
1528 | antcomb->scan_not_start = true; | ||
1529 | } | ||
1530 | |||
1531 | if (!antcomb->scan) { | ||
1532 | if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, | ||
1533 | alt_ratio, curr_main_set, curr_alt_set, | ||
1534 | alt_rssi_avg, main_rssi_avg)) { | ||
1535 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1536 | /* Switch main and alt LNA */ | ||
1537 | div_ant_conf.main_lna_conf = | ||
1538 | ATH_ANT_DIV_COMB_LNA2; | ||
1539 | div_ant_conf.alt_lna_conf = | ||
1540 | ATH_ANT_DIV_COMB_LNA1; | ||
1541 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1542 | div_ant_conf.main_lna_conf = | ||
1543 | ATH_ANT_DIV_COMB_LNA1; | ||
1544 | div_ant_conf.alt_lna_conf = | ||
1545 | ATH_ANT_DIV_COMB_LNA2; | ||
1546 | } | ||
1547 | |||
1548 | goto div_comb_done; | ||
1549 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
1550 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
1551 | /* Set alt to another LNA */ | ||
1552 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
1553 | div_ant_conf.alt_lna_conf = | ||
1554 | ATH_ANT_DIV_COMB_LNA1; | ||
1555 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
1556 | div_ant_conf.alt_lna_conf = | ||
1557 | ATH_ANT_DIV_COMB_LNA2; | ||
1558 | |||
1559 | goto div_comb_done; | ||
1560 | } | ||
1561 | |||
1562 | if ((alt_rssi_avg < (main_rssi_avg + | ||
1563 | div_ant_conf.lna1_lna2_delta))) | ||
1564 | goto div_comb_done; | ||
1565 | } | ||
1566 | |||
1567 | if (!antcomb->scan_not_start) { | ||
1568 | switch (curr_alt_set) { | ||
1569 | case ATH_ANT_DIV_COMB_LNA2: | ||
1570 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1571 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1572 | antcomb->scan = true; | ||
1573 | /* set to A+B */ | ||
1574 | div_ant_conf.main_lna_conf = | ||
1575 | ATH_ANT_DIV_COMB_LNA1; | ||
1576 | div_ant_conf.alt_lna_conf = | ||
1577 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1578 | break; | ||
1579 | case ATH_ANT_DIV_COMB_LNA1: | ||
1580 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1581 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1582 | antcomb->scan = true; | ||
1583 | /* set to A+B */ | ||
1584 | div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1585 | div_ant_conf.alt_lna_conf = | ||
1586 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1587 | break; | ||
1588 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
1589 | antcomb->rssi_add = alt_rssi_avg; | ||
1590 | antcomb->scan = true; | ||
1591 | /* set to A-B */ | ||
1592 | div_ant_conf.alt_lna_conf = | ||
1593 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1594 | break; | ||
1595 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
1596 | antcomb->rssi_sub = alt_rssi_avg; | ||
1597 | antcomb->scan = false; | ||
1598 | if (antcomb->rssi_lna2 > | ||
1599 | (antcomb->rssi_lna1 + | ||
1600 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
1601 | /* use LNA2 as main LNA */ | ||
1602 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
1603 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1604 | /* set to A+B */ | ||
1605 | div_ant_conf.main_lna_conf = | ||
1606 | ATH_ANT_DIV_COMB_LNA2; | ||
1607 | div_ant_conf.alt_lna_conf = | ||
1608 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1609 | } else if (antcomb->rssi_sub > | ||
1610 | antcomb->rssi_lna1) { | ||
1611 | /* set to A-B */ | ||
1612 | div_ant_conf.main_lna_conf = | ||
1613 | ATH_ANT_DIV_COMB_LNA2; | ||
1614 | div_ant_conf.alt_lna_conf = | ||
1615 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1616 | } else { | ||
1617 | /* set to LNA1 */ | ||
1618 | div_ant_conf.main_lna_conf = | ||
1619 | ATH_ANT_DIV_COMB_LNA2; | ||
1620 | div_ant_conf.alt_lna_conf = | ||
1621 | ATH_ANT_DIV_COMB_LNA1; | ||
1622 | } | ||
1623 | } else { | ||
1624 | /* use LNA1 as main LNA */ | ||
1625 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
1626 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1627 | /* set to A+B */ | ||
1628 | div_ant_conf.main_lna_conf = | ||
1629 | ATH_ANT_DIV_COMB_LNA1; | ||
1630 | div_ant_conf.alt_lna_conf = | ||
1631 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1632 | } else if (antcomb->rssi_sub > | ||
1633 | antcomb->rssi_lna1) { | ||
1634 | /* set to A-B */ | ||
1635 | div_ant_conf.main_lna_conf = | ||
1636 | ATH_ANT_DIV_COMB_LNA1; | ||
1637 | div_ant_conf.alt_lna_conf = | ||
1638 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1639 | } else { | ||
1640 | /* set to LNA2 */ | ||
1641 | div_ant_conf.main_lna_conf = | ||
1642 | ATH_ANT_DIV_COMB_LNA1; | ||
1643 | div_ant_conf.alt_lna_conf = | ||
1644 | ATH_ANT_DIV_COMB_LNA2; | ||
1645 | } | ||
1646 | } | ||
1647 | break; | ||
1648 | default: | ||
1649 | break; | ||
1650 | } | ||
1651 | } else { | ||
1652 | if (!antcomb->alt_good) { | ||
1653 | antcomb->scan_not_start = false; | ||
1654 | /* Set alt to another LNA */ | ||
1655 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1656 | div_ant_conf.main_lna_conf = | ||
1657 | ATH_ANT_DIV_COMB_LNA2; | ||
1658 | div_ant_conf.alt_lna_conf = | ||
1659 | ATH_ANT_DIV_COMB_LNA1; | ||
1660 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1661 | div_ant_conf.main_lna_conf = | ||
1662 | ATH_ANT_DIV_COMB_LNA1; | ||
1663 | div_ant_conf.alt_lna_conf = | ||
1664 | ATH_ANT_DIV_COMB_LNA2; | ||
1665 | } | ||
1666 | goto div_comb_done; | ||
1667 | } | ||
1668 | } | ||
1669 | |||
1670 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
1671 | main_rssi_avg, alt_rssi_avg, | ||
1672 | alt_ratio); | ||
1673 | |||
1674 | antcomb->quick_scan_cnt++; | ||
1675 | |||
1676 | div_comb_done: | ||
1677 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); | ||
1678 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | ||
1679 | |||
1680 | antcomb->scan_start_time = jiffies; | ||
1681 | antcomb->total_pkt_count = 0; | ||
1682 | antcomb->main_total_rssi = 0; | ||
1683 | antcomb->alt_total_rssi = 0; | ||
1684 | antcomb->main_recv_cnt = 0; | ||
1685 | antcomb->alt_recv_cnt = 0; | ||
1686 | } | ||
1687 | |||
1076 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1688 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1077 | { | 1689 | { |
1078 | struct ath_buf *bf; | 1690 | struct ath_buf *bf; |
1079 | struct sk_buff *skb = NULL, *requeue_skb; | 1691 | struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; |
1080 | struct ieee80211_rx_status *rxs; | 1692 | struct ieee80211_rx_status *rxs; |
1081 | struct ath_hw *ah = sc->sc_ah; | 1693 | struct ath_hw *ah = sc->sc_ah; |
1082 | struct ath_common *common = ath9k_hw_common(ah); | 1694 | struct ath_common *common = ath9k_hw_common(ah); |
1083 | /* | 1695 | /* |
1084 | * The hw can techncically differ from common->hw when using ath9k | 1696 | * The hw can technically differ from common->hw when using ath9k |
1085 | * virtual wiphy so to account for that we iterate over the active | 1697 | * virtual wiphy so to account for that we iterate over the active |
1086 | * wiphys and find the appropriate wiphy and therefore hw. | 1698 | * wiphys and find the appropriate wiphy and therefore hw. |
1087 | */ | 1699 | */ |
1088 | struct ieee80211_hw *hw = NULL; | 1700 | struct ieee80211_hw *hw = sc->hw; |
1089 | struct ieee80211_hdr *hdr; | 1701 | struct ieee80211_hdr *hdr; |
1090 | int retval; | 1702 | int retval; |
1091 | bool decrypt_error = false; | 1703 | bool decrypt_error = false; |
@@ -1096,6 +1708,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1096 | u8 rx_status_len = ah->caps.rx_status_len; | 1708 | u8 rx_status_len = ah->caps.rx_status_len; |
1097 | u64 tsf = 0; | 1709 | u64 tsf = 0; |
1098 | u32 tsf_lower = 0; | 1710 | u32 tsf_lower = 0; |
1711 | unsigned long flags; | ||
1099 | 1712 | ||
1100 | if (edma) | 1713 | if (edma) |
1101 | dma_type = DMA_BIDIRECTIONAL; | 1714 | dma_type = DMA_BIDIRECTIONAL; |
@@ -1126,10 +1739,17 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1126 | if (!skb) | 1739 | if (!skb) |
1127 | continue; | 1740 | continue; |
1128 | 1741 | ||
1129 | hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len); | 1742 | /* |
1130 | rxs = IEEE80211_SKB_RXCB(skb); | 1743 | * Take frame header from the first fragment and RX status from |
1744 | * the last one. | ||
1745 | */ | ||
1746 | if (sc->rx.frag) | ||
1747 | hdr_skb = sc->rx.frag; | ||
1748 | else | ||
1749 | hdr_skb = skb; | ||
1131 | 1750 | ||
1132 | hw = ath_get_virt_hw(sc, hdr); | 1751 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); |
1752 | rxs = IEEE80211_SKB_RXCB(hdr_skb); | ||
1133 | 1753 | ||
1134 | ath_debug_stat_rx(sc, &rs); | 1754 | ath_debug_stat_rx(sc, &rs); |
1135 | 1755 | ||
@@ -1138,12 +1758,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1138 | * chain it back at the queue without processing it. | 1758 | * chain it back at the queue without processing it. |
1139 | */ | 1759 | */ |
1140 | if (flush) | 1760 | if (flush) |
1141 | goto requeue; | 1761 | goto requeue_drop_frag; |
1142 | 1762 | ||
1143 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | 1763 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, |
1144 | rxs, &decrypt_error); | 1764 | rxs, &decrypt_error); |
1145 | if (retval) | 1765 | if (retval) |
1146 | goto requeue; | 1766 | goto requeue_drop_frag; |
1147 | 1767 | ||
1148 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1768 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
1149 | if (rs.rs_tstamp > tsf_lower && | 1769 | if (rs.rs_tstamp > tsf_lower && |
@@ -1163,7 +1783,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1163 | * skb and put it at the tail of the sc->rx.rxbuf list for | 1783 | * skb and put it at the tail of the sc->rx.rxbuf list for |
1164 | * processing. */ | 1784 | * processing. */ |
1165 | if (!requeue_skb) | 1785 | if (!requeue_skb) |
1166 | goto requeue; | 1786 | goto requeue_drop_frag; |
1167 | 1787 | ||
1168 | /* Unmap the frame */ | 1788 | /* Unmap the frame */ |
1169 | dma_unmap_single(sc->dev, bf->bf_buf_addr, | 1789 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
@@ -1174,8 +1794,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1174 | if (ah->caps.rx_status_len) | 1794 | if (ah->caps.rx_status_len) |
1175 | skb_pull(skb, ah->caps.rx_status_len); | 1795 | skb_pull(skb, ah->caps.rx_status_len); |
1176 | 1796 | ||
1177 | ath9k_rx_skb_postprocess(common, skb, &rs, | 1797 | if (!rs.rs_more) |
1178 | rxs, decrypt_error); | 1798 | ath9k_rx_skb_postprocess(common, hdr_skb, &rs, |
1799 | rxs, decrypt_error); | ||
1179 | 1800 | ||
1180 | /* We will now give hardware our shiny new allocated skb */ | 1801 | /* We will now give hardware our shiny new allocated skb */ |
1181 | bf->bf_mpdu = requeue_skb; | 1802 | bf->bf_mpdu = requeue_skb; |
@@ -1186,12 +1807,43 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1186 | bf->bf_buf_addr))) { | 1807 | bf->bf_buf_addr))) { |
1187 | dev_kfree_skb_any(requeue_skb); | 1808 | dev_kfree_skb_any(requeue_skb); |
1188 | bf->bf_mpdu = NULL; | 1809 | bf->bf_mpdu = NULL; |
1189 | ath_print(common, ATH_DBG_FATAL, | 1810 | bf->bf_buf_addr = 0; |
1190 | "dma_mapping_error() on RX\n"); | 1811 | ath_err(common, "dma_mapping_error() on RX\n"); |
1191 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); | 1812 | ieee80211_rx(hw, skb); |
1192 | break; | 1813 | break; |
1193 | } | 1814 | } |
1194 | bf->bf_dmacontext = bf->bf_buf_addr; | 1815 | |
1816 | if (rs.rs_more) { | ||
1817 | /* | ||
1818 | * rs_more indicates chained descriptors which can be | ||
1819 | * used to link buffers together for a sort of | ||
1820 | * scatter-gather operation. | ||
1821 | */ | ||
1822 | if (sc->rx.frag) { | ||
1823 | /* too many fragments - cannot handle frame */ | ||
1824 | dev_kfree_skb_any(sc->rx.frag); | ||
1825 | dev_kfree_skb_any(skb); | ||
1826 | skb = NULL; | ||
1827 | } | ||
1828 | sc->rx.frag = skb; | ||
1829 | goto requeue; | ||
1830 | } | ||
1831 | |||
1832 | if (sc->rx.frag) { | ||
1833 | int space = skb->len - skb_tailroom(hdr_skb); | ||
1834 | |||
1835 | sc->rx.frag = NULL; | ||
1836 | |||
1837 | if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) { | ||
1838 | dev_kfree_skb(skb); | ||
1839 | goto requeue_drop_frag; | ||
1840 | } | ||
1841 | |||
1842 | skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len), | ||
1843 | skb->len); | ||
1844 | dev_kfree_skb_any(skb); | ||
1845 | skb = hdr_skb; | ||
1846 | } | ||
1195 | 1847 | ||
1196 | /* | 1848 | /* |
1197 | * change the default rx antenna if rx diversity chooses the | 1849 | * change the default rx antenna if rx diversity chooses the |
@@ -1204,14 +1856,25 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1204 | sc->rx.rxotherant = 0; | 1856 | sc->rx.rxotherant = 0; |
1205 | } | 1857 | } |
1206 | 1858 | ||
1207 | if (unlikely(ath9k_check_auto_sleep(sc) || | 1859 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
1208 | (sc->ps_flags & (PS_WAIT_FOR_BEACON | | 1860 | |
1861 | if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | | ||
1209 | PS_WAIT_FOR_CAB | | 1862 | PS_WAIT_FOR_CAB | |
1210 | PS_WAIT_FOR_PSPOLL_DATA)))) | 1863 | PS_WAIT_FOR_PSPOLL_DATA)) || |
1864 | ath9k_check_auto_sleep(sc)) | ||
1211 | ath_rx_ps(sc, skb); | 1865 | ath_rx_ps(sc, skb); |
1866 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1212 | 1867 | ||
1213 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); | 1868 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) |
1869 | ath_ant_comb_scan(sc, &rs); | ||
1214 | 1870 | ||
1871 | ieee80211_rx(hw, skb); | ||
1872 | |||
1873 | requeue_drop_frag: | ||
1874 | if (sc->rx.frag) { | ||
1875 | dev_kfree_skb_any(sc->rx.frag); | ||
1876 | sc->rx.frag = NULL; | ||
1877 | } | ||
1215 | requeue: | 1878 | requeue: |
1216 | if (edma) { | 1879 | if (edma) { |
1217 | list_add_tail(&bf->list, &sc->rx.rxbuf); | 1880 | list_add_tail(&bf->list, &sc->rx.rxbuf); |
@@ -1219,6 +1882,7 @@ requeue: | |||
1219 | } else { | 1882 | } else { |
1220 | list_move_tail(&bf->list, &sc->rx.rxbuf); | 1883 | list_move_tail(&bf->list, &sc->rx.rxbuf); |
1221 | ath_rx_buf_link(sc, bf); | 1884 | ath_rx_buf_link(sc, bf); |
1885 | ath9k_hw_rxena(ah); | ||
1222 | } | 1886 | } |
1223 | } while (1); | 1887 | } while (1); |
1224 | 1888 | ||