diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 3 |
3 files changed, 31 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 0b85f68d516f..11e6a897c21a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1159,6 +1159,34 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1159 | return true; | 1159 | return true; |
1160 | } | 1160 | } |
1161 | 1161 | ||
1162 | bool ath9k_hw_check_alive(struct ath_hw *ah) | ||
1163 | { | ||
1164 | int count = 50; | ||
1165 | u32 reg; | ||
1166 | |||
1167 | if (AR_SREV_9285_10_OR_LATER(ah)) | ||
1168 | return true; | ||
1169 | |||
1170 | do { | ||
1171 | reg = REG_READ(ah, AR_OBS_BUS_1); | ||
1172 | |||
1173 | if ((reg & 0x7E7FFFEF) == 0x00702400) | ||
1174 | continue; | ||
1175 | |||
1176 | switch (reg & 0x7E000B00) { | ||
1177 | case 0x1E000000: | ||
1178 | case 0x52000B00: | ||
1179 | case 0x18000B00: | ||
1180 | continue; | ||
1181 | default: | ||
1182 | return true; | ||
1183 | } | ||
1184 | } while (count-- > 0); | ||
1185 | |||
1186 | return false; | ||
1187 | } | ||
1188 | EXPORT_SYMBOL(ath9k_hw_check_alive); | ||
1189 | |||
1162 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 1190 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
1163 | bool bChannelChange) | 1191 | bool bChannelChange) |
1164 | { | 1192 | { |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 8158e8e6a53d..a78e09bab431 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -869,6 +869,7 @@ void ath9k_hw_set11nmac2040(struct ath_hw *ah); | |||
869 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 869 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
870 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | 870 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, |
871 | const struct ath9k_beacon_state *bs); | 871 | const struct ath9k_beacon_state *bs); |
872 | bool ath9k_hw_check_alive(struct ath_hw *ah); | ||
872 | 873 | ||
873 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); | 874 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); |
874 | 875 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 40136cf63fa4..aad370a7f95b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -405,7 +405,8 @@ void ath9k_tasklet(unsigned long data) | |||
405 | 405 | ||
406 | ath9k_ps_wakeup(sc); | 406 | ath9k_ps_wakeup(sc); |
407 | 407 | ||
408 | if (status & ATH9K_INT_FATAL) { | 408 | if ((status & ATH9K_INT_FATAL) || |
409 | !ath9k_hw_check_alive(ah)) { | ||
409 | ath_reset(sc, false); | 410 | ath_reset(sc, false); |
410 | ath9k_ps_restore(sc); | 411 | ath9k_ps_restore(sc); |
411 | return; | 412 | return; |