diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 91af57c48581..20c70ba45753 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -611,14 +611,12 @@ void ath9k_tasklet(unsigned long data) | |||
611 | u32 status = sc->intrstatus; | 611 | u32 status = sc->intrstatus; |
612 | u32 rxmask; | 612 | u32 rxmask; |
613 | 613 | ||
614 | ath9k_ps_wakeup(sc); | ||
615 | |||
616 | if (status & ATH9K_INT_FATAL) { | 614 | if (status & ATH9K_INT_FATAL) { |
617 | ath_reset(sc, true); | 615 | ath_reset(sc, true); |
618 | ath9k_ps_restore(sc); | ||
619 | return; | 616 | return; |
620 | } | 617 | } |
621 | 618 | ||
619 | ath9k_ps_wakeup(sc); | ||
622 | spin_lock(&sc->sc_pcu_lock); | 620 | spin_lock(&sc->sc_pcu_lock); |
623 | 621 | ||
624 | /* | 622 | /* |
@@ -939,8 +937,6 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
939 | 937 | ||
940 | spin_unlock_bh(&sc->sc_pcu_lock); | 938 | spin_unlock_bh(&sc->sc_pcu_lock); |
941 | ath9k_ps_restore(sc); | 939 | ath9k_ps_restore(sc); |
942 | |||
943 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); | ||
944 | } | 940 | } |
945 | 941 | ||
946 | int ath_reset(struct ath_softc *sc, bool retry_tx) | 942 | int ath_reset(struct ath_softc *sc, bool retry_tx) |
@@ -953,6 +949,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
953 | /* Stop ANI */ | 949 | /* Stop ANI */ |
954 | del_timer_sync(&common->ani.timer); | 950 | del_timer_sync(&common->ani.timer); |
955 | 951 | ||
952 | ath9k_ps_wakeup(sc); | ||
956 | spin_lock_bh(&sc->sc_pcu_lock); | 953 | spin_lock_bh(&sc->sc_pcu_lock); |
957 | 954 | ||
958 | ieee80211_stop_queues(hw); | 955 | ieee80211_stop_queues(hw); |
@@ -999,6 +996,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
999 | 996 | ||
1000 | /* Start ANI */ | 997 | /* Start ANI */ |
1001 | ath_start_ani(common); | 998 | ath_start_ani(common); |
999 | ath9k_ps_restore(sc); | ||
1002 | 1000 | ||
1003 | return r; | 1001 | return r; |
1004 | } | 1002 | } |
@@ -1220,6 +1218,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1220 | 1218 | ||
1221 | spin_lock_bh(&sc->sc_pcu_lock); | 1219 | spin_lock_bh(&sc->sc_pcu_lock); |
1222 | 1220 | ||
1221 | /* prevent tasklets to enable interrupts once we disable them */ | ||
1222 | ah->imask &= ~ATH9K_INT_GLOBAL; | ||
1223 | |||
1223 | /* make sure h/w will not generate any interrupt | 1224 | /* make sure h/w will not generate any interrupt |
1224 | * before setting the invalid flag. */ | 1225 | * before setting the invalid flag. */ |
1225 | ath9k_hw_disable_interrupts(ah); | 1226 | ath9k_hw_disable_interrupts(ah); |
@@ -1242,6 +1243,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1242 | 1243 | ||
1243 | spin_unlock_bh(&sc->sc_pcu_lock); | 1244 | spin_unlock_bh(&sc->sc_pcu_lock); |
1244 | 1245 | ||
1246 | /* we can now sync irq and kill any running tasklets, since we already | ||
1247 | * disabled interrupts and not holding a spin lock */ | ||
1248 | synchronize_irq(sc->irq); | ||
1249 | tasklet_kill(&sc->intr_tq); | ||
1250 | tasklet_kill(&sc->bcon_tasklet); | ||
1251 | |||
1245 | ath9k_ps_restore(sc); | 1252 | ath9k_ps_restore(sc); |
1246 | 1253 | ||
1247 | sc->ps_idle = true; | 1254 | sc->ps_idle = true; |
@@ -1706,7 +1713,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1706 | 1713 | ||
1707 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1714 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1708 | sc->config.txpowlimit = 2 * conf->power_level; | 1715 | sc->config.txpowlimit = 2 * conf->power_level; |
1716 | ath9k_ps_wakeup(sc); | ||
1709 | ath_update_txpow(sc); | 1717 | ath_update_txpow(sc); |
1718 | ath9k_ps_restore(sc); | ||
1710 | } | 1719 | } |
1711 | 1720 | ||
1712 | if (disable_radio) { | 1721 | if (disable_radio) { |