From: Bruno Randolf <b...@einfach.org>

---
 drivers/net/wireless/ath/ath5k/ath5k.h |    2 ++
 drivers/net/wireless/ath/ath5k/base.c  |   29 ++++++++++++++++++++++++-----
 drivers/net/wireless/ath/ath5k/base.h  |    1 +
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h 
b/drivers/net/wireless/ath/ath5k/ath5k.h
index 8b5383e..d28b748 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -917,6 +917,7 @@ enum ath5k_int {
 enum ath5k_calibration_mask {
        AR5K_FULL_CALIBRATION = 0x01,
        AR5K_SHORT_CALIBRATION = 0x02,
+       AR5K_ANI_CALIBRATION = 0x04,
 };
 
 /*
@@ -1139,6 +1140,7 @@ struct ath5k_hw {
 
        /* Calibration timestamp */
        unsigned long           ah_cal_next_full;
+       unsigned long           ah_cal_next_ani;
 
        /* Calibration mask */
        u8                      ah_cal_mask;
diff --git a/drivers/net/wireless/ath/ath5k/base.c 
b/drivers/net/wireless/ath/ath5k/base.c
index 32aebb6..2ffab83 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -364,6 +364,7 @@ static void         ath5k_beacon_send(struct ath5k_softc 
*sc);
 static void    ath5k_beacon_config(struct ath5k_softc *sc);
 static void    ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
 static void    ath5k_tasklet_beacon(unsigned long data);
+static void    ath5k_tasklet_ani(unsigned long data);
 
 static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
 {
@@ -829,6 +830,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
        tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
        tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
        tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
+       tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc);
 
        ret = ath5k_eeprom_read_mac(ah, mac);
        if (ret) {
@@ -2634,6 +2636,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
        tasklet_kill(&sc->restq);
        tasklet_kill(&sc->calib);
        tasklet_kill(&sc->beacontq);
+       tasklet_kill(&sc->ani_tasklet);
 
        ath5k_rfkill_hw_stop(sc->ah);
 
@@ -2643,10 +2646,16 @@ ath5k_stop_hw(struct ath5k_softc *sc)
 static void
 ath5k_intr_calibration_poll(struct ath5k_hw *ah)
 {
-       if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
+       if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) &&
+           !(ah->ah_cal_mask & AR5K_FULL_CALIBRATION)) {
+               /* run ANI only when full calibration is not active */
+               ah->ah_cal_next_ani = jiffies +
+                       msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI);
+               tasklet_schedule(&ah->ah_sc->ani_tasklet);
+       }
+       else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) {
                ah->ah_cal_next_full = jiffies +
                        msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL);
-               ah->ah_cal_mask = AR5K_FULL_CALIBRATION;
                tasklet_schedule(&ah->ah_sc->calib);
        }
        /* we could use SWI to generate enough interrupts to meet our
@@ -2746,8 +2755,7 @@ ath5k_tasklet_calibrate(unsigned long data)
        struct ath5k_hw *ah = sc->ah;
 
        /* Only full calibration for now */
-       if (ah->ah_cal_mask != AR5K_FULL_CALIBRATION)
-               return;
+       ah->ah_cal_mask |= AR5K_FULL_CALIBRATION;
 
        /* Stop queues so that calibration
         * doesn't interfere with tx */
@@ -2770,11 +2778,22 @@ ath5k_tasklet_calibrate(unsigned long data)
                        ieee80211_frequency_to_channel(
                                sc->curchan->center_freq));
 
-       ah->ah_cal_mask = 0;
+       ah->ah_cal_mask &= ~AR5K_FULL_CALIBRATION;
 
        /* Wake queues */
        ieee80211_wake_queues(sc->hw);
+}
+
+
+static void
+ath5k_tasklet_ani(unsigned long data)
+{
+       struct ath5k_softc *sc = (void *)data;
+       struct ath5k_hw *ah = sc->ah;
 
+       ah->ah_cal_mask |= AR5K_ANI_CALIBRATION;
+       ath5k_ani_periodic_calibration(ah);
+       ah->ah_cal_mask &= ~AR5K_ANI_CALIBRATION;
 }
 
 
diff --git a/drivers/net/wireless/ath/ath5k/base.h 
b/drivers/net/wireless/ath/ath5k/base.h
index 9174523..49e8a56 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -232,6 +232,7 @@ struct ath5k_softc {
        bool                    enable_beacon;  /* true if beacons are on */
 
        struct ath5k_statistics stats;
+       struct tasklet_struct   ani_tasklet;    /* ANI calibration */
 };
 
 #define ath5k_hw_hasbssidmask(_ah) \

_______________________________________________
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel

Reply via email to