ath9k: Handle abnormal NAV in AP mode

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>
This commit is contained in:
Sujith Manoharan 2013-09-11 21:30:27 +05:30 committed by John W. Linville
parent 9ef4893234
commit 1e516ca7c9
3 changed files with 16 additions and 0 deletions

View File

@ -334,6 +334,8 @@ void ath9k_beacon_tasklet(unsigned long data)
if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
sc->beacon.bmisscnt++; sc->beacon.bmisscnt++;
ath9k_hw_check_nav(ah);
if (!ath9k_hw_check_alive(ah)) if (!ath9k_hw_check_alive(ah))
ieee80211_queue_work(sc->hw, &sc->hw_check_work); ieee80211_queue_work(sc->hw, &sc->hw_check_work);

View File

@ -1656,6 +1656,19 @@ static bool ath9k_hw_detect_mac_hang(struct ath_hw *ah)
return true; 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) bool ath9k_hw_check_alive(struct ath_hw *ah)
{ {
int count = 50; int count = 50;

View 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_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
const struct ath9k_beacon_state *bs); 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_check_alive(struct ath_hw *ah);
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);