aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c36
3 files changed, 35 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index cba7d772f7f3..b5ac32cfbeb8 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -691,6 +691,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
#define DEFAULT_CACHELINE 32
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
+#define MAX_GTT_CNT 5
enum sc_op_flags {
SC_OP_INVALID,
@@ -733,6 +734,7 @@ struct ath_softc {
unsigned long sc_flags;
unsigned long driver_data;
+ u8 gtt_cnt;
u32 intrstatus;
u16 ps_flags; /* PS_* */
u16 curtxpow;
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index b01b8c3ec570..cc7a025d833e 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -44,6 +44,7 @@ enum ath_reset_type {
RESET_TYPE_BB_WATCHDOG,
RESET_TYPE_FATAL_INT,
RESET_TYPE_TX_ERROR,
+ RESET_TYPE_TX_GTT,
RESET_TYPE_TX_HANG,
RESET_TYPE_PLL_HANG,
RESET_TYPE_MAC_HANG,
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index ca8aff1aec94..73a36551a5ed 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -258,6 +258,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
}
}
+ sc->gtt_cnt = 0;
ieee80211_wake_queues(sc->hw);
return true;
@@ -476,6 +477,19 @@ void ath9k_tasklet(unsigned long data)
}
}
+ 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 @@ void ath9k_tasklet(unsigned long data)
}
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 @@ irqreturn_t ath_isr(int irq, void *dev)
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 @@ irqreturn_t ath_isr(int irq, void *dev)
}
#endif
-
if (status & ATH9K_INT_SWBA)
tasklet_schedule(&sc->bcon_tasklet);
@@ -733,7 +756,12 @@ static int ath9k_start(struct ieee80211_hw *hw)
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;