]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / dev / ath / ath_hal / ar9300 / ar9300_interrupts.c
1 /*
2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include "opt_ah.h"
18
19 #include "ah.h"
20 #include "ah_internal.h"
21
22 #include "ar9300/ar9300.h"
23 #include "ar9300/ar9300reg.h"
24 #include "ar9300/ar9300phy.h"
25
26 /*
27  * Checks to see if an interrupt is pending on our NIC
28  *
29  * Returns: TRUE    if an interrupt is pending
30  *          FALSE   if not
31  */
32 HAL_BOOL
33 ar9300_is_interrupt_pending(struct ath_hal *ah)
34 {
35     u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
36     u_int32_t host_isr;
37
38     /*
39      * Some platforms trigger our ISR before applying power to
40      * the card, so make sure.
41      */
42     host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));
43     if ((host_isr & AR_INTR_ASYNC_USED) && (host_isr != AR_INTR_SPURIOUS)) {
44         return AH_TRUE;
45     }
46
47     host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));
48     if (AR_SREV_POSEIDON(ah)) {
49         sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
50     }
51     else if (AR_SREV_WASP(ah)) {
52         sync_en_def = AR9340_INTR_SYNC_DEFAULT;
53     }
54
55     if ((host_isr & (sync_en_def | AR_INTR_SYNC_MASK_GPIO)) &&
56         (host_isr != AR_INTR_SPURIOUS)) {
57         return AH_TRUE;
58     }
59
60     return AH_FALSE;
61 }
62
63 /*
64  * Reads the Interrupt Status Register value from the NIC, thus deasserting
65  * the interrupt line, and returns both the masked and unmasked mapped ISR
66  * values.  The value returned is mapped to abstract the hw-specific bit
67  * locations in the Interrupt Status Register.
68  *
69  * Returns: A hardware-abstracted bitmap of all non-masked-out
70  *          interrupts pending, as well as an unmasked value
71  */
72 #define MAP_ISR_S2_HAL_CST          6 /* Carrier sense timeout */
73 #define MAP_ISR_S2_HAL_GTT          6 /* Global transmit timeout */
74 #define MAP_ISR_S2_HAL_TIM          3 /* TIM */
75 #define MAP_ISR_S2_HAL_CABEND       0 /* CABEND */
76 #define MAP_ISR_S2_HAL_DTIMSYNC     7 /* DTIMSYNC */
77 #define MAP_ISR_S2_HAL_DTIM         7 /* DTIM */
78 #define MAP_ISR_S2_HAL_TSFOOR       4 /* Rx TSF out of range */
79 #define MAP_ISR_S2_HAL_BBPANIC      6 /* Panic watchdog IRQ from BB */
80 HAL_BOOL
81 ar9300_get_pending_interrupts(
82     struct ath_hal *ah,
83     HAL_INT *masked,
84     HAL_INT_TYPE type,
85     u_int8_t msi,
86     HAL_BOOL nortc)
87 {
88     struct ath_hal_9300 *ahp = AH9300(ah);
89     HAL_BOOL  ret_val = AH_TRUE;
90     u_int32_t isr = 0;
91     u_int32_t mask2 = 0;
92     u_int32_t sync_cause = 0;
93     u_int32_t async_cause;
94     u_int32_t msi_pend_addr_mask = 0;
95     u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
96     HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
97
98     *masked = 0;
99
100     if (!nortc) {
101         if (HAL_INT_MSI == type) {
102             if (msi == HAL_MSIVEC_RXHP) {
103                 OS_REG_WRITE(ah, AR_ISR, AR_ISR_HP_RXOK);
104                 *masked = HAL_INT_RXHP;
105                 goto end;
106             } else if (msi == HAL_MSIVEC_RXLP) {
107                 OS_REG_WRITE(ah, AR_ISR,
108                     (AR_ISR_LP_RXOK | AR_ISR_RXMINTR | AR_ISR_RXINTM));
109                 *masked = HAL_INT_RXLP;
110                 goto end;
111             } else if (msi == HAL_MSIVEC_TX) {
112                 OS_REG_WRITE(ah, AR_ISR, AR_ISR_TXOK);
113                 *masked = HAL_INT_TX;
114                 goto end;
115             } else if (msi == HAL_MSIVEC_MISC) {
116                 /*
117                  * For the misc MSI event fall through and determine the cause.
118                  */
119             }
120         }
121     }
122
123     /* Make sure mac interrupt is pending in async interrupt cause register */
124     async_cause = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));
125     if (async_cause & AR_INTR_ASYNC_USED) {
126         /*
127          * RTC may not be on since it runs on a slow 32khz clock
128          * so check its status to be sure
129          */
130         if (!nortc &&
131             (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
132              AR_RTC_STATUS_ON)
133         {
134             isr = OS_REG_READ(ah, AR_ISR);
135         }
136     }
137
138     if (AR_SREV_POSEIDON(ah)) {
139         sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
140     }
141     else if (AR_SREV_WASP(ah)) {
142         sync_en_def = AR9340_INTR_SYNC_DEFAULT;
143     }
144
145     sync_cause =
146         OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)) &
147         (sync_en_def | AR_INTR_SYNC_MASK_GPIO);
148
149     if (!isr && !sync_cause && !async_cause) {
150         ret_val = AH_FALSE;
151         goto end;
152     }
153
154     HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
155         "%s: isr=0x%x, sync_cause=0x%x, async_cause=0x%x\n",
156         __func__,
157         isr,
158         sync_cause,
159         async_cause);
160
161     if (isr) {
162         if (isr & AR_ISR_BCNMISC) {
163             u_int32_t isr2;
164             isr2 = OS_REG_READ(ah, AR_ISR_S2);
165
166             /* Translate ISR bits to HAL values */
167             mask2 |= ((isr2 & AR_ISR_S2_TIM) >> MAP_ISR_S2_HAL_TIM);
168             mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> MAP_ISR_S2_HAL_DTIM);
169             mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> MAP_ISR_S2_HAL_DTIMSYNC);
170             mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> MAP_ISR_S2_HAL_CABEND);
171             mask2 |= ((isr2 & AR_ISR_S2_GTT) << MAP_ISR_S2_HAL_GTT);
172             mask2 |= ((isr2 & AR_ISR_S2_CST) << MAP_ISR_S2_HAL_CST);
173             mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> MAP_ISR_S2_HAL_TSFOOR);
174             mask2 |= ((isr2 & AR_ISR_S2_BBPANIC) >> MAP_ISR_S2_HAL_BBPANIC);
175
176             if (!p_cap->halIsrRacSupport) {
177                 /*
178                  * EV61133 (missing interrupts due to ISR_RAC):
179                  * If not using ISR_RAC, clear interrupts by writing to ISR_S2.
180                  * This avoids a race condition where a new BCNMISC interrupt
181                  * could come in between reading the ISR and clearing the
182                  * interrupt via the primary ISR.  We therefore clear the
183                  * interrupt via the secondary, which avoids this race.
184                  */ 
185                 OS_REG_WRITE(ah, AR_ISR_S2, isr2);
186                 isr &= ~AR_ISR_BCNMISC;
187             }
188         }
189
190         /* Use AR_ISR_RAC only if chip supports it. 
191          * See EV61133 (missing interrupts due to ISR_RAC) 
192          */
193         if (p_cap->halIsrRacSupport) {
194             isr = OS_REG_READ(ah, AR_ISR_RAC);
195         }
196         if (isr == 0xffffffff) {
197             *masked = 0;
198             ret_val = AH_FALSE;
199             goto end;
200         }
201  
202         *masked = isr & HAL_INT_COMMON;
203
204         /*
205          * When interrupt mitigation is switched on, we fake a normal RX or TX
206          * interrupt when we received a mitigated interrupt. This way, the upper
207          * layer do not need to know about feature.
208          */
209         if (ahp->ah_intr_mitigation_rx) {
210             /* Only Rx interrupt mitigation. No Tx intr. mitigation. */
211             if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) {
212                 *masked |= HAL_INT_RXLP;
213             }
214         }
215         if (ahp->ah_intr_mitigation_tx) {
216             if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) {
217                 *masked |= HAL_INT_TX;
218             }
219         }
220
221         if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) {
222             *masked |= HAL_INT_RXLP;
223         }
224         if (isr & AR_ISR_HP_RXOK) {
225             *masked |= HAL_INT_RXHP;
226         }
227         if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
228             *masked |= HAL_INT_TX;
229
230             if (!p_cap->halIsrRacSupport) {
231                 u_int32_t s0, s1;
232                 /*
233                  * EV61133 (missing interrupts due to ISR_RAC):
234                  * If not using ISR_RAC, clear interrupts by writing to
235                  * ISR_S0/S1.
236                  * This avoids a race condition where a new interrupt
237                  * could come in between reading the ISR and clearing the
238                  * interrupt via the primary ISR.  We therefore clear the
239                  * interrupt via the secondary, which avoids this race.
240                  */ 
241                 s0 = OS_REG_READ(ah, AR_ISR_S0);
242                 OS_REG_WRITE(ah, AR_ISR_S0, s0);
243                 s1 = OS_REG_READ(ah, AR_ISR_S1);
244                 OS_REG_WRITE(ah, AR_ISR_S1, s1);
245
246                 isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL);
247             }
248         }
249
250         /*
251          * Do not treat receive overflows as fatal for owl.
252          */
253         if (isr & AR_ISR_RXORN) {
254 #if __PKT_SERIOUS_ERRORS__
255             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
256                 "%s: receive FIFO overrun interrupt\n", __func__);
257 #endif
258         }
259
260 #if 0
261         /* XXX Verify if this is fixed for Osprey */
262         if (!p_cap->halAutoSleepSupport) {
263             u_int32_t isr5 = OS_REG_READ(ah, AR_ISR_S5_S);
264             if (isr5 & AR_ISR_S5_TIM_TIMER) {
265                 *masked |= HAL_INT_TIM_TIMER;
266             }
267         }
268 #endif
269         if (isr & AR_ISR_GENTMR) {
270             u_int32_t s5;
271
272             if (p_cap->halIsrRacSupport) {
273                 /* Use secondary shadow registers if using ISR_RAC */
274                 s5 = OS_REG_READ(ah, AR_ISR_S5_S);
275             } else {
276                 s5 = OS_REG_READ(ah, AR_ISR_S5);
277             }
278             if (isr & AR_ISR_GENTMR) {
279
280                 HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
281                     "%s: GENTIMER, ISR_RAC=0x%x ISR_S2_S=0x%x\n", __func__,
282                     isr, s5);
283                 ahp->ah_intr_gen_timer_trigger =
284                     MS(s5, AR_ISR_S5_GENTIMER_TRIG);
285                 ahp->ah_intr_gen_timer_thresh =
286                     MS(s5, AR_ISR_S5_GENTIMER_THRESH);
287                 if (ahp->ah_intr_gen_timer_trigger) {
288                     *masked |= HAL_INT_GENTIMER;
289                 }
290             }
291             if (!p_cap->halIsrRacSupport) {
292                 /*
293                  * EV61133 (missing interrupts due to ISR_RAC):
294                  * If not using ISR_RAC, clear interrupts by writing to ISR_S5.
295                  * This avoids a race condition where a new interrupt
296                  * could come in between reading the ISR and clearing the
297                  * interrupt via the primary ISR.  We therefore clear the
298                  * interrupt via the secondary, which avoids this race.
299                  */ 
300                 OS_REG_WRITE(ah, AR_ISR_S5, s5);
301                 isr &= ~AR_ISR_GENTMR;
302             }
303         }
304
305         *masked |= mask2;
306
307         if (!p_cap->halIsrRacSupport) {
308             /*
309              * EV61133 (missing interrupts due to ISR_RAC):
310              * If not using ISR_RAC, clear the interrupts we've read by
311              * writing back ones in these locations to the primary ISR
312              * (except for interrupts that have a secondary isr register -
313              * see above).
314              */ 
315             OS_REG_WRITE(ah, AR_ISR, isr);
316
317             /* Flush prior write */
318             (void) OS_REG_READ(ah, AR_ISR);
319         }
320
321 #ifdef AH_SUPPORT_AR9300
322         if (*masked & HAL_INT_BBPANIC) {
323             ar9300_handle_bb_panic(ah);
324         }
325 #endif
326     }
327
328     if (async_cause) {
329         if (nortc) {
330             OS_REG_WRITE(ah,
331                 AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR), async_cause);
332             /* Flush prior write */
333             (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR));
334         } else {
335 #ifdef ATH_GPIO_USE_ASYNC_CAUSE
336             if (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) {
337                 ahp->ah_gpio_cause = (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) >>
338                                      AR_INTR_ASYNC_ENABLE_GPIO_S;
339                 *masked |= HAL_INT_GPIO;
340             }
341 #endif
342         }
343
344 #if ATH_SUPPORT_MCI
345         if ((async_cause & AR_INTR_ASYNC_CAUSE_MCI) &&
346             p_cap->halMciSupport)
347         {
348             u_int32_t int_raw, int_rx_msg;
349
350             int_rx_msg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
351             int_raw = OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW);
352
353             if ((int_raw == 0xdeadbeef) || (int_rx_msg == 0xdeadbeef))
354             {
355                 HALDEBUG(ah, HAL_DEBUG_BT_COEX, 
356                     "(MCI) Get 0xdeadbeef during MCI int processing"
357                     "new int_raw=0x%08x, new rx_msg_raw=0x%08x, "
358                     "int_raw=0x%08x, rx_msg_raw=0x%08x\n",
359                     int_raw, int_rx_msg, ahp->ah_mci_int_raw, 
360                     ahp->ah_mci_int_rx_msg);
361             }
362             else {
363                 if (ahp->ah_mci_int_raw || ahp->ah_mci_int_rx_msg) {
364                     ahp->ah_mci_int_rx_msg |= int_rx_msg;
365                     ahp->ah_mci_int_raw |= int_raw;
366                 }
367                 else {
368                     ahp->ah_mci_int_rx_msg = int_rx_msg;
369                     ahp->ah_mci_int_raw = int_raw;
370                 }
371
372                 *masked |= HAL_INT_MCI;
373                 ahp->ah_mci_rx_status = OS_REG_READ(ah, AR_MCI_RX_STATUS);
374                 if (int_rx_msg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
375                     ahp->ah_mci_cont_status = 
376                                     OS_REG_READ(ah, AR_MCI_CONT_STATUS);
377                 }
378                 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 
379                     int_rx_msg);
380                 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, int_raw);
381
382                 HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s:AR_INTR_SYNC_MCI\n", __func__);
383             }
384         }
385 #endif
386     }
387
388     if (sync_cause) {
389         int host1_fatal, host1_perr, radm_cpl_timeout, local_timeout;
390
391         host1_fatal = AR_SREV_WASP(ah) ? 
392             AR9340_INTR_SYNC_HOST1_FATAL : AR9300_INTR_SYNC_HOST1_FATAL;
393         host1_perr = AR_SREV_WASP(ah) ?
394             AR9340_INTR_SYNC_HOST1_PERR : AR9300_INTR_SYNC_HOST1_PERR;
395         radm_cpl_timeout = AR_SREV_WASP(ah) ? 
396             0x0 : AR9300_INTR_SYNC_RADM_CPL_TIMEOUT;
397         local_timeout = AR_SREV_WASP(ah) ?
398             AR9340_INTR_SYNC_LOCAL_TIMEOUT : AR9300_INTR_SYNC_LOCAL_TIMEOUT;
399
400         if (sync_cause & host1_fatal) {
401 #if __PKT_SERIOUS_ERRORS__
402             HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
403                 "%s: received PCI FATAL interrupt\n", __func__);
404 #endif
405            *masked |= HAL_INT_FATAL; /* Set FATAL INT flag here;*/
406         }
407         if (sync_cause & host1_perr) {
408 #if __PKT_SERIOUS_ERRORS__
409             HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
410                 "%s: received PCI PERR interrupt\n", __func__);
411 #endif
412         }
413
414         if (sync_cause & radm_cpl_timeout) {
415             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
416                 "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
417                 __func__);
418
419             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF);
420             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), 0);
421             *masked |= HAL_INT_FATAL;
422         }
423         if (sync_cause & local_timeout) {
424             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
425                 "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
426                 __func__);
427         }
428
429 #ifndef ATH_GPIO_USE_ASYNC_CAUSE
430         if (sync_cause & AR_INTR_SYNC_MASK_GPIO) {
431             ahp->ah_gpio_cause = (sync_cause & AR_INTR_SYNC_MASK_GPIO) >>
432                                  AR_INTR_SYNC_ENABLE_GPIO_S;
433             *masked |= HAL_INT_GPIO;
434             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
435                 "%s: AR_INTR_SYNC_GPIO\n", __func__);
436         }
437 #endif
438
439         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR), sync_cause);
440         /* Flush prior write */
441         (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));
442     }
443
444 end:
445     if (HAL_INT_MSI == type) {
446         /*
447          * WAR for Bug EV#75887
448          * In normal case, SW read HOST_INTF_PCIE_MSI (0x40A4) and write
449          * into ah_msi_reg.  Then use value of ah_msi_reg to set bit#25
450          * when want to enable HW write the cfg_msi_pending.
451          * Sometimes, driver get MSI interrupt before read 0x40a4 and
452          * ah_msi_reg is initialization value (0x0).
453          * We don't know why "MSI interrupt earlier than driver read" now...
454          */
455         if (!ahp->ah_msi_reg) {
456             ahp->ah_msi_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI));
457         }
458         if (AR_SREV_POSEIDON(ah)) {
459             msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
460         } else {
461             msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;
462         }
463         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),
464             ((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));
465
466     }
467
468     return ret_val;
469 }
470
471 HAL_INT
472 ar9300_get_interrupts(struct ath_hal *ah)
473 {
474     return AH9300(ah)->ah_mask_reg;
475 }
476
477 /*
478  * Atomically enables NIC interrupts.  Interrupts are passed in
479  * via the enumerated bitmask in ints.
480  */
481 HAL_INT
482 ar9300_set_interrupts(struct ath_hal *ah, HAL_INT ints, HAL_BOOL nortc)
483 {
484     struct ath_hal_9300 *ahp = AH9300(ah);
485     u_int32_t omask = ahp->ah_mask_reg;
486     u_int32_t mask, mask2, msi_mask = 0;
487     u_int32_t msi_pend_addr_mask = 0;
488     u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;
489     HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;
490
491     HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
492         "%s: 0x%x => 0x%x\n", __func__, omask, ints);
493
494     if (omask & HAL_INT_GLOBAL) {
495         HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
496
497         if (ah->ah_config.ath_hal_enable_msi) {
498             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE), 0);
499             /* flush write to HW */
500             (void)OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE));
501         }
502
503         if (!nortc) {
504             OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
505             (void) OS_REG_READ(ah, AR_IER);   /* flush write to HW */
506         }
507
508         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0);
509         /* flush write to HW */
510         (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE));
511         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), 0);
512         /* flush write to HW */
513         (void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE));
514     }
515
516     if (!nortc) {
517         /* reference count for global IER */
518         if (ints & HAL_INT_GLOBAL) {
519 #ifdef AH_DEBUG
520             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
521                 "%s: Request HAL_INT_GLOBAL ENABLED\n", __func__);
522 #if 0
523             if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0) {
524                 HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
525                     "%s: WARNING: ah_ier_ref_count is 0 "
526                     "and attempting to enable IER\n",
527                     __func__);
528             }
529 #endif
530 #endif
531 #if 0
532             if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) > 0) {
533                 OS_ATOMIC_DEC(&ahp->ah_ier_ref_count);
534             } 
535 #endif
536         } else {
537             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
538                 "%s: Request HAL_INT_GLOBAL DISABLED\n", __func__);
539             OS_ATOMIC_INC(&ahp->ah_ier_ref_count);
540         }
541         HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
542             "%s: ah_ier_ref_count = %d\n", __func__, ahp->ah_ier_ref_count);
543
544         mask = ints & HAL_INT_COMMON;
545         mask2 = 0;
546         msi_mask = 0;
547
548         if (ints & HAL_INT_TX) {
549             if (ahp->ah_intr_mitigation_tx) {
550                 mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
551             } else if (ahp->ah_tx_ok_interrupt_mask) {
552                 mask |= AR_IMR_TXOK;
553             }
554             msi_mask |= AR_INTR_PRIO_TX;
555             if (ahp->ah_tx_err_interrupt_mask) {
556                 mask |= AR_IMR_TXERR;
557             }
558             if (ahp->ah_tx_eol_interrupt_mask) {
559                 mask |= AR_IMR_TXEOL;
560             }
561         }
562         if (ints & HAL_INT_RX) {
563             mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
564             if (ahp->ah_intr_mitigation_rx) {
565                 mask &= ~(AR_IMR_RXOK_LP);
566                 mask |=  AR_IMR_RXMINTR | AR_IMR_RXINTM;
567             } else {
568                 mask |= AR_IMR_RXOK_LP;
569             }
570             msi_mask |= AR_INTR_PRIO_RXLP | AR_INTR_PRIO_RXHP;
571             if (! p_cap->halAutoSleepSupport) {
572                 mask |= AR_IMR_GENTMR;
573             }
574         }
575
576         if (ints & (HAL_INT_BMISC)) {
577             mask |= AR_IMR_BCNMISC;
578             if (ints & HAL_INT_TIM) {
579                 mask2 |= AR_IMR_S2_TIM;
580             }
581             if (ints & HAL_INT_DTIM) {
582                 mask2 |= AR_IMR_S2_DTIM;
583             }
584             if (ints & HAL_INT_DTIMSYNC) {
585                 mask2 |= AR_IMR_S2_DTIMSYNC;
586             }
587             if (ints & HAL_INT_CABEND) {
588                 mask2 |= (AR_IMR_S2_CABEND);
589             }
590             if (ints & HAL_INT_TSFOOR) {
591                 mask2 |= AR_IMR_S2_TSFOOR;
592             }
593         }
594
595         if (ints & (HAL_INT_GTT | HAL_INT_CST)) {
596             mask |= AR_IMR_BCNMISC;
597             if (ints & HAL_INT_GTT) {
598                 mask2 |= AR_IMR_S2_GTT;
599             }
600             if (ints & HAL_INT_CST) {
601                 mask2 |= AR_IMR_S2_CST;
602             }
603         }
604
605         if (ints & HAL_INT_BBPANIC) {
606             /* EV92527 - MAC secondary interrupt must enable AR_IMR_BCNMISC */
607             mask |= AR_IMR_BCNMISC;
608             mask2 |= AR_IMR_S2_BBPANIC;
609         }
610
611         if (ints & HAL_INT_GENTIMER) {
612             HALDEBUG(ah, HAL_DEBUG_INTERRUPT,
613                 "%s: enabling gen timer\n", __func__);
614             mask |= AR_IMR_GENTMR;
615         }
616
617         /* Write the new IMR and store off our SW copy. */
618         HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
619         OS_REG_WRITE(ah, AR_IMR, mask);
620         ahp->ah_mask2Reg &= ~(AR_IMR_S2_TIM |
621                         AR_IMR_S2_DTIM |
622                         AR_IMR_S2_DTIMSYNC |
623                         AR_IMR_S2_CABEND |
624                         AR_IMR_S2_CABTO  |
625                         AR_IMR_S2_TSFOOR |
626                         AR_IMR_S2_GTT |
627                         AR_IMR_S2_CST |
628                         AR_IMR_S2_BBPANIC);
629         ahp->ah_mask2Reg |= mask2;
630         OS_REG_WRITE(ah, AR_IMR_S2, ahp->ah_mask2Reg );
631         ahp->ah_mask_reg = ints;
632
633         if (! p_cap->halAutoSleepSupport) {
634             if (ints & HAL_INT_TIM_TIMER) {
635                 OS_REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
636             }
637             else {
638                 OS_REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
639             }
640         }
641     }
642
643     /* Re-enable interrupts if they were enabled before. */
644 #if HAL_INTR_REFCOUNT_DISABLE
645     if ((ints & HAL_INT_GLOBAL)) {
646 #else
647     if ((ints & HAL_INT_GLOBAL) && (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0)) {
648 #endif
649         HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
650         
651         if (!nortc) {
652             OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
653         }
654
655         mask = AR_INTR_MAC_IRQ;
656 #ifdef ATH_GPIO_USE_ASYNC_CAUSE
657         if (ints & HAL_INT_GPIO) {
658             if (ahp->ah_gpio_mask) {
659                 mask |= SM(ahp->ah_gpio_mask, AR_INTR_ASYNC_MASK_GPIO);
660             }
661         }
662 #endif
663
664 #if ATH_SUPPORT_MCI
665         if (ints & HAL_INT_MCI) {
666             mask |= AR_INTR_ASYNC_MASK_MCI;
667         }
668 #endif
669
670         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), mask);
671         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK), mask);
672
673         if (ah->ah_config.ath_hal_enable_msi) {
674             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE),
675                 msi_mask);
676             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK),
677                 msi_mask);
678             if (AR_SREV_POSEIDON(ah)) {
679                 msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;
680             } else {
681                 msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;
682             }
683             OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),
684                 ((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));
685         }
686
687         /*
688          * debug - enable to see all synchronous interrupts status
689          * Enable synchronous GPIO interrupts as well, since some async
690          * GPIO interrupts don't wake the chip up.
691          */
692         mask = 0;
693 #ifndef ATH_GPIO_USE_ASYNC_CAUSE
694         if (ints & HAL_INT_GPIO) {
695             mask |= SM(ahp->ah_gpio_mask, AR_INTR_SYNC_MASK_GPIO);
696         }
697 #endif
698         if (AR_SREV_POSEIDON(ah)) {
699             sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;
700         }
701         else if (AR_SREV_WASP(ah)) {
702             sync_en_def = AR9340_INTR_SYNC_DEFAULT;
703         }
704
705         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE),
706             (sync_en_def | mask));
707         OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK),
708             (sync_en_def | mask));
709
710         HALDEBUG(ah,  HAL_DEBUG_INTERRUPT,
711             "AR_IMR 0x%x IER 0x%x\n",
712             OS_REG_READ(ah, AR_IMR), OS_REG_READ(ah, AR_IER));
713     }
714
715     return omask;
716 }
717
718 void
719 ar9300_set_intr_mitigation_timer(
720     struct ath_hal* ah,
721     HAL_INT_MITIGATION reg,
722     u_int32_t value)
723 {
724 #ifdef AR5416_INT_MITIGATION
725     switch (reg) {
726     case HAL_INT_THRESHOLD:
727         OS_REG_WRITE(ah, AR_MIRT, 0);
728         break;
729     case HAL_INT_RX_LASTPKT:
730         OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, value);
731         break;
732     case HAL_INT_RX_FIRSTPKT:
733         OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, value);
734         break;
735     case HAL_INT_TX_LASTPKT:
736         OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, value);
737         break;
738     case HAL_INT_TX_FIRSTPKT:
739         OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, value);
740         break;
741     default:
742         break;
743     }
744 #endif
745 }
746
747 u_int32_t
748 ar9300_get_intr_mitigation_timer(struct ath_hal* ah, HAL_INT_MITIGATION reg)
749 {
750     u_int32_t val = 0;
751 #ifdef AR5416_INT_MITIGATION
752     switch (reg) {
753     case HAL_INT_THRESHOLD:
754         val = OS_REG_READ(ah, AR_MIRT);
755         break;
756     case HAL_INT_RX_LASTPKT:
757         val = OS_REG_READ(ah, AR_RIMT) & 0xFFFF;
758         break;
759     case HAL_INT_RX_FIRSTPKT:
760         val = OS_REG_READ(ah, AR_RIMT) >> 16;
761         break;
762     case HAL_INT_TX_LASTPKT:
763         val = OS_REG_READ(ah, AR_TIMT) & 0xFFFF;
764         break;
765     case HAL_INT_TX_FIRSTPKT:
766         val = OS_REG_READ(ah, AR_TIMT) >> 16;
767         break;
768     default:
769         break;
770     }
771 #endif
772     return val;
773 }