diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 71 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.h | 2 |
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 | } |
172 | EXPORT_SYMBOL(ath9k_hw_abort_tx_dma); | 172 | EXPORT_SYMBOL(ath9k_hw_abort_tx_dma); |
173 | 173 | ||
174 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | 174 | bool 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 | } |
251 | EXPORT_SYMBOL(ath9k_hw_stoptxdma); | 198 | EXPORT_SYMBOL(ath9k_hw_stop_dma_queue); |
252 | 199 | ||
253 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) | 200 | void 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); | |||
676 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); | 676 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); |
677 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); | 677 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); |
678 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); | 678 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); |
679 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); | 679 | bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q); |
680 | void ath9k_hw_abort_tx_dma(struct ath_hw *ah); | 680 | void ath9k_hw_abort_tx_dma(struct ath_hw *ah); |
681 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); | 681 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); |
682 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, | 682 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, |