ath9k: check for specific rx stuck conditions and recover from them
authorFelix Fietkau <nbd@openwrt.org>
Mon, 19 Apr 2010 17:57:29 +0000 (19:57 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 20 Apr 2010 15:50:52 +0000 (11:50 -0400)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/main.c

index 0b85f68d516f8cd41529a242a845261169e71b3d..11e6a897c21a54b3624148af5be9e3f86268a10d 100644 (file)
@@ -1159,6 +1159,34 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
        return true;
 }
 
+bool ath9k_hw_check_alive(struct ath_hw *ah)
+{
+       int count = 50;
+       u32 reg;
+
+       if (AR_SREV_9285_10_OR_LATER(ah))
+               return true;
+
+       do {
+               reg = REG_READ(ah, AR_OBS_BUS_1);
+
+               if ((reg & 0x7E7FFFEF) == 0x00702400)
+                       continue;
+
+               switch (reg & 0x7E000B00) {
+               case 0x1E000000:
+               case 0x52000B00:
+               case 0x18000B00:
+                       continue;
+               default:
+                       return true;
+               }
+       } while (count-- > 0);
+
+       return false;
+}
+EXPORT_SYMBOL(ath9k_hw_check_alive);
+
 int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                    bool bChannelChange)
 {
index 8158e8e6a53ddede80fa1bb9562fe0869a96e6c4..a78e09bab431225bd438db738d95dc34e979a8e1 100644 (file)
@@ -869,6 +869,7 @@ void ath9k_hw_set11nmac2040(struct ath_hw *ah);
 void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
 void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
                                    const struct ath9k_beacon_state *bs);
+bool ath9k_hw_check_alive(struct ath_hw *ah);
 
 bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
 
index 40136cf63fa48342a7e08541434726561f1ebc9d..aad370a7f95b782049fc11b05277c48538ea0944 100644 (file)
@@ -405,7 +405,8 @@ void ath9k_tasklet(unsigned long data)
 
        ath9k_ps_wakeup(sc);
 
-       if (status & ATH9K_INT_FATAL) {
+       if ((status & ATH9K_INT_FATAL) ||
+           !ath9k_hw_check_alive(ah)) {
                ath_reset(sc, false);
                ath9k_ps_restore(sc);
                return;