ath9k: perform ANI cycle in idle state
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>
Wed, 10 Oct 2012 17:33:02 +0000 (23:03 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 19 Oct 2012 20:16:14 +0000 (16:16 -0400)
As of now the ANI cycle is executed only when the chip is awake.
On idle state case, the station wakes up from network sleep for
beacon reception. Since most of the time, ANI cycle is not syncing
with beacon wakeup, ANI cycle is ignored. Approx 5 mins once, the
calibration is performed. This could affect the connection stability
when the station is idle for long. Even though the OFDM and CCK phy
error rates are too high, ANI is unable to tune its immunity level
as quick enough due to rare execution.

Here the experiment shows that OFDM and CCK levels are at default
even on higher phy error rate.

listenTime=44 OFDM:3 errs=121977/s CCK:2 errs=440818/s ofdm_turn=1

This change ensures that ANI calibration will be exectued atleast
once for every 10 seconds. The below result shows improvements and
immunity levels are adopted quick enough.

listenTime=557 OFDM:4 errs=752/s CCK:4 errs=125/s ofdm_turn=0

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/link.c
drivers/net/wireless/ath/ath9k/main.c

index dfe6a4707fd22684a5994de3b6c4d9dcadd456f2..77c2c16b69610e6186497a0e2cbfc6fb8ca12aa8 100644 (file)
@@ -437,6 +437,7 @@ void ath9k_set_beacon(struct ath_softc *sc);
 #define ATH_LONG_CALINTERVAL_INT  1000    /* 1000 ms */
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
+#define ATH_ANI_MAX_SKIP_COUNT  10
 
 #define ATH_PAPRD_TIMEOUT      100 /* msecs */
 #define ATH_PLL_WORK_INTERVAL   100
@@ -642,6 +643,7 @@ enum sc_op_flags {
 #define PS_WAIT_FOR_PSPOLL_DATA   BIT(2)
 #define PS_WAIT_FOR_TX_ACK        BIT(3)
 #define PS_BEACON_SYNC            BIT(4)
+#define PS_WAIT_FOR_ANI           BIT(5)
 
 struct ath_rate_table;
 
index dbc1b7a4cbfdc0eeca59efa19f4d52e7e09044ec..1d4f5f1fdd8d78d52038e238dcc3ace6fb3f0390 100644 (file)
@@ -834,6 +834,7 @@ struct ath_hw {
        int coarse_low[5];
        int firpwr[5];
        enum ath9k_ani_cmd ani_function;
+       u32 ani_skip_count;
 
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
        struct ath_btcoex_hw btcoex_hw;
index 7b88b9c39ccddc4ef4e3aeafb53e437d0f35a0ce..223b9693527e0c3da4e4e111d89f4d1c2481fd36 100644 (file)
@@ -350,8 +350,18 @@ void ath_ani_calibrate(unsigned long data)
                ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
 
        /* Only calibrate if awake */
-       if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
+       if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
+               if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) {
+                       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+                       sc->ps_flags |= PS_WAIT_FOR_ANI;
+                       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+               }
                goto set_timer;
+       }
+       ah->ani_skip_count = 0;
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       sc->ps_flags &= ~PS_WAIT_FOR_ANI;
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
        ath9k_ps_wakeup(sc);
 
index dd45edfa6baec25304af0a07ccea22f1c0910f29..2da62be081f7b610a8233d12f54991cfe76a4c11 100644 (file)
@@ -131,7 +131,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
                   !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
                                     PS_WAIT_FOR_CAB |
                                     PS_WAIT_FOR_PSPOLL_DATA |
-                                    PS_WAIT_FOR_TX_ACK))) {
+                                    PS_WAIT_FOR_TX_ACK |
+                                    PS_WAIT_FOR_ANI))) {
                mode = ATH9K_PM_NETWORK_SLEEP;
                if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
                        ath9k_btcoex_stop_gen_timer(sc);