aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c71
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h2
3 files changed, 12 insertions, 74 deletions
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index a4bdfdb043ef..6d2a545fc35e 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -373,6 +373,7 @@ void ath_beacon_tasklet(unsigned long data)
373 ath_dbg(common, ATH_DBG_BSTUCK, 373 ath_dbg(common, ATH_DBG_BSTUCK,
374 "missed %u consecutive beacons\n", 374 "missed %u consecutive beacons\n",
375 sc->beacon.bmisscnt); 375 sc->beacon.bmisscnt);
376 ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
376 ath9k_hw_bstuck_nfcal(ah); 377 ath9k_hw_bstuck_nfcal(ah);
377 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { 378 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
378 ath_dbg(common, ATH_DBG_BSTUCK, 379 ath_dbg(common, ATH_DBG_BSTUCK,
@@ -450,16 +451,6 @@ void ath_beacon_tasklet(unsigned long data)
450 sc->beacon.updateslot = OK; 451 sc->beacon.updateslot = OK;
451 } 452 }
452 if (bfaddr != 0) { 453 if (bfaddr != 0) {
453 /*
454 * Stop any current dma and put the new frame(s) on the queue.
455 * This should never fail since we check above that no frames
456 * are still pending on the queue.
457 */
458 if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
459 ath_err(common, "beacon queue %u did not stop?\n",
460 sc->beacon.beaconq);
461 }
462
463 /* NB: cabq traffic should already be queued and primed */ 454 /* NB: cabq traffic should already be queued and primed */
464 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); 455 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
465 ath9k_hw_txstart(ah, sc->beacon.beaconq); 456 ath9k_hw_txstart(ah, sc->beacon.beaconq);
@@ -780,7 +771,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
780 ah->imask &= ~ATH9K_INT_SWBA; 771 ah->imask &= ~ATH9K_INT_SWBA;
781 ath9k_hw_set_interrupts(ah, ah->imask); 772 ath9k_hw_set_interrupts(ah, ah->imask);
782 tasklet_kill(&sc->bcon_tasklet); 773 tasklet_kill(&sc->bcon_tasklet);
783 ath9k_hw_stoptxdma(ah, sc->beacon.beaconq); 774 ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
784 } 775 }
785 ath9k_ps_restore(sc); 776 ath9k_ps_restore(sc);
786} 777}
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 58aaf9ab0920..cb5d81426d57 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{
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index d37c6d413be1..b2b2ff852c32 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -676,7 +676,7 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
676void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); 676void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
677u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); 677u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
678bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); 678bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
679bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); 679bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
680void ath9k_hw_abort_tx_dma(struct ath_hw *ah); 680void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
681void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); 681void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
682bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, 682bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,