Path: blob/main/sys/dev/ath/ath_hal/ar5212/ar5212_interrupts.c
39566 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2002-2008 Sam Leffler, Errno Consulting4* Copyright (c) 2002-2008 Atheros Communications, Inc.5*6* Permission to use, copy, modify, and/or distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF16* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/18#include "opt_ah.h"1920#include "ah.h"21#include "ah_internal.h"2223#include "ar5212/ar5212.h"24#include "ar5212/ar5212reg.h"25#include "ar5212/ar5212phy.h"2627/*28* Checks to see if an interrupt is pending on our NIC29*30* Returns: TRUE if an interrupt is pending31* FALSE if not32*/33HAL_BOOL34ar5212IsInterruptPending(struct ath_hal *ah)35{36/*37* Some platforms trigger our ISR before applying power to38* the card, so make sure the INTPEND is really 1, not 0xffffffff.39*/40return (OS_REG_READ(ah, AR_INTPEND) == AR_INTPEND_TRUE);41}4243/*44* Reads the Interrupt Status Register value from the NIC, thus deasserting45* the interrupt line, and returns both the masked and unmasked mapped ISR46* values. The value returned is mapped to abstract the hw-specific bit47* locations in the Interrupt Status Register.48*49* Returns: A hardware-abstracted bitmap of all non-masked-out50* interrupts pending, as well as an unmasked value51*/52HAL_BOOL53ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)54{55uint32_t isr, isr0, isr1;56uint32_t mask2;57struct ath_hal_5212 *ahp = AH5212(ah);5859isr = OS_REG_READ(ah, AR_ISR);60mask2 = 0;61if (isr & AR_ISR_BCNMISC) {62uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2);63if (isr2 & AR_ISR_S2_TIM)64mask2 |= HAL_INT_TIM;65if (isr2 & AR_ISR_S2_DTIM)66mask2 |= HAL_INT_DTIM;67if (isr2 & AR_ISR_S2_DTIMSYNC)68mask2 |= HAL_INT_DTIMSYNC;69if (isr2 & AR_ISR_S2_CABEND)70mask2 |= HAL_INT_CABEND;71if (isr2 & AR_ISR_S2_TBTT)72mask2 |= HAL_INT_TBTT;73}74isr = OS_REG_READ(ah, AR_ISR_RAC);75if (isr == 0xffffffff) {76*masked = 0;77return AH_FALSE;78}7980*masked = isr & HAL_INT_COMMON;8182if (isr & AR_ISR_HIUERR)83*masked |= HAL_INT_FATAL;84if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))85*masked |= HAL_INT_RX;86if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) {87*masked |= HAL_INT_TX;88isr0 = OS_REG_READ(ah, AR_ISR_S0_S);89ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK);90ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC);91isr1 = OS_REG_READ(ah, AR_ISR_S1_S);92ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR);93ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL);94}9596/*97* Receive overrun is usually non-fatal on Oahu/Spirit.98* BUT on some parts rx could fail and the chip must be reset.99* So we force a hardware reset in all cases.100*/101if ((isr & AR_ISR_RXORN) && AH_PRIVATE(ah)->ah_rxornIsFatal) {102HALDEBUG(ah, HAL_DEBUG_ANY,103"%s: receive FIFO overrun interrupt\n", __func__);104*masked |= HAL_INT_FATAL;105}106*masked |= mask2;107108/*109* On fatal errors collect ISR state for debugging.110*/111if (*masked & HAL_INT_FATAL) {112AH_PRIVATE(ah)->ah_fatalState[0] = isr;113AH_PRIVATE(ah)->ah_fatalState[1] = OS_REG_READ(ah, AR_ISR_S0_S);114AH_PRIVATE(ah)->ah_fatalState[2] = OS_REG_READ(ah, AR_ISR_S1_S);115AH_PRIVATE(ah)->ah_fatalState[3] = OS_REG_READ(ah, AR_ISR_S2_S);116AH_PRIVATE(ah)->ah_fatalState[4] = OS_REG_READ(ah, AR_ISR_S3_S);117AH_PRIVATE(ah)->ah_fatalState[5] = OS_REG_READ(ah, AR_ISR_S4_S);118HALDEBUG(ah, HAL_DEBUG_ANY,119"%s: fatal error, ISR_RAC=0x%x ISR_S2_S=0x%x\n",120__func__, isr, AH_PRIVATE(ah)->ah_fatalState[3]);121}122return AH_TRUE;123}124125HAL_INT126ar5212GetInterrupts(struct ath_hal *ah)127{128return AH5212(ah)->ah_maskReg;129}130131/*132* Atomically enables NIC interrupts. Interrupts are passed in133* via the enumerated bitmask in ints.134*/135HAL_INT136ar5212SetInterrupts(struct ath_hal *ah, HAL_INT ints)137{138struct ath_hal_5212 *ahp = AH5212(ah);139uint32_t omask = ahp->ah_maskReg;140uint32_t mask, mask2;141142HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",143__func__, omask, ints);144145if (omask & HAL_INT_GLOBAL) {146HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);147OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);148(void) OS_REG_READ(ah, AR_IER); /* flush write to HW */149}150151mask = ints & HAL_INT_COMMON;152mask2 = 0;153if (ints & HAL_INT_TX) {154if (ahp->ah_txOkInterruptMask)155mask |= AR_IMR_TXOK;156if (ahp->ah_txErrInterruptMask)157mask |= AR_IMR_TXERR;158if (ahp->ah_txDescInterruptMask)159mask |= AR_IMR_TXDESC;160if (ahp->ah_txEolInterruptMask)161mask |= AR_IMR_TXEOL;162}163if (ints & HAL_INT_RX)164mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC;165if (ints & (HAL_INT_BMISC)) {166mask |= AR_IMR_BCNMISC;167if (ints & HAL_INT_TIM)168mask2 |= AR_IMR_S2_TIM;169if (ints & HAL_INT_DTIM)170mask2 |= AR_IMR_S2_DTIM;171if (ints & HAL_INT_DTIMSYNC)172mask2 |= AR_IMR_S2_DTIMSYNC;173if (ints & HAL_INT_CABEND)174mask2 |= AR_IMR_S2_CABEND;175if (ints & HAL_INT_TBTT)176mask2 |= AR_IMR_S2_TBTT;177}178if (ints & HAL_INT_FATAL) {179/*180* NB: ar5212Reset sets MCABT+SSERR+DPERR in AR_IMR_S2181* so enabling HIUERR enables delivery.182*/183mask |= AR_IMR_HIUERR;184}185186/* Write the new IMR and store off our SW copy. */187HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);188OS_REG_WRITE(ah, AR_IMR, mask);189OS_REG_WRITE(ah, AR_IMR_S2,190(OS_REG_READ(ah, AR_IMR_S2) &~ AR_IMR_SR2_BCNMISC) | mask2);191ahp->ah_maskReg = ints;192193/* Re-enable interrupts if they were enabled before. */194if (ints & HAL_INT_GLOBAL) {195HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);196OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);197}198return omask;199}200201202