aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-11-16 07:08:40 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-12-07 15:14:03 -0500
commitc8e8868e3bf2ee0b6e606ce43af023b5f6edc954 (patch)
tree178f42ba7d28b293c97779e1602e2fe08e59efab /drivers/net/wireless/ath/ath9k/main.c
parent4e79fada02df6819106a35ed6111ac47500541b2 (diff)
ath9k: always issue a full hw reset after waking up from full-sleep mode
After waking up from full sleep, registers are accessible, but rx/tx typically fails. A fast channel change will not recover from this, so ensure that a full-sleep -> wake transition is always followed by a full reset. The reason why this hasn't created any serious problems yet is that it's hidden by the (wrong) behavior of enabling/disabling the radio when the wiphy idle state changes. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index fd59c1f25c43..3733828e72bc 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *sc)
118 if (--sc->ps_usecount != 0) 118 if (--sc->ps_usecount != 0)
119 goto unlock; 119 goto unlock;
120 120
121 if (sc->ps_idle) 121 if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
122 mode = ATH9K_PM_FULL_SLEEP; 122 mode = ATH9K_PM_FULL_SLEEP;
123 else if (sc->ps_enabled && 123 else if (sc->ps_enabled &&
124 !(sc->ps_flags & (PS_WAIT_FOR_BEACON | 124 !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
@@ -332,7 +332,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
332 hchan = ah->curchan; 332 hchan = ah->curchan;
333 } 333 }
334 334
335 if (fastcc && !ath9k_hw_check_alive(ah)) 335 if (fastcc && (ah->chip_fullsleep ||
336 !ath9k_hw_check_alive(ah)))
336 fastcc = false; 337 fastcc = false;
337 338
338 if (!ath_prepare_reset(sc, retry_tx, flush)) 339 if (!ath_prepare_reset(sc, retry_tx, flush))
@@ -1183,6 +1184,13 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1183 } 1184 }
1184 } 1185 }
1185 1186
1187 /*
1188 * Cannot tx while the hardware is in full sleep, it first needs a full
1189 * chip reset to recover from that
1190 */
1191 if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP))
1192 goto exit;
1193
1186 if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) { 1194 if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
1187 /* 1195 /*
1188 * We are using PS-Poll and mac80211 can request TX while in 1196 * We are using PS-Poll and mac80211 can request TX while in