aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath9k/core.c')
-rw-r--r--drivers/net/wireless/ath9k/core.c129
1 files changed, 122 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c
index 5af7dfbd423..c5033f6f42a 100644
--- a/drivers/net/wireless/ath9k/core.c
+++ b/drivers/net/wireless/ath9k/core.c
@@ -490,6 +490,122 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht)
490 __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask); 490 __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask);
491} 491}
492 492
493/*******/
494/* ANI */
495/*******/
496
497/*
498 * This routine performs the periodic noise floor calibration function
499 * that is used to adjust and optimize the chip performance. This
500 * takes environmental changes (location, temperature) into account.
501 * When the task is complete, it reschedules itself depending on the
502 * appropriate interval that was calculated.
503 */
504
505static void ath_ani_calibrate(unsigned long data)
506{
507 struct ath_softc *sc;
508 struct ath_hal *ah;
509 bool longcal = false;
510 bool shortcal = false;
511 bool aniflag = false;
512 unsigned int timestamp = jiffies_to_msecs(jiffies);
513 u32 cal_interval;
514
515 sc = (struct ath_softc *)data;
516 ah = sc->sc_ah;
517
518 /*
519 * don't calibrate when we're scanning.
520 * we are most likely not on our home channel.
521 */
522 if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)
523 return;
524
525 /* Long calibration runs independently of short calibration. */
526 if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) {
527 longcal = true;
528 DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n",
529 __func__, jiffies);
530 sc->sc_ani.sc_longcal_timer = timestamp;
531 }
532
533 /* Short calibration applies only while sc_caldone is false */
534 if (!sc->sc_ani.sc_caldone) {
535 if ((timestamp - sc->sc_ani.sc_shortcal_timer) >=
536 ATH_SHORT_CALINTERVAL) {
537 shortcal = true;
538 DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n",
539 __func__, jiffies);
540 sc->sc_ani.sc_shortcal_timer = timestamp;
541 sc->sc_ani.sc_resetcal_timer = timestamp;
542 }
543 } else {
544 if ((timestamp - sc->sc_ani.sc_resetcal_timer) >=
545 ATH_RESTART_CALINTERVAL) {
546 ath9k_hw_reset_calvalid(ah, ah->ah_curchan,
547 &sc->sc_ani.sc_caldone);
548 if (sc->sc_ani.sc_caldone)
549 sc->sc_ani.sc_resetcal_timer = timestamp;
550 }
551 }
552
553 /* Verify whether we must check ANI */
554 if ((timestamp - sc->sc_ani.sc_checkani_timer) >=
555 ATH_ANI_POLLINTERVAL) {
556 aniflag = true;
557 sc->sc_ani.sc_checkani_timer = timestamp;
558 }
559
560 /* Skip all processing if there's nothing to do. */
561 if (longcal || shortcal || aniflag) {
562 /* Call ANI routine if necessary */
563 if (aniflag)
564 ath9k_hw_ani_monitor(ah, &sc->sc_halstats,
565 ah->ah_curchan);
566
567 /* Perform calibration if necessary */
568 if (longcal || shortcal) {
569 bool iscaldone = false;
570
571 if (ath9k_hw_calibrate(ah, ah->ah_curchan,
572 sc->sc_rx_chainmask, longcal,
573 &iscaldone)) {
574 if (longcal)
575 sc->sc_ani.sc_noise_floor =
576 ath9k_hw_getchan_noise(ah,
577 ah->ah_curchan);
578
579 DPRINTF(sc, ATH_DBG_ANI,
580 "%s: calibrate chan %u/%x nf: %d\n",
581 __func__,
582 ah->ah_curchan->channel,
583 ah->ah_curchan->channelFlags,
584 sc->sc_ani.sc_noise_floor);
585 } else {
586 DPRINTF(sc, ATH_DBG_ANY,
587 "%s: calibrate chan %u/%x failed\n",
588 __func__,
589 ah->ah_curchan->channel,
590 ah->ah_curchan->channelFlags);
591 }
592 sc->sc_ani.sc_caldone = iscaldone;
593 }
594 }
595
596 /*
597 * Set timer interval based on previous results.
598 * The interval must be the shortest necessary to satisfy ANI,
599 * short calibration and long calibration.
600 */
601
602 cal_interval = ATH_ANI_POLLINTERVAL;
603 if (!sc->sc_ani.sc_caldone)
604 cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL);
605
606 mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
607}
608
493/******************/ 609/******************/
494/* VAP management */ 610/* VAP management */
495/******************/ 611/******************/
@@ -676,12 +792,6 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
676 if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) 792 if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
677 sc->sc_imask |= ATH9K_INT_CST; 793 sc->sc_imask |= ATH9K_INT_CST;
678 794
679 /* Note: We disable MIB interrupts for now as we don't yet
680 * handle processing ANI, otherwise you will get an interrupt
681 * storm after about 7 hours of usage making the system unusable
682 * with huge latency. Once we do have ANI processing included
683 * we can re-enable this interrupt. */
684#if 0
685 /* 795 /*
686 * Enable MIB interrupts when there are hardware phy counters. 796 * Enable MIB interrupts when there are hardware phy counters.
687 * Note we only do this (at the moment) for station mode. 797 * Note we only do this (at the moment) for station mode.
@@ -690,7 +800,6 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
690 ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || 800 ((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
691 (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) 801 (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)))
692 sc->sc_imask |= ATH9K_INT_MIB; 802 sc->sc_imask |= ATH9K_INT_MIB;
693#endif
694 /* 803 /*
695 * Some hardware processes the TIM IE and fires an 804 * Some hardware processes the TIM IE and fires an
696 * interrupt when the TIM bit is set. For hardware 805 * interrupt when the TIM bit is set. For hardware
@@ -991,6 +1100,10 @@ int ath_init(u16 devid, struct ath_softc *sc)
991 } 1100 }
992 sc->sc_ah = ah; 1101 sc->sc_ah = ah;
993 1102
1103 /* Initializes the noise floor to a reasonable default value.
1104 * Later on this will be updated during ANI processing. */
1105 sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
1106
994 /* Get the hardware key cache size. */ 1107 /* Get the hardware key cache size. */
995 sc->sc_keymax = ah->ah_caps.keycache_size; 1108 sc->sc_keymax = ah->ah_caps.keycache_size;
996 if (sc->sc_keymax > ATH_KEYMAX) { 1109 if (sc->sc_keymax > ATH_KEYMAX) {
@@ -1098,6 +1211,8 @@ int ath_init(u16 devid, struct ath_softc *sc)
1098 goto bad2; 1211 goto bad2;
1099 } 1212 }
1100 1213
1214 setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc);
1215
1101 sc->sc_rc = ath_rate_attach(ah); 1216 sc->sc_rc = ath_rate_attach(ah);
1102 if (sc->sc_rc == NULL) { 1217 if (sc->sc_rc == NULL) {
1103 error = -EIO; 1218 error = -EIO;