aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/dma.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/dma.c180
1 files changed, 168 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 923c9ca5c4f0..82541fec9f0e 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -37,6 +37,7 @@
37#include "debug.h" 37#include "debug.h"
38#include "base.h" 38#include "base.h"
39 39
40
40/*********\ 41/*********\
41* Receive * 42* Receive *
42\*********/ 43\*********/
@@ -57,7 +58,7 @@ void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
57 * 58 *
58 * @ah: The &struct ath5k_hw 59 * @ah: The &struct ath5k_hw
59 */ 60 */
60int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) 61static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
61{ 62{
62 unsigned int i; 63 unsigned int i;
63 64
@@ -69,7 +70,11 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
69 for (i = 1000; i > 0 && 70 for (i = 1000; i > 0 &&
70 (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; 71 (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
71 i--) 72 i--)
72 udelay(10); 73 udelay(100);
74
75 if (i)
76 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
77 "failed to stop RX DMA !\n");
73 78
74 return i ? 0 : -EBUSY; 79 return i ? 0 : -EBUSY;
75} 80}
@@ -90,11 +95,18 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
90 * @ah: The &struct ath5k_hw 95 * @ah: The &struct ath5k_hw
91 * @phys_addr: RX descriptor address 96 * @phys_addr: RX descriptor address
92 * 97 *
93 * XXX: Should we check if rx is enabled before setting rxdp ? 98 * Returns -EIO if rx is active
94 */ 99 */
95void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) 100int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
96{ 101{
102 if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) {
103 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
104 "tried to set RXDP while rx was active !\n");
105 return -EIO;
106 }
107
97 ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); 108 ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
109 return 0;
98} 110}
99 111
100 112
@@ -125,7 +137,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
125 137
126 /* Return if queue is declared inactive */ 138 /* Return if queue is declared inactive */
127 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) 139 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
128 return -EIO; 140 return -EINVAL;
129 141
130 if (ah->ah_version == AR5K_AR5210) { 142 if (ah->ah_version == AR5K_AR5210) {
131 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); 143 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
@@ -173,10 +185,10 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
173 * 185 *
174 * Stop DMA transmit on a specific hw queue and drain queue so we don't 186 * Stop DMA transmit on a specific hw queue and drain queue so we don't
175 * have any pending frames. Returns -EBUSY if we still have pending frames, 187 * have any pending frames. Returns -EBUSY if we still have pending frames,
176 * -EINVAL if queue number is out of range. 188 * -EINVAL if queue number is out of range or inactive.
177 * 189 *
178 */ 190 */
179int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) 191static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
180{ 192{
181 unsigned int i = 40; 193 unsigned int i = 40;
182 u32 tx_queue, pending; 194 u32 tx_queue, pending;
@@ -185,7 +197,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
185 197
186 /* Return if queue is declared inactive */ 198 /* Return if queue is declared inactive */
187 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) 199 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
188 return -EIO; 200 return -EINVAL;
189 201
190 if (ah->ah_version == AR5K_AR5210) { 202 if (ah->ah_version == AR5K_AR5210) {
191 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); 203 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
@@ -211,12 +223,31 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
211 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); 223 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
212 ath5k_hw_reg_read(ah, AR5K_CR); 224 ath5k_hw_reg_read(ah, AR5K_CR);
213 } else { 225 } else {
226
227 /*
228 * Enable DCU early termination to quickly
229 * flush any pending frames from QCU
230 */
231 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
232 AR5K_QCU_MISC_DCU_EARLY);
233
214 /* 234 /*
215 * Schedule TX disable and wait until queue is empty 235 * Schedule TX disable and wait until queue is empty
216 */ 236 */
217 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); 237 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
218 238
219 /*Check for pending frames*/ 239 /* Wait for queue to stop */
240 for (i = 1000; i > 0 &&
241 (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue) != 0);
242 i--)
243 udelay(100);
244
245 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
246 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
247 "queue %i didn't stop !\n", queue);
248
249 /* Check for pending frames */
250 i = 1000;
220 do { 251 do {
221 pending = ath5k_hw_reg_read(ah, 252 pending = ath5k_hw_reg_read(ah,
222 AR5K_QUEUE_STATUS(queue)) & 253 AR5K_QUEUE_STATUS(queue)) &
@@ -247,12 +278,12 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
247 AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); 278 AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
248 279
249 /* Wait a while and disable mechanism */ 280 /* Wait a while and disable mechanism */
250 udelay(200); 281 udelay(400);
251 AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, 282 AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
252 AR5K_QUIET_CTL1_QT_EN); 283 AR5K_QUIET_CTL1_QT_EN);
253 284
254 /* Re-check for pending frames */ 285 /* Re-check for pending frames */
255 i = 40; 286 i = 100;
256 do { 287 do {
257 pending = ath5k_hw_reg_read(ah, 288 pending = ath5k_hw_reg_read(ah,
258 AR5K_QUEUE_STATUS(queue)) & 289 AR5K_QUEUE_STATUS(queue)) &
@@ -262,12 +293,27 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
262 293
263 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, 294 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
264 AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); 295 AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
296
297 if (pending)
298 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
299 "quiet mechanism didn't work q:%i !\n",
300 queue);
265 } 301 }
266 302
303 /*
304 * Disable DCU early termination
305 */
306 AR5K_REG_DISABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
307 AR5K_QCU_MISC_DCU_EARLY);
308
267 /* Clear register */ 309 /* Clear register */
268 ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); 310 ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
269 if (pending) 311 if (pending) {
312 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
313 "tx dma didn't stop (q:%i, frm:%i) !\n",
314 queue, pending);
270 return -EBUSY; 315 return -EBUSY;
316 }
271 } 317 }
272 318
273 /* TODO: Check for success on 5210 else return error */ 319 /* TODO: Check for success on 5210 else return error */
@@ -275,6 +321,26 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
275} 321}
276 322
277/** 323/**
324 * ath5k_hw_stop_beacon_queue - Stop beacon queue
325 *
326 * @ah The &struct ath5k_hw
327 * @queue The queue number
328 *
329 * Returns -EIO if queue didn't stop
330 */
331int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
332{
333 int ret;
334 ret = ath5k_hw_stop_tx_dma(ah, queue);
335 if (ret) {
336 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
337 "beacon queue didn't stop !\n");
338 return -EIO;
339 }
340 return 0;
341}
342
343/**
278 * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue 344 * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
279 * 345 *
280 * @ah: The &struct ath5k_hw 346 * @ah: The &struct ath5k_hw
@@ -427,6 +493,7 @@ done:
427 return ret; 493 return ret;
428} 494}
429 495
496
430/*******************\ 497/*******************\
431* Interrupt masking * 498* Interrupt masking *
432\*******************/ 499\*******************/
@@ -688,3 +755,92 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
688 return old_mask; 755 return old_mask;
689} 756}
690 757
758
759/********************\
760 Init/Stop functions
761\********************/
762
763/**
764 * ath5k_hw_dma_init - Initialize DMA unit
765 *
766 * @ah: The &struct ath5k_hw
767 *
768 * Set DMA size and pre-enable interrupts
769 * (driver handles tx/rx buffer setup and
770 * dma start/stop)
771 *
772 * XXX: Save/restore RXDP/TXDP registers ?
773 */
774void ath5k_hw_dma_init(struct ath5k_hw *ah)
775{
776 /*
777 * Set Rx/Tx DMA Configuration
778 *
779 * Set standard DMA size (128). Note that
780 * a DMA size of 512 causes rx overruns and tx errors
781 * on pci-e cards (tested on 5424 but since rx overruns
782 * also occur on 5416/5418 with madwifi we set 128
783 * for all PCI-E cards to be safe).
784 *
785 * XXX: need to check 5210 for this
786 * TODO: Check out tx triger level, it's always 64 on dumps but I
787 * guess we can tweak it and see how it goes ;-)
788 */
789 if (ah->ah_version != AR5K_AR5210) {
790 AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
791 AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
792 AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
793 AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
794 }
795
796 /* Pre-enable interrupts on 5211/5212*/
797 if (ah->ah_version != AR5K_AR5210)
798 ath5k_hw_set_imr(ah, ah->ah_imr);
799
800}
801
802/**
803 * ath5k_hw_dma_stop - stop DMA unit
804 *
805 * @ah: The &struct ath5k_hw
806 *
807 * Stop tx/rx DMA and interrupts. Returns
808 * -EBUSY if tx or rx dma failed to stop.
809 *
810 * XXX: Sometimes DMA unit hangs and we have
811 * stuck frames on tx queues, only a reset
812 * can fix that.
813 */
814int ath5k_hw_dma_stop(struct ath5k_hw *ah)
815{
816 int i, qmax, err;
817 err = 0;
818
819 /* Disable interrupts */
820 ath5k_hw_set_imr(ah, 0);
821
822 /* Stop rx dma */
823 err = ath5k_hw_stop_rx_dma(ah);
824 if (err)
825 return err;
826
827 /* Clear any pending interrupts
828 * and disable tx dma */
829 if (ah->ah_version != AR5K_AR5210) {
830 ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
831 qmax = AR5K_NUM_TX_QUEUES;
832 } else {
833 /* PISR/SISR Not available on 5210 */
834 ath5k_hw_reg_read(ah, AR5K_ISR);
835 qmax = AR5K_NUM_TX_QUEUES_NOQCU;
836 }
837
838 for (i = 0; i < qmax; i++) {
839 err = ath5k_hw_stop_tx_dma(ah, i);
840 /* -EINVAL -> queue inactive */
841 if (err != -EINVAL)
842 return err;
843 }
844
845 return err;
846}