ath9k: Process GTT interrupts
Global Transmission Timeout interrupts are generated by
the HW when transmission of a frame fails - this is done
based on the threshold programmed in the AR_GTXTO register.
Currently, even though the interrupt is enabled for all chips,
it is not handled in the driver. This patch handles GTT events
for AR9003 and above chips, checking if the MAC/BB has hung
after successive GTT interrupts crosses a threshold (5).
This can be enabled for the older chips in the AR9002 family once
appropriate HW hang checks are implemented for them.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index ca8aff1..73a3655 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -258,6 +258,7 @@
}
}
+ sc->gtt_cnt = 0;
ieee80211_wake_queues(sc->hw);
return true;
@@ -476,6 +477,19 @@
}
}
+ if (status & ATH9K_INT_GTT) {
+ sc->gtt_cnt++;
+
+ if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) {
+ type = RESET_TYPE_TX_GTT;
+ ath9k_queue_reset(sc, type);
+ atomic_inc(&ah->intr_ref_cnt);
+ ath_dbg(common, ANY,
+ "GTT: Skipping interrupts\n");
+ goto out;
+ }
+ }
+
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
/*
@@ -503,10 +517,19 @@
}
if (status & ATH9K_INT_TX) {
- if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ /*
+ * For EDMA chips, TX completion is enabled for the
+ * beacon queue, so if a beacon has been transmitted
+ * successfully after a GTT interrupt, the GTT counter
+ * gets reset to zero here.
+ */
+ /* sc->gtt_cnt = 0; */
+
ath_tx_edma_tasklet(sc);
- else
+ } else {
ath_tx_tasklet(sc);
+ }
wake_up(&sc->tx_wait);
}
@@ -536,6 +559,7 @@
ATH9K_INT_TX | \
ATH9K_INT_BMISS | \
ATH9K_INT_CST | \
+ ATH9K_INT_GTT | \
ATH9K_INT_TSFOOR | \
ATH9K_INT_GENTIMER | \
ATH9K_INT_MCI)
@@ -608,7 +632,6 @@
}
#endif
-
if (status & ATH9K_INT_SWBA)
tasklet_schedule(&sc->bcon_tasklet);
@@ -733,7 +756,12 @@
if (ah->config.hw_hang_checks & HW_BB_WATCHDOG)
ah->imask |= ATH9K_INT_BB_WATCHDOG;
- ah->imask |= ATH9K_INT_GTT;
+ /*
+ * Enable GTT interrupts only for AR9003/AR9004 chips
+ * for now.
+ */
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ah->imask |= ATH9K_INT_GTT;
if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
ah->imask |= ATH9K_INT_CST;