diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2009-01-27 15:06:38 +0530 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-30 13:38:27 -0500 |
commit | 94ff91d4afd8ae14e8bb7012ba17cf6984130e44 (patch) | |
tree | 742360ef9a99a31279dc4ebee525b12bafa72d9c | |
parent | f46730d13f23b4578dca1c0f7663ea3093ff4f0e (diff) |
ath9k: Fix bug in TX DMA termination
Removing the module was slow because ath9k_hw_stopdma()
was looping for a long time quantum. Use reasonable
values now to fix this issue.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath9k/mac.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c index af32d091dc3..ef832a5ebbd 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath9k/mac.c @@ -107,14 +107,32 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel) bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) { +#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ +#define ATH9K_TIME_QUANTUM 100 /* usec */ + + struct ath_hal_5416 *ahp = AH5416(ah); + struct ath9k_hw_capabilities *pCap = &ah->ah_caps; + struct ath9k_tx_queue_info *qi; u32 tsfLow, j, wait; + u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; + + if (q >= pCap->total_queues) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); + return false; + } + + qi = &ahp->ah_txq[q]; + if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { + DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); + return false; + } REG_WRITE(ah, AR_Q_TXD, 1 << q); - for (wait = 1000; wait != 0; wait--) { + for (wait = wait_time; wait != 0; wait--) { if (ath9k_hw_numtxpending(ah, q) == 0) break; - udelay(100); + udelay(ATH9K_TIME_QUANTUM); } if (ath9k_hw_numtxpending(ah, q)) { @@ -144,8 +162,7 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) udelay(200); REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); - wait = 1000; - + wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { DPRINTF(ah->ah_sc, ATH_DBG_XMIT, @@ -153,15 +170,17 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) "msec after killing last frame\n"); break; } - udelay(100); + udelay(ATH9K_TIME_QUANTUM); } REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); } REG_WRITE(ah, AR_Q_TXD, 0); - return wait != 0; + +#undef ATH9K_TX_STOP_DMA_TIMEOUT +#undef ATH9K_TIME_QUANTUM } bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, |