aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/mac.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c71
1 files changed, 9 insertions, 62 deletions
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 58aaf9ab092..cb5d81426d5 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -171,84 +171,31 @@ void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
171} 171}
172EXPORT_SYMBOL(ath9k_hw_abort_tx_dma); 172EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
173 173
174bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) 174bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
175{ 175{
176#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ 176#define ATH9K_TX_STOP_DMA_TIMEOUT 1000 /* usec */
177#define ATH9K_TIME_QUANTUM 100 /* usec */ 177#define ATH9K_TIME_QUANTUM 100 /* usec */
178 struct ath_common *common = ath9k_hw_common(ah); 178 int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
179 struct ath9k_hw_capabilities *pCap = &ah->caps; 179 int wait;
180 struct ath9k_tx_queue_info *qi;
181 u32 tsfLow, j, wait;
182 u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
183
184 if (q >= pCap->total_queues) {
185 ath_dbg(common, ATH_DBG_QUEUE,
186 "Stopping TX DMA, invalid queue: %u\n", q);
187 return false;
188 }
189
190 qi = &ah->txq[q];
191 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
192 ath_dbg(common, ATH_DBG_QUEUE,
193 "Stopping TX DMA, inactive queue: %u\n", q);
194 return false;
195 }
196 180
197 REG_WRITE(ah, AR_Q_TXD, 1 << q); 181 REG_WRITE(ah, AR_Q_TXD, 1 << q);
198 182
199 for (wait = wait_time; wait != 0; wait--) { 183 for (wait = wait_time; wait != 0; wait--) {
200 if (ath9k_hw_numtxpending(ah, q) == 0) 184 if (wait != wait_time)
201 break;
202 udelay(ATH9K_TIME_QUANTUM);
203 }
204
205 if (ath9k_hw_numtxpending(ah, q)) {
206 ath_dbg(common, ATH_DBG_QUEUE,
207 "%s: Num of pending TX Frames %d on Q %d\n",
208 __func__, ath9k_hw_numtxpending(ah, q), q);
209
210 for (j = 0; j < 2; j++) {
211 tsfLow = REG_READ(ah, AR_TSF_L32);
212 REG_WRITE(ah, AR_QUIET2,
213 SM(10, AR_QUIET2_QUIET_DUR));
214 REG_WRITE(ah, AR_QUIET_PERIOD, 100);
215 REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
216 REG_SET_BIT(ah, AR_TIMER_MODE,
217 AR_QUIET_TIMER_EN);
218
219 if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
220 break;
221
222 ath_dbg(common, ATH_DBG_QUEUE,
223 "TSF has moved while trying to set quiet time TSF: 0x%08x\n",
224 tsfLow);
225 }
226
227 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
228
229 udelay(200);
230 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
231
232 wait = wait_time;
233 while (ath9k_hw_numtxpending(ah, q)) {
234 if ((--wait) == 0) {
235 ath_err(common,
236 "Failed to stop TX DMA in 100 msec after killing last frame\n");
237 break;
238 }
239 udelay(ATH9K_TIME_QUANTUM); 185 udelay(ATH9K_TIME_QUANTUM);
240 }
241 186
242 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); 187 if (ath9k_hw_numtxpending(ah, q) == 0)
188 break;
243 } 189 }
244 190
245 REG_WRITE(ah, AR_Q_TXD, 0); 191 REG_WRITE(ah, AR_Q_TXD, 0);
192
246 return wait != 0; 193 return wait != 0;
247 194
248#undef ATH9K_TX_STOP_DMA_TIMEOUT 195#undef ATH9K_TX_STOP_DMA_TIMEOUT
249#undef ATH9K_TIME_QUANTUM 196#undef ATH9K_TIME_QUANTUM
250} 197}
251EXPORT_SYMBOL(ath9k_hw_stoptxdma); 198EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
252 199
253void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) 200void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
254{ 201{