From: Rajkumar Manoharan Date: Sun, 1 Jul 2012 14:23:54 +0000 (+0530) Subject: ath9k: fix power consumption on network sleep when BTCOEX is enabled X-Git-Tag: v3.6-rc1~125^2~57^2~186 X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=08d4df410a9ff02c999e69268ec2f4fbfeaac8d7;p=~emulex%2Finfiniband.git ath9k: fix power consumption on network sleep when BTCOEX is enabled 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 Signed-off-by: John W. Linville --- diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index fe39eb4c42a..79840d6deef 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -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 */ /********************/ diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 5eac4d16865..f23af023f3c 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6ce012815ba..06a3d1c7f2b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -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; }