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