ath9k: Handle abnormal NAV in AP mode
authorSujith Manoharan <c_manoha@qca.qualcomm.com>
Wed, 11 Sep 2013 16:00:27 +0000 (21:30 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 26 Sep 2013 19:13:46 +0000 (15:13 -0400)
Beacon transmission would get stuck if the NAV is
an invalid value for some reason. Check and correct
the NAV value in the HW when this happens.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h

index b5c16b3a37b953133038d0450616d3c5b2be16e3..17be35392bb4f5134996a6e14b6bdc2547d40de9 100644 (file)
@@ -334,6 +334,8 @@ void ath9k_beacon_tasklet(unsigned long data)
        if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
                sc->beacon.bmisscnt++;
 
+               ath9k_hw_check_nav(ah);
+
                if (!ath9k_hw_check_alive(ah))
                        ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 
index 525ac984eafd93d0793c0f274c2c66fd1d50c57a..d3206ab4029715967a06f9456b57523ff5b34e67 100644 (file)
@@ -1656,6 +1656,19 @@ hang_check_iter:
        return true;
 }
 
+void ath9k_hw_check_nav(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 val;
+
+       val = REG_READ(ah, AR_NAV);
+       if (val != 0xdeadbeef && val > 0x7fff) {
+               ath_dbg(common, BSTUCK, "Abnormal NAV: 0x%x\n", val);
+               REG_WRITE(ah, AR_NAV, 0);
+       }
+}
+EXPORT_SYMBOL(ath9k_hw_check_nav);
+
 bool ath9k_hw_check_alive(struct ath_hw *ah)
 {
        int count = 50;
index 5e564c7888134d80b6e4af3a6bdc501c49bdced7..5376011d52009306a7d32ee97a0cfd3029e19e02 100644 (file)
@@ -1031,6 +1031,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);
+void ath9k_hw_check_nav(struct ath_hw *ah);
 bool ath9k_hw_check_alive(struct ath_hw *ah);
 
 bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);