summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k/beacon.c
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>2011-06-23 13:39:13 +0530
committerJohn W. Linville <linville@tuxdriver.com>2011-06-27 15:09:40 -0400
commitdcfcbd590d91e8385eb554aaed419bdebaf4c72a (patch)
tree3ea376c7c1c866e6c8da62d11ff0a072a74340ec /drivers/net/wireless/ath/ath9k/beacon.c
parent15b4d843ab66bc0ac2cd46baa20a3ce9638604e6 (diff)
ath9k_hw: Fix false tx hung detection in AR9003 chips
The edma based (AR9003 family) chips update tx status descriptors in a common ring buffer for all transmitted frames. Whenever tx interrupt is raised, the descriptors are processed and tx status index is moved. The complete tx stauts ring are updated with beacons tx status when there are no data frames to be sent for a period of time. In this state, transmitting data frames causes the driver to wait for the tx status on an incorrect tx status index though the status was updated by hw properly. The driver detects this condition as a h/w hang and does unnecessary chip resets. This issue was orginally reported in adhoc mode while sending frames after an idle time. Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/beacon.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 0174cdb65a83..0b6e3b65bb0b 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -360,6 +360,7 @@ void ath_beacon_tasklet(unsigned long data)
struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf = NULL;
struct ieee80211_vif *vif;
+ struct ath_tx_status ts;
int slot;
u32 bfaddr, bc = 0;
@@ -464,6 +465,11 @@ void ath_beacon_tasklet(unsigned long data)
ath9k_hw_txstart(ah, sc->beacon.beaconq);
sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ spin_lock_bh(&sc->sc_pcu_lock);
+ ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+ }
}
}