The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2008 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  *
   19  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 
   26 #include "ar5212/ar5212.h"
   27 #include "ar5212/ar5212reg.h"
   28 #include "ar5212/ar5212phy.h"
   29 
   30 /*
   31  * Checks to see if an interrupt is pending on our NIC
   32  *
   33  * Returns: TRUE    if an interrupt is pending
   34  *          FALSE   if not
   35  */
   36 HAL_BOOL
   37 ar5212IsInterruptPending(struct ath_hal *ah)
   38 {
   39         /* 
   40          * Some platforms trigger our ISR before applying power to
   41          * the card, so make sure the INTPEND is really 1, not 0xffffffff.
   42          */
   43         return (OS_REG_READ(ah, AR_INTPEND) == AR_INTPEND_TRUE);
   44 }
   45 
   46 /*
   47  * Reads the Interrupt Status Register value from the NIC, thus deasserting
   48  * the interrupt line, and returns both the masked and unmasked mapped ISR
   49  * values.  The value returned is mapped to abstract the hw-specific bit
   50  * locations in the Interrupt Status Register.
   51  *
   52  * Returns: A hardware-abstracted bitmap of all non-masked-out
   53  *          interrupts pending, as well as an unmasked value
   54  */
   55 HAL_BOOL
   56 ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)
   57 {
   58         uint32_t isr, isr0, isr1;
   59         uint32_t mask2;
   60         struct ath_hal_5212 *ahp = AH5212(ah);
   61 
   62         isr = OS_REG_READ(ah, AR_ISR);
   63         mask2 = 0;
   64         if (isr & AR_ISR_BCNMISC) {
   65                 uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2);
   66                 if (isr2 & AR_ISR_S2_TIM)
   67                         mask2 |= HAL_INT_TIM;
   68                 if (isr2 & AR_ISR_S2_DTIM)
   69                         mask2 |= HAL_INT_DTIM;
   70                 if (isr2 & AR_ISR_S2_DTIMSYNC)
   71                         mask2 |= HAL_INT_DTIMSYNC;
   72                 if (isr2 & AR_ISR_S2_CABEND)
   73                         mask2 |= HAL_INT_CABEND;
   74                 if (isr2 & AR_ISR_S2_TBTT)
   75                         mask2 |= HAL_INT_TBTT;
   76         }
   77         isr = OS_REG_READ(ah, AR_ISR_RAC);
   78         if (isr == 0xffffffff) {
   79                 *masked = 0;
   80                 return AH_FALSE;
   81         }
   82 
   83         *masked = isr & HAL_INT_COMMON;
   84 
   85         if (isr & AR_ISR_HIUERR)
   86                 *masked |= HAL_INT_FATAL;
   87         if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
   88                 *masked |= HAL_INT_RX;
   89         if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) {
   90                 *masked |= HAL_INT_TX;
   91                 isr0 = OS_REG_READ(ah, AR_ISR_S0_S);
   92                 ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK);
   93                 ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC);
   94                 isr1 = OS_REG_READ(ah, AR_ISR_S1_S);
   95                 ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR);
   96                 ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL);
   97         }
   98 
   99         /*
  100          * Receive overrun is usually non-fatal on Oahu/Spirit.
  101          * BUT on some parts rx could fail and the chip must be reset.
  102          * So we force a hardware reset in all cases.
  103          */
  104         if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) {
  105                 HALDEBUG(ah, HAL_DEBUG_ANY,
  106                     "%s: receive FIFO overrun interrupt\n", __func__);
  107                 *masked |= HAL_INT_FATAL;
  108         }
  109         *masked |= mask2;
  110 
  111         /*
  112          * On fatal errors collect ISR state for debugging.
  113          */
  114         if (*masked & HAL_INT_FATAL) {
  115                 AH_PRIVATE(ah)->ah_fatalState[0] = isr;
  116                 AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S);
  117                 AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S);
  118                 AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S);
  119                 AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S);
  120                 AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S);
  121                 HALDEBUG(ah, HAL_DEBUG_ANY,
  122                     "%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n",
  123                     __func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]);
  124         }
  125         return AH_TRUE;
  126 }
  127 
  128 HAL_INT
  129 ar5212GetInterrupts(struct ath_hal *ah)
  130 {
  131         return AH5212(ah)->ah_maskReg;
  132 }
  133 
  134 /*
  135  * Atomically enables NIC interrupts.  Interrupts are passed in
  136  * via the enumerated bitmask in ints.
  137  */
  138 HAL_INT
  139 ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints)
  140 {
  141         struct ath_hal_5212 *ahp = AH5212(ah);
  142         uint32_t omask = ahp->ah_maskReg;
  143         uint32_t mask, mask2;
  144 
  145         HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",
  146             __func__, omask, ints);
  147 
  148         if (omask & HAL_INT_GLOBAL) {
  149                 HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
  150                 OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
  151                 (void) OS_REG_READ(ah, AR_IER);   /* flush write to HW */
  152         }
  153 
  154         mask = ints & HAL_INT_COMMON;
  155         mask2 = 0;
  156         if (ints & HAL_INT_TX) {
  157                 if (ahp->ah_txOkInterruptMask)
  158                         mask |= AR_IMR_TXOK;
  159                 if (ahp->ah_txErrInterruptMask)
  160                         mask |= AR_IMR_TXERR;
  161                 if (ahp->ah_txDescInterruptMask)
  162                         mask |= AR_IMR_TXDESC;
  163                 if (ahp->ah_txEolInterruptMask)
  164                         mask |= AR_IMR_TXEOL;
  165         }
  166         if (ints & HAL_INT_RX)
  167                 mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC;
  168         if (ints & (HAL_INT_BMISC)) {
  169                 mask |= AR_IMR_BCNMISC;
  170                 if (ints & HAL_INT_TIM)
  171                         mask2 |= AR_IMR_S2_TIM;
  172                 if (ints & HAL_INT_DTIM)
  173                         mask2 |= AR_IMR_S2_DTIM;
  174                 if (ints & HAL_INT_DTIMSYNC)
  175                         mask2 |= AR_IMR_S2_DTIMSYNC;
  176                 if (ints & HAL_INT_CABEND)
  177                         mask2 |= AR_IMR_S2_CABEND;
  178                 if (ints & HAL_INT_TBTT)
  179                         mask2 |= AR_IMR_S2_TBTT;
  180         }
  181         if (ints & HAL_INT_FATAL) {
  182                 /*
  183                  * NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2
  184                  *     so enabling HIUERR enables delivery.
  185                  */
  186                 mask |= AR_IMR_HIUERR;
  187         }
  188 
  189         /* Write the new IMR and store off our SW copy. */
  190         HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
  191         OS_REG_WRITE(ah, AR_IMR, mask);
  192         OS_REG_WRITE(ah, AR_IMR_S2,
  193             (OS_REG_READ(ah, AR_IMR_S2) &~ AR_IMR_SR2_BCNMISC) | mask2);
  194         ahp->ah_maskReg = ints;
  195 
  196         /* Re-enable interrupts if they were enabled before. */
  197         if (ints & HAL_INT_GLOBAL) {
  198                 HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
  199                 OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
  200         }
  201         return omask;
  202 }

Cache object: e82b24a460c631ae7a536a08997d799b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.