ath9k: fix power consumption on network sleep when BTCOEX is enabled
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>
Sun, 1 Jul 2012 14:23:54 +0000 (19:53 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 9 Jul 2012 20:36:20 +0000 (16:36 -0400)
The chip is waken up for every 45ms in btcoex timer cycle to
for sharing the radio between BT and WLAN. Whenever the wlan
interface is in network sleep mode, do not schedule hw timers.
This could reduce power consumption on idle associated state.

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/gpio.c
drivers/net/wireless/ath/ath9k/main.c

index fe39eb4..79840d6 100644 (file)
@@ -481,6 +481,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc);
 void ath9k_btcoex_timer_pause(struct ath_softc *sc);
 void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
 u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
+void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
 #else
 static inline int ath9k_init_btcoex(struct ath_softc *sc)
 {
@@ -504,6 +505,9 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc,
 {
        return 0;
 }
+static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
+{
+}
 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
 
 /********************/
index 5eac4d1..f23af02 100644 (file)
@@ -194,6 +194,14 @@ static void ath_btcoex_period_timer(unsigned long data)
        struct ath_mci_profile *mci = &btcoex->mci;
        u32 timer_period;
        bool is_btscan;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
+               spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+               goto skip_hw_wakeup;
+       }
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
        ath9k_ps_wakeup(sc);
        if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
@@ -232,6 +240,7 @@ static void ath_btcoex_period_timer(unsigned long data)
        }
 
        ath9k_ps_restore(sc);
+skip_hw_wakeup:
        timer_period = btcoex->btcoex_period;
        mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
 }
@@ -328,6 +337,13 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc)
        btcoex->hw_timer_enabled = false;
 }
 
+void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
+{
+       struct ath_btcoex *btcoex = &sc->btcoex;
+
+       ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+}
+
 u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
 {
        struct ath_btcoex *btcoex = &sc->btcoex;
index 6ce0128..06a3d1c 100644 (file)
@@ -130,6 +130,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
                                     PS_WAIT_FOR_PSPOLL_DATA |
                                     PS_WAIT_FOR_TX_ACK))) {
                mode = ATH9K_PM_NETWORK_SLEEP;
+               if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
+                       ath9k_btcoex_stop_gen_timer(sc);
        } else {
                goto unlock;
        }