Merge branch 'for-linus' of git://neil.brown.name/md
[linux-2.6] / drivers / net / wireless / ath / ath5k / dma.c
1 /*
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
40 /*********\
41 * Receive *
42 \*********/
43
44 /**
45  * ath5k_hw_start_rx_dma - Start DMA receive
46  *
47  * @ah: The &struct ath5k_hw
48  */
49 void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
50 {
51         ATH5K_TRACE(ah->ah_sc);
52         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  */
61 int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
62 {
63         unsigned int i;
64
65         ATH5K_TRACE(ah->ah_sc);
66         ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
67
68         /*
69          * It may take some time to disable the DMA receive unit
70          */
71         for (i = 1000; i > 0 &&
72                         (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
73                         i--)
74                 udelay(10);
75
76         return i ? 0 : -EBUSY;
77 }
78
79 /**
80  * ath5k_hw_get_rxdp - Get RX Descriptor's address
81  *
82  * @ah: The &struct ath5k_hw
83  */
84 u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
85 {
86         return ath5k_hw_reg_read(ah, AR5K_RXDP);
87 }
88
89 /**
90  * ath5k_hw_set_rxdp - Set RX Descriptor's address
91  *
92  * @ah: The &struct ath5k_hw
93  * @phys_addr: RX descriptor address
94  *
95  * XXX: Should we check if rx is enabled before setting rxdp ?
96  */
97 void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
98 {
99         ATH5K_TRACE(ah->ah_sc);
100
101         ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
102 }
103
104
105 /**********\
106 * Transmit *
107 \**********/
108
109 /**
110  * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
111  *
112  * @ah: The &struct ath5k_hw
113  * @queue: The hw queue number
114  *
115  * Start DMA transmit for a specific queue and since 5210 doesn't have
116  * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
117  * queue for normal data and one queue for beacons). For queue setup
118  * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
119  * of range or if queue is already disabled.
120  *
121  * NOTE: Must be called after setting up tx control descriptor for that
122  * queue (see below).
123  */
124 int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
125 {
126         u32 tx_queue;
127
128         ATH5K_TRACE(ah->ah_sc);
129         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)
133                 return -EIO;
134
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,
181  * -EINVAL if queue number is out of range.
182  *
183  */
184 int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
185 {
186         unsigned int i = 40;
187         u32 tx_queue, pending;
188
189         ATH5K_TRACE(ah->ah_sc);
190         AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
191
192         /* Return if queue is declared inactive */
193         if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
194                 return -EIO;
195
196         if (ah->ah_version == AR5K_AR5210) {
197                 tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
198
199                 /*
200                  * Set by queue type
201                  */
202                 switch (ah->ah_txq[queue].tqi_type) {
203                 case AR5K_TX_QUEUE_DATA:
204                         tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
205                         break;
206                 case AR5K_TX_QUEUE_BEACON:
207                 case AR5K_TX_QUEUE_CAB:
208                         /* XXX Fix me... */
209                         tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
210                         ath5k_hw_reg_write(ah, 0, AR5K_BSR);
211                         break;
212                 default:
213                         return -EINVAL;
214                 }
215
216                 /* Stop queue */
217                 ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
218                 ath5k_hw_reg_read(ah, AR5K_CR);
219         } else {
220                 /*
221                  * Schedule TX disable and wait until queue is empty
222                  */
223                 AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
224
225                 /*Check for pending frames*/
226                 do {
227                         pending = ath5k_hw_reg_read(ah,
228                                 AR5K_QUEUE_STATUS(queue)) &
229                                 AR5K_QCU_STS_FRMPENDCNT;
230                         udelay(100);
231                 } while (--i && pending);
232
233                 /* For 2413+ order PCU to drop packets using
234                  * QUIET mechanism */
235                 if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) &&
236                 pending){
237                         /* Set periodicity and duration */
238                         ath5k_hw_reg_write(ah,
239                                 AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
240                                 AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
241                                 AR5K_QUIET_CTL2);
242
243                         /* Enable quiet period for current TSF */
244                         ath5k_hw_reg_write(ah,
245                                 AR5K_QUIET_CTL1_QT_EN |
246                                 AR5K_REG_SM(ath5k_hw_reg_read(ah,
247                                                 AR5K_TSF_L32_5211) >> 10,
248                                                 AR5K_QUIET_CTL1_NEXT_QT_TSF),
249                                 AR5K_QUIET_CTL1);
250
251                         /* Force channel idle high */
252                         AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
253                                         AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
254
255                         /* Wait a while and disable mechanism */
256                         udelay(200);
257                         AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
258                                                 AR5K_QUIET_CTL1_QT_EN);
259
260                         /* Re-check for pending frames */
261                         i = 40;
262                         do {
263                                 pending = ath5k_hw_reg_read(ah,
264                                         AR5K_QUEUE_STATUS(queue)) &
265                                         AR5K_QCU_STS_FRMPENDCNT;
266                                 udelay(100);
267                         } while (--i && pending);
268
269                         AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
270                                         AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
271                 }
272
273                 /* Clear register */
274                 ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
275                 if (pending)
276                         return -EBUSY;
277         }
278
279         /* TODO: Check for success on 5210 else return error */
280         return 0;
281 }
282
283 /**
284  * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
285  *
286  * @ah: The &struct ath5k_hw
287  * @queue: The hw queue number
288  *
289  * Get TX descriptor's address for a specific queue. For 5210 we ignore
290  * the queue number and use tx queue type since we only have 2 queues.
291  * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
292  * For newer chips with QCU/DCU we just read the corresponding TXDP register.
293  *
294  * XXX: Is TXDP read and clear ?
295  */
296 u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
297 {
298         u16 tx_reg;
299
300         ATH5K_TRACE(ah->ah_sc);
301         AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
302
303         /*
304          * Get the transmit queue descriptor pointer from the selected queue
305          */
306         /*5210 doesn't have QCU*/
307         if (ah->ah_version == AR5K_AR5210) {
308                 switch (ah->ah_txq[queue].tqi_type) {
309                 case AR5K_TX_QUEUE_DATA:
310                         tx_reg = AR5K_NOQCU_TXDP0;
311                         break;
312                 case AR5K_TX_QUEUE_BEACON:
313                 case AR5K_TX_QUEUE_CAB:
314                         tx_reg = AR5K_NOQCU_TXDP1;
315                         break;
316                 default:
317                         return 0xffffffff;
318                 }
319         } else {
320                 tx_reg = AR5K_QUEUE_TXDP(queue);
321         }
322
323         return ath5k_hw_reg_read(ah, tx_reg);
324 }
325
326 /**
327  * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
328  *
329  * @ah: The &struct ath5k_hw
330  * @queue: The hw queue number
331  *
332  * Set TX descriptor's address for a specific queue. For 5210 we ignore
333  * the queue number and we use tx queue type since we only have 2 queues
334  * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
335  * For newer chips with QCU/DCU we just set the corresponding TXDP register.
336  * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
337  * active.
338  */
339 int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
340 {
341         u16 tx_reg;
342
343         ATH5K_TRACE(ah->ah_sc);
344         AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
345
346         /*
347          * Set the transmit queue descriptor pointer register by type
348          * on 5210
349          */
350         if (ah->ah_version == AR5K_AR5210) {
351                 switch (ah->ah_txq[queue].tqi_type) {
352                 case AR5K_TX_QUEUE_DATA:
353                         tx_reg = AR5K_NOQCU_TXDP0;
354                         break;
355                 case AR5K_TX_QUEUE_BEACON:
356                 case AR5K_TX_QUEUE_CAB:
357                         tx_reg = AR5K_NOQCU_TXDP1;
358                         break;
359                 default:
360                         return -EINVAL;
361                 }
362         } else {
363                 /*
364                  * Set the transmit queue descriptor pointer for
365                  * the selected queue on QCU for 5211+
366                  * (this won't work if the queue is still active)
367                  */
368                 if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
369                         return -EIO;
370
371                 tx_reg = AR5K_QUEUE_TXDP(queue);
372         }
373
374         /* Set descriptor pointer */
375         ath5k_hw_reg_write(ah, phys_addr, tx_reg);
376
377         return 0;
378 }
379
380 /**
381  * ath5k_hw_update_tx_triglevel - Update tx trigger level
382  *
383  * @ah: The &struct ath5k_hw
384  * @increase: Flag to force increase of trigger level
385  *
386  * This function increases/decreases the tx trigger level for the tx fifo
387  * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
388  * the buffer and transmits it's data. Lowering this results sending small
389  * frames more quickly but can lead to tx underruns, raising it a lot can
390  * result other problems (i think bmiss is related). Right now we start with
391  * the lowest possible (64Bytes) and if we get tx underrun we increase it using
392  * the increase flag. Returns -EIO if we have have reached maximum/minimum.
393  *
394  * XXX: Link this with tx DMA size ?
395  * XXX: Use it to save interrupts ?
396  * TODO: Needs testing, i think it's related to bmiss...
397  */
398 int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
399 {
400         u32 trigger_level, imr;
401         int ret = -EIO;
402
403         ATH5K_TRACE(ah->ah_sc);
404
405         /*
406          * Disable interrupts by setting the mask
407          */
408         imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
409
410         trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
411                         AR5K_TXCFG_TXFULL);
412
413         if (!increase) {
414                 if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
415                         goto done;
416         } else
417                 trigger_level +=
418                         ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
419
420         /*
421          * Update trigger level on success
422          */
423         if (ah->ah_version == AR5K_AR5210)
424                 ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
425         else
426                 AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
427                                 AR5K_TXCFG_TXFULL, trigger_level);
428
429         ret = 0;
430
431 done:
432         /*
433          * Restore interrupt mask
434          */
435         ath5k_hw_set_imr(ah, imr);
436
437         return ret;
438 }
439
440 /*******************\
441 * Interrupt masking *
442 \*******************/
443
444 /**
445  * ath5k_hw_is_intr_pending - Check if we have pending interrupts
446  *
447  * @ah: The &struct ath5k_hw
448  *
449  * Check if we have pending interrupts to process. Returns 1 if we
450  * have pending interrupts and 0 if we haven't.
451  */
452 bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
453 {
454         ATH5K_TRACE(ah->ah_sc);
455         return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
456 }
457
458 /**
459  * ath5k_hw_get_isr - Get interrupt status
460  *
461  * @ah: The @struct ath5k_hw
462  * @interrupt_mask: Driver's interrupt mask used to filter out
463  * interrupts in sw.
464  *
465  * This function is used inside our interrupt handler to determine the reason
466  * for the interrupt by reading Primary Interrupt Status Register. Returns an
467  * abstract interrupt status mask which is mostly ISR with some uncommon bits
468  * being mapped on some standard non hw-specific positions
469  * (check out &ath5k_int).
470  *
471  * NOTE: We use read-and-clear register, so after this function is called ISR
472  * is zeroed.
473  */
474 int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
475 {
476         u32 data;
477
478         ATH5K_TRACE(ah->ah_sc);
479
480         /*
481          * Read interrupt status from the Interrupt Status register
482          * on 5210
483          */
484         if (ah->ah_version == AR5K_AR5210) {
485                 data = ath5k_hw_reg_read(ah, AR5K_ISR);
486                 if (unlikely(data == AR5K_INT_NOCARD)) {
487                         *interrupt_mask = data;
488                         return -ENODEV;
489                 }
490         } else {
491                 /*
492                  * Read interrupt status from Interrupt
493                  * Status Register shadow copy (Read And Clear)
494                  *
495                  * Note: PISR/SISR Not available on 5210
496                  */
497                 data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
498                 if (unlikely(data == AR5K_INT_NOCARD)) {
499                         *interrupt_mask = data;
500                         return -ENODEV;
501                 }
502         }
503
504         /*
505          * Get abstract interrupt mask (driver-compatible)
506          */
507         *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
508
509         if (ah->ah_version != AR5K_AR5210) {
510                 u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
511
512                 /*HIU = Host Interface Unit (PCI etc)*/
513                 if (unlikely(data & (AR5K_ISR_HIUERR)))
514                         *interrupt_mask |= AR5K_INT_FATAL;
515
516                 /*Beacon Not Ready*/
517                 if (unlikely(data & (AR5K_ISR_BNR)))
518                         *interrupt_mask |= AR5K_INT_BNR;
519
520                 if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
521                                         AR5K_SISR2_DPERR |
522                                         AR5K_SISR2_MCABT)))
523                         *interrupt_mask |= AR5K_INT_FATAL;
524
525                 if (data & AR5K_ISR_TIM)
526                         *interrupt_mask |= AR5K_INT_TIM;
527
528                 if (data & AR5K_ISR_BCNMISC) {
529                         if (sisr2 & AR5K_SISR2_TIM)
530                                 *interrupt_mask |= AR5K_INT_TIM;
531                         if (sisr2 & AR5K_SISR2_DTIM)
532                                 *interrupt_mask |= AR5K_INT_DTIM;
533                         if (sisr2 & AR5K_SISR2_DTIM_SYNC)
534                                 *interrupt_mask |= AR5K_INT_DTIM_SYNC;
535                         if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
536                                 *interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
537                         if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
538                                 *interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
539                 }
540
541                 if (data & AR5K_ISR_RXDOPPLER)
542                         *interrupt_mask |= AR5K_INT_RX_DOPPLER;
543                 if (data & AR5K_ISR_QCBRORN) {
544                         *interrupt_mask |= AR5K_INT_QCBRORN;
545                         ah->ah_txq_isr |= AR5K_REG_MS(
546                                         ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
547                                         AR5K_SISR3_QCBRORN);
548                 }
549                 if (data & AR5K_ISR_QCBRURN) {
550                         *interrupt_mask |= AR5K_INT_QCBRURN;
551                         ah->ah_txq_isr |= AR5K_REG_MS(
552                                         ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
553                                         AR5K_SISR3_QCBRURN);
554                 }
555                 if (data & AR5K_ISR_QTRIG) {
556                         *interrupt_mask |= AR5K_INT_QTRIG;
557                         ah->ah_txq_isr |= AR5K_REG_MS(
558                                         ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
559                                         AR5K_SISR4_QTRIG);
560                 }
561
562                 if (data & AR5K_ISR_TXOK)
563                         ah->ah_txq_isr |= AR5K_REG_MS(
564                                         ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
565                                         AR5K_SISR0_QCU_TXOK);
566
567                 if (data & AR5K_ISR_TXDESC)
568                         ah->ah_txq_isr |= AR5K_REG_MS(
569                                         ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
570                                         AR5K_SISR0_QCU_TXDESC);
571
572                 if (data & AR5K_ISR_TXERR)
573                         ah->ah_txq_isr |= AR5K_REG_MS(
574                                         ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
575                                         AR5K_SISR1_QCU_TXERR);
576
577                 if (data & AR5K_ISR_TXEOL)
578                         ah->ah_txq_isr |= AR5K_REG_MS(
579                                         ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
580                                         AR5K_SISR1_QCU_TXEOL);
581
582                 if (data & AR5K_ISR_TXURN)
583                         ah->ah_txq_isr |= AR5K_REG_MS(
584                                         ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
585                                         AR5K_SISR2_QCU_TXURN);
586         } else {
587                 if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
588                                 | AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
589                         *interrupt_mask |= AR5K_INT_FATAL;
590
591                 /*
592                  * XXX: BMISS interrupts may occur after association.
593                  * I found this on 5210 code but it needs testing. If this is
594                  * true we should disable them before assoc and re-enable them
595                  * after a successful assoc + some jiffies.
596                         interrupt_mask &= ~AR5K_INT_BMISS;
597                  */
598         }
599
600         /*
601          * In case we didn't handle anything,
602          * print the register value.
603          */
604         if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
605                 ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr);
606
607         return 0;
608 }
609
610 /**
611  * ath5k_hw_set_imr - Set interrupt mask
612  *
613  * @ah: The &struct ath5k_hw
614  * @new_mask: The new interrupt mask to be set
615  *
616  * Set the interrupt mask in hw to save interrupts. We do that by mapping
617  * ath5k_int bits to hw-specific bits to remove abstraction and writing
618  * Interrupt Mask Register.
619  */
620 enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
621 {
622         enum ath5k_int old_mask, int_mask;
623
624         old_mask = ah->ah_imr;
625
626         /*
627          * Disable card interrupts to prevent any race conditions
628          * (they will be re-enabled afterwards if AR5K_INT GLOBAL
629          * is set again on the new mask).
630          */
631         if (old_mask & AR5K_INT_GLOBAL) {
632                 ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
633                 ath5k_hw_reg_read(ah, AR5K_IER);
634         }
635
636         /*
637          * Add additional, chipset-dependent interrupt mask flags
638          * and write them to the IMR (interrupt mask register).
639          */
640         int_mask = new_mask & AR5K_INT_COMMON;
641
642         if (ah->ah_version != AR5K_AR5210) {
643                 /* Preserve per queue TXURN interrupt mask */
644                 u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
645                                 & AR5K_SIMR2_QCU_TXURN;
646
647                 if (new_mask & AR5K_INT_FATAL) {
648                         int_mask |= AR5K_IMR_HIUERR;
649                         simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
650                                 | AR5K_SIMR2_DPERR);
651                 }
652
653                 /*Beacon Not Ready*/
654                 if (new_mask & AR5K_INT_BNR)
655                         int_mask |= AR5K_INT_BNR;
656
657                 if (new_mask & AR5K_INT_TIM)
658                         int_mask |= AR5K_IMR_TIM;
659
660                 if (new_mask & AR5K_INT_TIM)
661                         simr2 |= AR5K_SISR2_TIM;
662                 if (new_mask & AR5K_INT_DTIM)
663                         simr2 |= AR5K_SISR2_DTIM;
664                 if (new_mask & AR5K_INT_DTIM_SYNC)
665                         simr2 |= AR5K_SISR2_DTIM_SYNC;
666                 if (new_mask & AR5K_INT_BCN_TIMEOUT)
667                         simr2 |= AR5K_SISR2_BCN_TIMEOUT;
668                 if (new_mask & AR5K_INT_CAB_TIMEOUT)
669                         simr2 |= AR5K_SISR2_CAB_TIMEOUT;
670
671                 if (new_mask & AR5K_INT_RX_DOPPLER)
672                         int_mask |= AR5K_IMR_RXDOPPLER;
673
674                 /* Note: Per queue interrupt masks
675                  * are set via reset_tx_queue (qcu.c) */
676                 ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
677                 ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
678
679         } else {
680                 if (new_mask & AR5K_INT_FATAL)
681                         int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
682                                 | AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
683
684                 ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
685         }
686
687         /* If RXNOFRM interrupt is masked disable it
688          * by setting AR5K_RXNOFRM to zero */
689         if (!(new_mask & AR5K_INT_RXNOFRM))
690                 ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
691
692         /* Store new interrupt mask */
693         ah->ah_imr = new_mask;
694
695         /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
696         if (new_mask & AR5K_INT_GLOBAL) {
697                 ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
698                 ath5k_hw_reg_read(ah, AR5K_IER);
699         }
700
701         return old_mask;
702 }
703