blob: e39c95340841d428097bcba24724c422decfba1b [file] [log] [blame]
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 */
18
19/*************************************\
20* DMA and interrupt masking functions *
21\*************************************/
22
23/*
24 * dma.c - DMA and interrupt masking functions
25 *
26 * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
27 * handle queue setup for 5210 chipset (rest are handled on qcu.c).
28 * Also we setup interrupt mask register (IMR) and read the various iterrupt
29 * status registers (ISR).
30 *
31 * TODO: Handle SISR on 5211+ and introduce a function to return the queue
32 * number that resulted the interrupt.
33 */
34
35#include "ath5k.h"
36#include "reg.h"
37#include "debug.h"
38#include "base.h"
39
Nick Kossifidis9320b5c2010-11-23 20:36:45 +020040
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030041/*********\
42* Receive *
43\*********/
44
45/**
46 * ath5k_hw_start_rx_dma - Start DMA receive
47 *
48 * @ah: The &struct ath5k_hw
49 */
50void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
51{
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030052 ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
53 ath5k_hw_reg_read(ah, AR5K_CR);
54}
55
56/**
57 * ath5k_hw_stop_rx_dma - Stop DMA receive
58 *
59 * @ah: The &struct ath5k_hw
60 */
61int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
62{
63 unsigned int i;
64
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030065 ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
66
67 /*
68 * It may take some time to disable the DMA receive unit
69 */
Nick Kossifidis509a1062008-09-29 01:23:07 +030070 for (i = 1000; i > 0 &&
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030071 (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
72 i--)
Nick Kossifidisb3a28e62010-11-23 20:47:31 +020073 udelay(100);
74
75 if (i)
76 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
77 "failed to stop RX DMA !\n");
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030078
79 return i ? 0 : -EBUSY;
80}
81
82/**
83 * ath5k_hw_get_rxdp - Get RX Descriptor's address
84 *
85 * @ah: The &struct ath5k_hw
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030086 */
87u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
88{
89 return ath5k_hw_reg_read(ah, AR5K_RXDP);
90}
91
92/**
93 * ath5k_hw_set_rxdp - Set RX Descriptor's address
94 *
95 * @ah: The &struct ath5k_hw
96 * @phys_addr: RX descriptor address
97 *
98 * XXX: Should we check if rx is enabled before setting rxdp ?
99 */
100void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
101{
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300102 ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
103}
104
105
106/**********\
107* Transmit *
108\**********/
109
110/**
111 * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
112 *
113 * @ah: The &struct ath5k_hw
114 * @queue: The hw queue number
115 *
116 * Start DMA transmit for a specific queue and since 5210 doesn't have
117 * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
118 * queue for normal data and one queue for beacons). For queue setup
119 * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
120 * of range or if queue is already disabled.
121 *
122 * NOTE: Must be called after setting up tx control descriptor for that
123 * queue (see below).
124 */
125int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
126{
127 u32 tx_queue;
128
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300129 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
130
131 /* Return if queue is declared inactive */
132 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
Nick Kossifidisd41174f2010-11-23 20:41:15 +0200133 return -EINVAL;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300134
135 if (ah->ah_version == AR5K_AR5210) {
136 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
137
138 /*
139 * Set the queue by type on 5210
140 */
141 switch (ah->ah_txq[queue].tqi_type) {
142 case AR5K_TX_QUEUE_DATA:
143 tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
144 break;
145 case AR5K_TX_QUEUE_BEACON:
146 tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
147 ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
148 AR5K_BSR);
149 break;
150 case AR5K_TX_QUEUE_CAB:
151 tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
152 ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V |
153 AR5K_BCR_BDMAE, AR5K_BSR);
154 break;
155 default:
156 return -EINVAL;
157 }
158 /* Start queue */
159 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
160 ath5k_hw_reg_read(ah, AR5K_CR);
161 } else {
162 /* Return if queue is disabled */
163 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
164 return -EIO;
165
166 /* Start queue */
167 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
168 }
169
170 return 0;
171}
172
173/**
174 * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
175 *
176 * @ah: The &struct ath5k_hw
177 * @queue: The hw queue number
178 *
179 * Stop DMA transmit on a specific hw queue and drain queue so we don't
180 * have any pending frames. Returns -EBUSY if we still have pending frames,
Nick Kossifidisd41174f2010-11-23 20:41:15 +0200181 * -EINVAL if queue number is out of range or inactive.
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300182 *
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300183 */
184int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
185{
Nick Kossifidis509a1062008-09-29 01:23:07 +0300186 unsigned int i = 40;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300187 u32 tx_queue, pending;
188
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300189 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
190
191 /* Return if queue is declared inactive */
192 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
Nick Kossifidisd41174f2010-11-23 20:41:15 +0200193 return -EINVAL;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300194
195 if (ah->ah_version == AR5K_AR5210) {
196 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
197
198 /*
199 * Set by queue type
200 */
201 switch (ah->ah_txq[queue].tqi_type) {
202 case AR5K_TX_QUEUE_DATA:
203 tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
204 break;
205 case AR5K_TX_QUEUE_BEACON:
206 case AR5K_TX_QUEUE_CAB:
207 /* XXX Fix me... */
208 tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
209 ath5k_hw_reg_write(ah, 0, AR5K_BSR);
210 break;
211 default:
212 return -EINVAL;
213 }
214
215 /* Stop queue */
216 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
217 ath5k_hw_reg_read(ah, AR5K_CR);
218 } else {
219 /*
220 * Schedule TX disable and wait until queue is empty
221 */
222 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
223
Nick Kossifidisb3a28e62010-11-23 20:47:31 +0200224 /* Wait for queue to stop */
225 for (i = 1000; i > 0 &&
226 (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue) != 0);
227 i--)
228 udelay(100);
229
230 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
231 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
232 "queue %i didn't stop !\n", queue);
233
234 /* Check for pending frames */
235 i = 1000;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300236 do {
237 pending = ath5k_hw_reg_read(ah,
238 AR5K_QUEUE_STATUS(queue)) &
239 AR5K_QCU_STS_FRMPENDCNT;
240 udelay(100);
241 } while (--i && pending);
242
Nick Kossifidis509a1062008-09-29 01:23:07 +0300243 /* For 2413+ order PCU to drop packets using
244 * QUIET mechanism */
245 if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
246 pending){
247 /* Set periodicity and duration */
248 ath5k_hw_reg_write(ah,
249 AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
250 AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
251 AR5K_QUIET_CTL2);
252
253 /* Enable quiet period for current TSF */
254 ath5k_hw_reg_write(ah,
255 AR5K_QUIET_CTL1_QT_EN |
256 AR5K_REG_SM(ath5k_hw_reg_read(ah,
257 AR5K_TSF_L32_5211) >> 10,
258 AR5K_QUIET_CTL1_NEXT_QT_TSF),
259 AR5K_QUIET_CTL1);
260
261 /* Force channel idle high */
262 AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
Bruno Randolfeada7ca2010-09-27 13:02:40 +0900263 AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
Nick Kossifidis509a1062008-09-29 01:23:07 +0300264
265 /* Wait a while and disable mechanism */
Nick Kossifidisb3a28e62010-11-23 20:47:31 +0200266 udelay(400);
Nick Kossifidis509a1062008-09-29 01:23:07 +0300267 AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
268 AR5K_QUIET_CTL1_QT_EN);
269
270 /* Re-check for pending frames */
Nick Kossifidisb3a28e62010-11-23 20:47:31 +0200271 i = 100;
Nick Kossifidis509a1062008-09-29 01:23:07 +0300272 do {
273 pending = ath5k_hw_reg_read(ah,
274 AR5K_QUEUE_STATUS(queue)) &
275 AR5K_QCU_STS_FRMPENDCNT;
276 udelay(100);
277 } while (--i && pending);
278
279 AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
Bruno Randolfeada7ca2010-09-27 13:02:40 +0900280 AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
Nick Kossifidisb3a28e62010-11-23 20:47:31 +0200281
282 if (pending)
283 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
284 "quiet mechanism didn't work q:%i !\n",
285 queue);
Nick Kossifidis509a1062008-09-29 01:23:07 +0300286 }
287
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300288 /* Clear register */
289 ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
Nick Kossifidisb3a28e62010-11-23 20:47:31 +0200290 if (pending) {
291 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
292 "tx dma didn't stop (q:%i, frm:%i) !\n",
293 queue, pending);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300294 return -EBUSY;
Nick Kossifidisb3a28e62010-11-23 20:47:31 +0200295 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300296 }
297
Nick Kossifidis509a1062008-09-29 01:23:07 +0300298 /* TODO: Check for success on 5210 else return error */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300299 return 0;
300}
301
302/**
303 * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
304 *
305 * @ah: The &struct ath5k_hw
306 * @queue: The hw queue number
307 *
308 * Get TX descriptor's address for a specific queue. For 5210 we ignore
309 * the queue number and use tx queue type since we only have 2 queues.
310 * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
311 * For newer chips with QCU/DCU we just read the corresponding TXDP register.
312 *
313 * XXX: Is TXDP read and clear ?
314 */
315u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
316{
317 u16 tx_reg;
318
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300319 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
320
321 /*
322 * Get the transmit queue descriptor pointer from the selected queue
323 */
324 /*5210 doesn't have QCU*/
325 if (ah->ah_version == AR5K_AR5210) {
326 switch (ah->ah_txq[queue].tqi_type) {
327 case AR5K_TX_QUEUE_DATA:
328 tx_reg = AR5K_NOQCU_TXDP0;
329 break;
330 case AR5K_TX_QUEUE_BEACON:
331 case AR5K_TX_QUEUE_CAB:
332 tx_reg = AR5K_NOQCU_TXDP1;
333 break;
334 default:
335 return 0xffffffff;
336 }
337 } else {
338 tx_reg = AR5K_QUEUE_TXDP(queue);
339 }
340
341 return ath5k_hw_reg_read(ah, tx_reg);
342}
343
344/**
345 * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
346 *
347 * @ah: The &struct ath5k_hw
348 * @queue: The hw queue number
349 *
350 * Set TX descriptor's address for a specific queue. For 5210 we ignore
351 * the queue number and we use tx queue type since we only have 2 queues
352 * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
353 * For newer chips with QCU/DCU we just set the corresponding TXDP register.
354 * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
355 * active.
356 */
357int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
358{
359 u16 tx_reg;
360
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300361 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
362
363 /*
364 * Set the transmit queue descriptor pointer register by type
365 * on 5210
366 */
367 if (ah->ah_version == AR5K_AR5210) {
368 switch (ah->ah_txq[queue].tqi_type) {
369 case AR5K_TX_QUEUE_DATA:
370 tx_reg = AR5K_NOQCU_TXDP0;
371 break;
372 case AR5K_TX_QUEUE_BEACON:
373 case AR5K_TX_QUEUE_CAB:
374 tx_reg = AR5K_NOQCU_TXDP1;
375 break;
376 default:
377 return -EINVAL;
378 }
379 } else {
380 /*
381 * Set the transmit queue descriptor pointer for
382 * the selected queue on QCU for 5211+
383 * (this won't work if the queue is still active)
384 */
385 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
386 return -EIO;
387
388 tx_reg = AR5K_QUEUE_TXDP(queue);
389 }
390
391 /* Set descriptor pointer */
392 ath5k_hw_reg_write(ah, phys_addr, tx_reg);
393
394 return 0;
395}
396
397/**
398 * ath5k_hw_update_tx_triglevel - Update tx trigger level
399 *
400 * @ah: The &struct ath5k_hw
401 * @increase: Flag to force increase of trigger level
402 *
403 * This function increases/decreases the tx trigger level for the tx fifo
404 * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
Bob Copelanda180a132010-08-15 13:03:12 -0400405 * the buffer and transmits its data. Lowering this results sending small
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300406 * frames more quickly but can lead to tx underruns, raising it a lot can
407 * result other problems (i think bmiss is related). Right now we start with
408 * the lowest possible (64Bytes) and if we get tx underrun we increase it using
Bob Copelanda180a132010-08-15 13:03:12 -0400409 * the increase flag. Returns -EIO if we have reached maximum/minimum.
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300410 *
411 * XXX: Link this with tx DMA size ?
412 * XXX: Use it to save interrupts ?
413 * TODO: Needs testing, i think it's related to bmiss...
414 */
415int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
416{
417 u32 trigger_level, imr;
418 int ret = -EIO;
419
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300420 /*
421 * Disable interrupts by setting the mask
422 */
423 imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
424
425 trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
426 AR5K_TXCFG_TXFULL);
427
428 if (!increase) {
429 if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
430 goto done;
431 } else
432 trigger_level +=
433 ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
434
435 /*
436 * Update trigger level on success
437 */
438 if (ah->ah_version == AR5K_AR5210)
439 ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
440 else
441 AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
442 AR5K_TXCFG_TXFULL, trigger_level);
443
444 ret = 0;
445
446done:
447 /*
448 * Restore interrupt mask
449 */
450 ath5k_hw_set_imr(ah, imr);
451
452 return ret;
453}
454
Nick Kossifidis9320b5c2010-11-23 20:36:45 +0200455
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300456/*******************\
457* Interrupt masking *
458\*******************/
459
460/**
461 * ath5k_hw_is_intr_pending - Check if we have pending interrupts
462 *
463 * @ah: The &struct ath5k_hw
464 *
465 * Check if we have pending interrupts to process. Returns 1 if we
466 * have pending interrupts and 0 if we haven't.
467 */
468bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
469{
Nick Kossifidis509a1062008-09-29 01:23:07 +0300470 return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300471}
472
473/**
474 * ath5k_hw_get_isr - Get interrupt status
475 *
476 * @ah: The @struct ath5k_hw
477 * @interrupt_mask: Driver's interrupt mask used to filter out
478 * interrupts in sw.
479 *
480 * This function is used inside our interrupt handler to determine the reason
481 * for the interrupt by reading Primary Interrupt Status Register. Returns an
482 * abstract interrupt status mask which is mostly ISR with some uncommon bits
483 * being mapped on some standard non hw-specific positions
484 * (check out &ath5k_int).
485 *
486 * NOTE: We use read-and-clear register, so after this function is called ISR
487 * is zeroed.
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300488 */
489int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
490{
491 u32 data;
492
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300493 /*
494 * Read interrupt status from the Interrupt Status register
495 * on 5210
496 */
497 if (ah->ah_version == AR5K_AR5210) {
498 data = ath5k_hw_reg_read(ah, AR5K_ISR);
499 if (unlikely(data == AR5K_INT_NOCARD)) {
500 *interrupt_mask = data;
501 return -ENODEV;
502 }
503 } else {
504 /*
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200505 * Read interrupt status from Interrupt
506 * Status Register shadow copy (Read And Clear)
507 *
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300508 * Note: PISR/SISR Not available on 5210
509 */
510 data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200511 if (unlikely(data == AR5K_INT_NOCARD)) {
512 *interrupt_mask = data;
513 return -ENODEV;
514 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300515 }
516
517 /*
518 * Get abstract interrupt mask (driver-compatible)
519 */
520 *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
521
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300522 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200523 u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
524
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300525 /*HIU = Host Interface Unit (PCI etc)*/
526 if (unlikely(data & (AR5K_ISR_HIUERR)))
527 *interrupt_mask |= AR5K_INT_FATAL;
528
529 /*Beacon Not Ready*/
530 if (unlikely(data & (AR5K_ISR_BNR)))
531 *interrupt_mask |= AR5K_INT_BNR;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300532
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200533 if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
534 AR5K_SISR2_DPERR |
535 AR5K_SISR2_MCABT)))
536 *interrupt_mask |= AR5K_INT_FATAL;
537
538 if (data & AR5K_ISR_TIM)
539 *interrupt_mask |= AR5K_INT_TIM;
540
541 if (data & AR5K_ISR_BCNMISC) {
542 if (sisr2 & AR5K_SISR2_TIM)
543 *interrupt_mask |= AR5K_INT_TIM;
544 if (sisr2 & AR5K_SISR2_DTIM)
545 *interrupt_mask |= AR5K_INT_DTIM;
546 if (sisr2 & AR5K_SISR2_DTIM_SYNC)
547 *interrupt_mask |= AR5K_INT_DTIM_SYNC;
548 if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
549 *interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
550 if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
551 *interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
552 }
553
554 if (data & AR5K_ISR_RXDOPPLER)
555 *interrupt_mask |= AR5K_INT_RX_DOPPLER;
556 if (data & AR5K_ISR_QCBRORN) {
557 *interrupt_mask |= AR5K_INT_QCBRORN;
558 ah->ah_txq_isr |= AR5K_REG_MS(
559 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
560 AR5K_SISR3_QCBRORN);
561 }
562 if (data & AR5K_ISR_QCBRURN) {
563 *interrupt_mask |= AR5K_INT_QCBRURN;
564 ah->ah_txq_isr |= AR5K_REG_MS(
565 ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
566 AR5K_SISR3_QCBRURN);
567 }
568 if (data & AR5K_ISR_QTRIG) {
569 *interrupt_mask |= AR5K_INT_QTRIG;
570 ah->ah_txq_isr |= AR5K_REG_MS(
571 ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
572 AR5K_SISR4_QTRIG);
573 }
574
575 if (data & AR5K_ISR_TXOK)
576 ah->ah_txq_isr |= AR5K_REG_MS(
577 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
578 AR5K_SISR0_QCU_TXOK);
579
580 if (data & AR5K_ISR_TXDESC)
581 ah->ah_txq_isr |= AR5K_REG_MS(
582 ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
583 AR5K_SISR0_QCU_TXDESC);
584
585 if (data & AR5K_ISR_TXERR)
586 ah->ah_txq_isr |= AR5K_REG_MS(
587 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
588 AR5K_SISR1_QCU_TXERR);
589
590 if (data & AR5K_ISR_TXEOL)
591 ah->ah_txq_isr |= AR5K_REG_MS(
592 ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
593 AR5K_SISR1_QCU_TXEOL);
594
595 if (data & AR5K_ISR_TXURN)
596 ah->ah_txq_isr |= AR5K_REG_MS(
597 ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
598 AR5K_SISR2_QCU_TXURN);
599 } else {
600 if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
601 | AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
602 *interrupt_mask |= AR5K_INT_FATAL;
603
604 /*
605 * XXX: BMISS interrupts may occur after association.
606 * I found this on 5210 code but it needs testing. If this is
607 * true we should disable them before assoc and re-enable them
Coly Li73ac36e2009-01-07 18:09:16 -0800608 * after a successful assoc + some jiffies.
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200609 interrupt_mask &= ~AR5K_INT_BMISS;
610 */
611 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300612
613 /*
614 * In case we didn't handle anything,
615 * print the register value.
616 */
617 if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200618 ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300619
620 return 0;
621}
622
623/**
624 * ath5k_hw_set_imr - Set interrupt mask
625 *
626 * @ah: The &struct ath5k_hw
627 * @new_mask: The new interrupt mask to be set
628 *
629 * Set the interrupt mask in hw to save interrupts. We do that by mapping
630 * ath5k_int bits to hw-specific bits to remove abstraction and writing
631 * Interrupt Mask Register.
632 */
633enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
634{
635 enum ath5k_int old_mask, int_mask;
636
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200637 old_mask = ah->ah_imr;
638
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300639 /*
640 * Disable card interrupts to prevent any race conditions
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200641 * (they will be re-enabled afterwards if AR5K_INT GLOBAL
642 * is set again on the new mask).
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300643 */
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200644 if (old_mask & AR5K_INT_GLOBAL) {
645 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
646 ath5k_hw_reg_read(ah, AR5K_IER);
647 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300648
649 /*
650 * Add additional, chipset-dependent interrupt mask flags
651 * and write them to the IMR (interrupt mask register).
652 */
653 int_mask = new_mask & AR5K_INT_COMMON;
654
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300655 if (ah->ah_version != AR5K_AR5210) {
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200656 /* Preserve per queue TXURN interrupt mask */
657 u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
658 & AR5K_SIMR2_QCU_TXURN;
659
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300660 if (new_mask & AR5K_INT_FATAL) {
661 int_mask |= AR5K_IMR_HIUERR;
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200662 simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
663 | AR5K_SIMR2_DPERR);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300664 }
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200665
666 /*Beacon Not Ready*/
667 if (new_mask & AR5K_INT_BNR)
668 int_mask |= AR5K_INT_BNR;
669
670 if (new_mask & AR5K_INT_TIM)
671 int_mask |= AR5K_IMR_TIM;
672
673 if (new_mask & AR5K_INT_TIM)
674 simr2 |= AR5K_SISR2_TIM;
675 if (new_mask & AR5K_INT_DTIM)
676 simr2 |= AR5K_SISR2_DTIM;
677 if (new_mask & AR5K_INT_DTIM_SYNC)
678 simr2 |= AR5K_SISR2_DTIM_SYNC;
679 if (new_mask & AR5K_INT_BCN_TIMEOUT)
680 simr2 |= AR5K_SISR2_BCN_TIMEOUT;
681 if (new_mask & AR5K_INT_CAB_TIMEOUT)
682 simr2 |= AR5K_SISR2_CAB_TIMEOUT;
683
684 if (new_mask & AR5K_INT_RX_DOPPLER)
685 int_mask |= AR5K_IMR_RXDOPPLER;
686
687 /* Note: Per queue interrupt masks
688 * are set via reset_tx_queue (qcu.c) */
689 ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
690 ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
691
692 } else {
693 if (new_mask & AR5K_INT_FATAL)
694 int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
695 | AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
696
697 ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300698 }
699
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200700 /* If RXNOFRM interrupt is masked disable it
701 * by setting AR5K_RXNOFRM to zero */
702 if (!(new_mask & AR5K_INT_RXNOFRM))
703 ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300704
705 /* Store new interrupt mask */
706 ah->ah_imr = new_mask;
707
Nick Kossifidis4c674c62008-10-26 20:40:25 +0200708 /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
709 if (new_mask & AR5K_INT_GLOBAL) {
710 ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
711 ath5k_hw_reg_read(ah, AR5K_IER);
712 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300713
714 return old_mask;
715}
716
Nick Kossifidis9320b5c2010-11-23 20:36:45 +0200717
718/********************\
719 Init/Stop functions
720\********************/
721
722/**
723 * ath5k_hw_dma_init - Initialize DMA unit
724 *
725 * @ah: The &struct ath5k_hw
726 *
727 * Set DMA size and pre-enable interrupts
728 * (driver handles tx/rx buffer setup and
729 * dma start/stop)
730 *
731 * XXX: Save/restore RXDP/TXDP registers ?
732 */
733void ath5k_hw_dma_init(struct ath5k_hw *ah)
734{
735 /*
736 * Set Rx/Tx DMA Configuration
737 *
738 * Set standard DMA size (128). Note that
739 * a DMA size of 512 causes rx overruns and tx errors
740 * on pci-e cards (tested on 5424 but since rx overruns
741 * also occur on 5416/5418 with madwifi we set 128
742 * for all PCI-E cards to be safe).
743 *
744 * XXX: need to check 5210 for this
745 * TODO: Check out tx triger level, it's always 64 on dumps but I
746 * guess we can tweak it and see how it goes ;-)
747 */
748 if (ah->ah_version != AR5K_AR5210) {
749 AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
750 AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
751 AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
752 AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
753 }
754
755 /* Pre-enable interrupts on 5211/5212*/
756 if (ah->ah_version != AR5K_AR5210)
757 ath5k_hw_set_imr(ah, ah->ah_imr);
758
759}
Nick Kossifidisd41174f2010-11-23 20:41:15 +0200760
761/**
762 * ath5k_hw_dma_stop - stop DMA unit
763 *
764 * @ah: The &struct ath5k_hw
765 *
766 * Stop tx/rx DMA and interrupts. Returns
767 * -EBUSY if tx or rx dma failed to stop.
768 *
769 * XXX: Sometimes DMA unit hangs and we have
770 * stuck frames on tx queues, only a reset
771 * can fix that.
772 */
773int ath5k_hw_dma_stop(struct ath5k_hw *ah)
774{
775 int i, qmax, err;
776 err = 0;
777
778 /* Disable interrupts */
779 ath5k_hw_set_imr(ah, 0);
780
781 /* Stop rx dma */
782 err = ath5k_hw_stop_rx_dma(ah);
783 if (err)
784 return err;
785
786 /* Clear any pending interrupts
787 * and disable tx dma */
788 if (ah->ah_version != AR5K_AR5210) {
789 ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
790 qmax = AR5K_NUM_TX_QUEUES;
791 } else {
792 /* PISR/SISR Not available on 5210 */
793 ath5k_hw_reg_read(ah, AR5K_ISR);
794 qmax = AR5K_NUM_TX_QUEUES_NOQCU;
795 }
796
797 for (i = 0; i < qmax; i++) {
798 err = ath5k_hw_stop_tx_dma(ah, i);
799 /* -EINVAL -> queue inactive */
800 if (err != -EINVAL)
801 return err;
802 }
803
804 return err;
805}