diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2009-01-27 04:36:38 -0500 |
---|---|---|
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 af32d091dc38..ef832a5ebbd8 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) | |||
107 | 107 | ||
108 | bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) | 108 | bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) |
109 | { | 109 | { |
110 | #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ | ||
111 | #define ATH9K_TIME_QUANTUM 100 /* usec */ | ||
112 | |||
113 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
114 | struct ath9k_hw_capabilities *pCap = &ah->ah_caps; | ||
115 | struct ath9k_tx_queue_info *qi; | ||
110 | u32 tsfLow, j, wait; | 116 | u32 tsfLow, j, wait; |
117 | u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; | ||
118 | |||
119 | if (q >= pCap->total_queues) { | ||
120 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q); | ||
121 | return false; | ||
122 | } | ||
123 | |||
124 | qi = &ahp->ah_txq[q]; | ||
125 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | ||
126 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n"); | ||
127 | return false; | ||
128 | } | ||
111 | 129 | ||
112 | REG_WRITE(ah, AR_Q_TXD, 1 << q); | 130 | REG_WRITE(ah, AR_Q_TXD, 1 << q); |
113 | 131 | ||
114 | for (wait = 1000; wait != 0; wait--) { | 132 | for (wait = wait_time; wait != 0; wait--) { |
115 | if (ath9k_hw_numtxpending(ah, q) == 0) | 133 | if (ath9k_hw_numtxpending(ah, q) == 0) |
116 | break; | 134 | break; |
117 | udelay(100); | 135 | udelay(ATH9K_TIME_QUANTUM); |
118 | } | 136 | } |
119 | 137 | ||
120 | if (ath9k_hw_numtxpending(ah, q)) { | 138 | if (ath9k_hw_numtxpending(ah, q)) { |
@@ -144,8 +162,7 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) | |||
144 | udelay(200); | 162 | udelay(200); |
145 | REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); | 163 | REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); |
146 | 164 | ||
147 | wait = 1000; | 165 | wait = wait_time; |
148 | |||
149 | while (ath9k_hw_numtxpending(ah, q)) { | 166 | while (ath9k_hw_numtxpending(ah, q)) { |
150 | if ((--wait) == 0) { | 167 | if ((--wait) == 0) { |
151 | DPRINTF(ah->ah_sc, ATH_DBG_XMIT, | 168 | DPRINTF(ah->ah_sc, ATH_DBG_XMIT, |
@@ -153,15 +170,17 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q) | |||
153 | "msec after killing last frame\n"); | 170 | "msec after killing last frame\n"); |
154 | break; | 171 | break; |
155 | } | 172 | } |
156 | udelay(100); | 173 | udelay(ATH9K_TIME_QUANTUM); |
157 | } | 174 | } |
158 | 175 | ||
159 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | 176 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); |
160 | } | 177 | } |
161 | 178 | ||
162 | REG_WRITE(ah, AR_Q_TXD, 0); | 179 | REG_WRITE(ah, AR_Q_TXD, 0); |
163 | |||
164 | return wait != 0; | 180 | return wait != 0; |
181 | |||
182 | #undef ATH9K_TX_STOP_DMA_TIMEOUT | ||
183 | #undef ATH9K_TIME_QUANTUM | ||
165 | } | 184 | } |
166 | 185 | ||
167 | bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, | 186 | bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds, |