ath9k: Handle full sleep in ps_restore.
authorVivek Natarajan <vnatarajan@atheros.com>
Fri, 29 Jan 2010 11:26:51 +0000 (16:56 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 29 Jan 2010 15:43:37 +0000 (10:43 -0500)
IDLE PS (Full Sleep) doesn't work when ifconfig up
is done during Idle unassociated state.
Fix this by restoring FULL SLEEP in ps_restore if CONF_IDLE
is set.

Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/main.c

index bdbcc70df07549410cfad83203cfb9f24edf41a7..3f8a7e773d559d79e29a31915be9ef98e9f7d4f2 100644 (file)
@@ -480,6 +480,7 @@ struct ath_softc {
        u8 nbcnvifs;
        u16 nvifs;
        bool ps_enabled;
+       bool ps_idle;
        unsigned long ps_usecount;
        enum ath9k_int imask;
 
index 6f3e71c5071e865cdef63e08705be6e896e3a933..e04835cb21b540f4faedf9ff495e4d5ca39fa6da 100644 (file)
@@ -143,8 +143,10 @@ void ath9k_ps_restore(struct ath_softc *sc)
        if (--sc->ps_usecount != 0)
                goto unlock;
 
-       if (sc->ps_enabled &&
-           !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
+       if (sc->ps_idle)
+               ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+       else if (sc->ps_enabled &&
+                !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
                              PS_WAIT_FOR_CAB |
                              PS_WAIT_FOR_PSPOLL_DATA |
                              PS_WAIT_FOR_TX_ACK)))
@@ -1528,6 +1530,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
                spin_unlock_bh(&sc->wiphy_lock);
 
                if (enable_radio) {
+                       sc->ps_idle = false;
                        ath_radio_enable(sc, hw);
                        ath_print(common, ATH_DBG_CONFIG,
                                  "not-idle: enabling radio\n");
@@ -1635,6 +1638,7 @@ skip_chan_change:
 
        if (disable_radio) {
                ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
+               sc->ps_idle = true;
                ath_radio_disable(sc, hw);
        }