aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-04-19 13:57:29 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-20 11:50:52 -0400
commitc9c99e5e440013c420fd8ec41ee83e89909d5186 (patch)
tree99bc6b0e758937c899d0ef4b28b6a30385d21139 /drivers/net/wireless
parent80725f454e58937ad546103e6a141c46b0d65a1b (diff)
ath9k: check for specific rx stuck conditions and recover from them
Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c28
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c3
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
1162bool 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}
1188EXPORT_SYMBOL(ath9k_hw_check_alive);
1189
1162int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, 1190int 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);
869void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); 869void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
870void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, 870void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
871 const struct ath9k_beacon_state *bs); 871 const struct ath9k_beacon_state *bs);
872bool ath9k_hw_check_alive(struct ath_hw *ah);
872 873
873bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); 874bool 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;