Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c
48526 views
/*1* Copyright (c) 2013 Qualcomm Atheros, Inc.2*3* Permission to use, copy, modify, and/or distribute this software for any4* purpose with or without fee is hereby granted, provided that the above5* copyright notice and this permission notice appear in all copies.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH8* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY9* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,10* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM11* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR12* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR13* PERFORMANCE OF THIS SOFTWARE.14*/1516#include "opt_ah.h"1718#include "ah.h"19#include "ah_internal.h"2021#include "ar9300/ar9300.h"22#include "ar9300/ar9300reg.h"23#include "ar9300/ar9300phy.h"2425/*26* Checks to see if an interrupt is pending on our NIC27*28* Returns: TRUE if an interrupt is pending29* FALSE if not30*/31HAL_BOOL32ar9300_is_interrupt_pending(struct ath_hal *ah)33{34u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;35u_int32_t host_isr;3637/*38* Some platforms trigger our ISR before applying power to39* the card, so make sure.40*/41host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));42if ((host_isr & AR_INTR_ASYNC_USED) && (host_isr != AR_INTR_SPURIOUS)) {43return AH_TRUE;44}4546host_isr = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));47if (AR_SREV_POSEIDON(ah)) {48sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;49}50else if (AR_SREV_WASP(ah)) {51sync_en_def = AR9340_INTR_SYNC_DEFAULT;52}5354if ((host_isr & (sync_en_def | AR_INTR_SYNC_MASK_GPIO)) &&55(host_isr != AR_INTR_SPURIOUS)) {56return AH_TRUE;57}5859return AH_FALSE;60}6162/*63* Reads the Interrupt Status Register value from the NIC, thus deasserting64* the interrupt line, and returns both the masked and unmasked mapped ISR65* values. The value returned is mapped to abstract the hw-specific bit66* locations in the Interrupt Status Register.67*68* Returns: A hardware-abstracted bitmap of all non-masked-out69* interrupts pending, as well as an unmasked value70*/71#define MAP_ISR_S2_HAL_CST 6 /* Carrier sense timeout */72#define MAP_ISR_S2_HAL_GTT 6 /* Global transmit timeout */73#define MAP_ISR_S2_HAL_TIM 3 /* TIM */74#define MAP_ISR_S2_HAL_CABEND 0 /* CABEND */75#define MAP_ISR_S2_HAL_DTIMSYNC 7 /* DTIMSYNC */76#define MAP_ISR_S2_HAL_DTIM 7 /* DTIM */77#define MAP_ISR_S2_HAL_TSFOOR 4 /* Rx TSF out of range */78#define MAP_ISR_S2_HAL_BBPANIC 6 /* Panic watchdog IRQ from BB */79HAL_BOOL80ar9300_get_pending_interrupts(81struct ath_hal *ah,82HAL_INT *masked,83HAL_INT_TYPE type,84u_int8_t msi,85HAL_BOOL nortc)86{87struct ath_hal_9300 *ahp = AH9300(ah);88HAL_BOOL ret_val = AH_TRUE;89u_int32_t isr = 0;90u_int32_t mask2 = 0;91u_int32_t sync_cause = 0;92u_int32_t async_cause;93u_int32_t msi_pend_addr_mask = 0;94u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;95HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;9697*masked = 0;9899if (!nortc) {100if (HAL_INT_MSI == type) {101if (msi == HAL_MSIVEC_RXHP) {102OS_REG_WRITE(ah, AR_ISR, AR_ISR_HP_RXOK);103*masked = HAL_INT_RXHP;104goto end;105} else if (msi == HAL_MSIVEC_RXLP) {106OS_REG_WRITE(ah, AR_ISR,107(AR_ISR_LP_RXOK | AR_ISR_RXMINTR | AR_ISR_RXINTM));108*masked = HAL_INT_RXLP;109goto end;110} else if (msi == HAL_MSIVEC_TX) {111OS_REG_WRITE(ah, AR_ISR, AR_ISR_TXOK);112*masked = HAL_INT_TX;113goto end;114} else if (msi == HAL_MSIVEC_MISC) {115/*116* For the misc MSI event fall through and determine the cause.117*/118}119}120}121122/* Make sure mac interrupt is pending in async interrupt cause register */123async_cause = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE));124if (async_cause & AR_INTR_ASYNC_USED) {125/*126* RTC may not be on since it runs on a slow 32khz clock127* so check its status to be sure128*/129if (!nortc &&130(OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==131AR_RTC_STATUS_ON)132{133isr = OS_REG_READ(ah, AR_ISR);134}135}136137if (AR_SREV_POSEIDON(ah)) {138sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;139}140else if (AR_SREV_WASP(ah)) {141sync_en_def = AR9340_INTR_SYNC_DEFAULT;142}143144/* Store away the async and sync cause registers */145/* XXX Do this before the filtering done below */146#ifdef AH_INTERRUPT_DEBUGGING147ah->ah_intrstate[0] = OS_REG_READ(ah, AR_ISR);148ah->ah_intrstate[1] = OS_REG_READ(ah, AR_ISR_S0);149ah->ah_intrstate[2] = OS_REG_READ(ah, AR_ISR_S1);150ah->ah_intrstate[3] = OS_REG_READ(ah, AR_ISR_S2);151ah->ah_intrstate[4] = OS_REG_READ(ah, AR_ISR_S3);152ah->ah_intrstate[5] = OS_REG_READ(ah, AR_ISR_S4);153ah->ah_intrstate[6] = OS_REG_READ(ah, AR_ISR_S5);154155/* XXX double reading? */156ah->ah_syncstate = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE));157#endif158159sync_cause =160OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE)) &161(sync_en_def | AR_INTR_SYNC_MASK_GPIO);162163if (!isr && !sync_cause && !async_cause) {164ret_val = AH_FALSE;165goto end;166}167168HALDEBUG(ah, HAL_DEBUG_INTERRUPT,169"%s: isr=0x%x, sync_cause=0x%x, async_cause=0x%x\n",170__func__,171isr,172sync_cause,173async_cause);174175if (isr) {176if (isr & AR_ISR_BCNMISC) {177u_int32_t isr2;178isr2 = OS_REG_READ(ah, AR_ISR_S2);179180/* Translate ISR bits to HAL values */181mask2 |= ((isr2 & AR_ISR_S2_TIM) >> MAP_ISR_S2_HAL_TIM);182mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> MAP_ISR_S2_HAL_DTIM);183mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> MAP_ISR_S2_HAL_DTIMSYNC);184mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> MAP_ISR_S2_HAL_CABEND);185mask2 |= ((isr2 & AR_ISR_S2_GTT) << MAP_ISR_S2_HAL_GTT);186mask2 |= ((isr2 & AR_ISR_S2_CST) << MAP_ISR_S2_HAL_CST);187mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> MAP_ISR_S2_HAL_TSFOOR);188mask2 |= ((isr2 & AR_ISR_S2_BBPANIC) >> MAP_ISR_S2_HAL_BBPANIC);189190if (!p_cap->halIsrRacSupport) {191/*192* EV61133 (missing interrupts due to ISR_RAC):193* If not using ISR_RAC, clear interrupts by writing to ISR_S2.194* This avoids a race condition where a new BCNMISC interrupt195* could come in between reading the ISR and clearing the196* interrupt via the primary ISR. We therefore clear the197* interrupt via the secondary, which avoids this race.198*/199OS_REG_WRITE(ah, AR_ISR_S2, isr2);200isr &= ~AR_ISR_BCNMISC;201}202}203204/* Use AR_ISR_RAC only if chip supports it.205* See EV61133 (missing interrupts due to ISR_RAC)206*/207if (p_cap->halIsrRacSupport) {208isr = OS_REG_READ(ah, AR_ISR_RAC);209}210if (isr == 0xffffffff) {211*masked = 0;212ret_val = AH_FALSE;213goto end;214}215216*masked = isr & HAL_INT_COMMON;217218/*219* When interrupt mitigation is switched on, we fake a normal RX or TX220* interrupt when we received a mitigated interrupt. This way, the upper221* layer do not need to know about feature.222*/223if (ahp->ah_intr_mitigation_rx) {224/* Only Rx interrupt mitigation. No Tx intr. mitigation. */225if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) {226*masked |= HAL_INT_RXLP;227}228}229if (ahp->ah_intr_mitigation_tx) {230if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) {231*masked |= HAL_INT_TX;232}233}234235if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) {236*masked |= HAL_INT_RXLP;237}238if (isr & AR_ISR_HP_RXOK) {239*masked |= HAL_INT_RXHP;240}241if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {242*masked |= HAL_INT_TX;243244if (!p_cap->halIsrRacSupport) {245u_int32_t s0, s1;246/*247* EV61133 (missing interrupts due to ISR_RAC):248* If not using ISR_RAC, clear interrupts by writing to249* ISR_S0/S1.250* This avoids a race condition where a new interrupt251* could come in between reading the ISR and clearing the252* interrupt via the primary ISR. We therefore clear the253* interrupt via the secondary, which avoids this race.254*/255s0 = OS_REG_READ(ah, AR_ISR_S0);256OS_REG_WRITE(ah, AR_ISR_S0, s0);257s1 = OS_REG_READ(ah, AR_ISR_S1);258OS_REG_WRITE(ah, AR_ISR_S1, s1);259260isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL);261}262}263264/*265* Do not treat receive overflows as fatal for owl.266*/267if (isr & AR_ISR_RXORN) {268#if __PKT_SERIOUS_ERRORS__269HALDEBUG(ah, HAL_DEBUG_INTERRUPT,270"%s: receive FIFO overrun interrupt\n", __func__);271#endif272}273274#if 0275/* XXX Verify if this is fixed for Osprey */276if (!p_cap->halAutoSleepSupport) {277u_int32_t isr5 = OS_REG_READ(ah, AR_ISR_S5_S);278if (isr5 & AR_ISR_S5_TIM_TIMER) {279*masked |= HAL_INT_TIM_TIMER;280}281}282#endif283if (isr & AR_ISR_GENTMR) {284u_int32_t s5;285286if (p_cap->halIsrRacSupport) {287/* Use secondary shadow registers if using ISR_RAC */288s5 = OS_REG_READ(ah, AR_ISR_S5_S);289} else {290s5 = OS_REG_READ(ah, AR_ISR_S5);291}292if (isr & AR_ISR_GENTMR) {293294HALDEBUG(ah, HAL_DEBUG_INTERRUPT,295"%s: GENTIMER, ISR_RAC=0x%x ISR_S2_S=0x%x\n", __func__,296isr, s5);297ahp->ah_intr_gen_timer_trigger =298MS(s5, AR_ISR_S5_GENTIMER_TRIG);299ahp->ah_intr_gen_timer_thresh =300MS(s5, AR_ISR_S5_GENTIMER_THRESH);301if (ahp->ah_intr_gen_timer_trigger) {302*masked |= HAL_INT_GENTIMER;303}304}305if (!p_cap->halIsrRacSupport) {306/*307* EV61133 (missing interrupts due to ISR_RAC):308* If not using ISR_RAC, clear interrupts by writing to ISR_S5.309* This avoids a race condition where a new interrupt310* could come in between reading the ISR and clearing the311* interrupt via the primary ISR. We therefore clear the312* interrupt via the secondary, which avoids this race.313*/314OS_REG_WRITE(ah, AR_ISR_S5, s5);315isr &= ~AR_ISR_GENTMR;316}317}318319*masked |= mask2;320321if (!p_cap->halIsrRacSupport) {322/*323* EV61133 (missing interrupts due to ISR_RAC):324* If not using ISR_RAC, clear the interrupts we've read by325* writing back ones in these locations to the primary ISR326* (except for interrupts that have a secondary isr register -327* see above).328*/329OS_REG_WRITE(ah, AR_ISR, isr);330331/* Flush prior write */332(void) OS_REG_READ(ah, AR_ISR);333}334335#ifdef AH_SUPPORT_AR9300336if (*masked & HAL_INT_BBPANIC) {337ar9300_handle_bb_panic(ah);338}339#endif340}341342if (async_cause) {343if (nortc) {344OS_REG_WRITE(ah,345AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR), async_cause);346/* Flush prior write */347(void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_CAUSE_CLR));348} else {349#ifdef ATH_GPIO_USE_ASYNC_CAUSE350if (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) {351ahp->ah_gpio_cause = (async_cause & AR_INTR_ASYNC_CAUSE_GPIO) >>352AR_INTR_ASYNC_ENABLE_GPIO_S;353*masked |= HAL_INT_GPIO;354}355#endif356}357358#if ATH_SUPPORT_MCI359if ((async_cause & AR_INTR_ASYNC_CAUSE_MCI) &&360p_cap->halMciSupport)361{362u_int32_t int_raw, int_rx_msg;363364int_rx_msg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);365int_raw = OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW);366367if ((int_raw == 0xdeadbeef) || (int_rx_msg == 0xdeadbeef))368{369HALDEBUG(ah, HAL_DEBUG_BT_COEX,370"(MCI) Get 0xdeadbeef during MCI int processing"371"new int_raw=0x%08x, new rx_msg_raw=0x%08x, "372"int_raw=0x%08x, rx_msg_raw=0x%08x\n",373int_raw, int_rx_msg, ahp->ah_mci_int_raw,374ahp->ah_mci_int_rx_msg);375}376else {377if (ahp->ah_mci_int_raw || ahp->ah_mci_int_rx_msg) {378ahp->ah_mci_int_rx_msg |= int_rx_msg;379ahp->ah_mci_int_raw |= int_raw;380}381else {382ahp->ah_mci_int_rx_msg = int_rx_msg;383ahp->ah_mci_int_raw = int_raw;384}385386*masked |= HAL_INT_MCI;387ahp->ah_mci_rx_status = OS_REG_READ(ah, AR_MCI_RX_STATUS);388if (int_rx_msg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) {389ahp->ah_mci_cont_status =390OS_REG_READ(ah, AR_MCI_CONT_STATUS);391HALDEBUG(ah, HAL_DEBUG_BT_COEX,392"(MCI) cont_status=0x%08x\n", ahp->ah_mci_cont_status);393}394OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,395int_rx_msg);396OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, int_raw);397398HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s:AR_INTR_SYNC_MCI\n", __func__);399}400}401#endif402}403404if (sync_cause) {405int host1_fatal, host1_perr, radm_cpl_timeout, local_timeout;406407host1_fatal = AR_SREV_WASP(ah) ?408AR9340_INTR_SYNC_HOST1_FATAL : AR9300_INTR_SYNC_HOST1_FATAL;409host1_perr = AR_SREV_WASP(ah) ?410AR9340_INTR_SYNC_HOST1_PERR : AR9300_INTR_SYNC_HOST1_PERR;411radm_cpl_timeout = AR_SREV_WASP(ah) ?4120x0 : AR9300_INTR_SYNC_RADM_CPL_TIMEOUT;413local_timeout = AR_SREV_WASP(ah) ?414AR9340_INTR_SYNC_LOCAL_TIMEOUT : AR9300_INTR_SYNC_LOCAL_TIMEOUT;415416if (sync_cause & host1_fatal) {417#if __PKT_SERIOUS_ERRORS__418HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,419"%s: received PCI FATAL interrupt\n", __func__);420#endif421*masked |= HAL_INT_FATAL; /* Set FATAL INT flag here;*/422}423if (sync_cause & host1_perr) {424#if __PKT_SERIOUS_ERRORS__425HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,426"%s: received PCI PERR interrupt\n", __func__);427#endif428}429430if (sync_cause & radm_cpl_timeout) {431HALDEBUG(ah, HAL_DEBUG_INTERRUPT,432"%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",433__func__);434435OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), AR_RC_HOSTIF);436OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_RC), 0);437*masked |= HAL_INT_FATAL;438}439if (sync_cause & local_timeout) {440HALDEBUG(ah, HAL_DEBUG_INTERRUPT,441"%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",442__func__);443}444445#ifndef ATH_GPIO_USE_ASYNC_CAUSE446if (sync_cause & AR_INTR_SYNC_MASK_GPIO) {447ahp->ah_gpio_cause = (sync_cause & AR_INTR_SYNC_MASK_GPIO) >>448AR_INTR_SYNC_ENABLE_GPIO_S;449*masked |= HAL_INT_GPIO;450HALDEBUG(ah, HAL_DEBUG_INTERRUPT,451"%s: AR_INTR_SYNC_GPIO\n", __func__);452}453#endif454455OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR), sync_cause);456/* Flush prior write */457(void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_CAUSE_CLR));458}459460end:461if (HAL_INT_MSI == type) {462/*463* WAR for Bug EV#75887464* In normal case, SW read HOST_INTF_PCIE_MSI (0x40A4) and write465* into ah_msi_reg. Then use value of ah_msi_reg to set bit#25466* when want to enable HW write the cfg_msi_pending.467* Sometimes, driver get MSI interrupt before read 0x40a4 and468* ah_msi_reg is initialization value (0x0).469* We don't know why "MSI interrupt earlier than driver read" now...470*/471if (!ahp->ah_msi_reg) {472ahp->ah_msi_reg = OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI));473}474if (AR_SREV_POSEIDON(ah)) {475msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;476} else {477msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;478}479OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),480((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));481482}483484return ret_val;485}486487HAL_INT488ar9300_get_interrupts(struct ath_hal *ah)489{490return AH9300(ah)->ah_mask_reg;491}492493/*494* Atomically enables NIC interrupts. Interrupts are passed in495* via the enumerated bitmask in ints.496*/497HAL_INT498ar9300_set_interrupts(struct ath_hal *ah, HAL_INT ints, HAL_BOOL nortc)499{500struct ath_hal_9300 *ahp = AH9300(ah);501u_int32_t omask = ahp->ah_mask_reg;502u_int32_t mask, mask2, msi_mask = 0;503u_int32_t msi_pend_addr_mask = 0;504u_int32_t sync_en_def = AR9300_INTR_SYNC_DEFAULT;505HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps;506507HALDEBUG(ah, HAL_DEBUG_INTERRUPT,508"%s: 0x%x => 0x%x\n", __func__, omask, ints);509510if (omask & HAL_INT_GLOBAL) {511HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);512513if (ah->ah_config.ath_hal_enable_msi) {514OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE), 0);515/* flush write to HW */516(void)OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE));517}518519if (!nortc) {520OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);521(void) OS_REG_READ(ah, AR_IER); /* flush write to HW */522}523524OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE), 0);525/* flush write to HW */526(void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE));527OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), 0);528/* flush write to HW */529(void) OS_REG_READ(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE));530}531532if (!nortc) {533/* reference count for global IER */534if (ints & HAL_INT_GLOBAL) {535#ifdef AH_DEBUG536HALDEBUG(ah, HAL_DEBUG_INTERRUPT,537"%s: Request HAL_INT_GLOBAL ENABLED\n", __func__);538#if 0539if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0) {540HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,541"%s: WARNING: ah_ier_ref_count is 0 "542"and attempting to enable IER\n",543__func__);544}545#endif546#endif547#if 0548if (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) > 0) {549OS_ATOMIC_DEC(&ahp->ah_ier_ref_count);550}551#endif552} else {553HALDEBUG(ah, HAL_DEBUG_INTERRUPT,554"%s: Request HAL_INT_GLOBAL DISABLED\n", __func__);555OS_ATOMIC_INC(&ahp->ah_ier_ref_count);556}557HALDEBUG(ah, HAL_DEBUG_INTERRUPT,558"%s: ah_ier_ref_count = %d\n", __func__, ahp->ah_ier_ref_count);559560mask = ints & HAL_INT_COMMON;561mask2 = 0;562msi_mask = 0;563564if (ints & HAL_INT_TX) {565if (ahp->ah_intr_mitigation_tx) {566mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;567} else if (ahp->ah_tx_ok_interrupt_mask) {568mask |= AR_IMR_TXOK;569}570msi_mask |= AR_INTR_PRIO_TX;571if (ahp->ah_tx_err_interrupt_mask) {572mask |= AR_IMR_TXERR;573}574if (ahp->ah_tx_eol_interrupt_mask) {575mask |= AR_IMR_TXEOL;576}577}578if (ints & HAL_INT_RX) {579mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;580if (ahp->ah_intr_mitigation_rx) {581mask &= ~(AR_IMR_RXOK_LP);582mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;583} else {584mask |= AR_IMR_RXOK_LP;585}586msi_mask |= AR_INTR_PRIO_RXLP | AR_INTR_PRIO_RXHP;587if (! p_cap->halAutoSleepSupport) {588mask |= AR_IMR_GENTMR;589}590}591592if (ints & (HAL_INT_BMISC)) {593mask |= AR_IMR_BCNMISC;594if (ints & HAL_INT_TIM) {595mask2 |= AR_IMR_S2_TIM;596}597if (ints & HAL_INT_DTIM) {598mask2 |= AR_IMR_S2_DTIM;599}600if (ints & HAL_INT_DTIMSYNC) {601mask2 |= AR_IMR_S2_DTIMSYNC;602}603if (ints & HAL_INT_CABEND) {604mask2 |= (AR_IMR_S2_CABEND);605}606if (ints & HAL_INT_TSFOOR) {607mask2 |= AR_IMR_S2_TSFOOR;608}609}610611if (ints & (HAL_INT_GTT | HAL_INT_CST)) {612mask |= AR_IMR_BCNMISC;613if (ints & HAL_INT_GTT) {614mask2 |= AR_IMR_S2_GTT;615}616if (ints & HAL_INT_CST) {617mask2 |= AR_IMR_S2_CST;618}619}620621if (ints & HAL_INT_BBPANIC) {622/* EV92527 - MAC secondary interrupt must enable AR_IMR_BCNMISC */623mask |= AR_IMR_BCNMISC;624mask2 |= AR_IMR_S2_BBPANIC;625}626627if (ints & HAL_INT_GENTIMER) {628HALDEBUG(ah, HAL_DEBUG_INTERRUPT,629"%s: enabling gen timer\n", __func__);630mask |= AR_IMR_GENTMR;631}632633/* Write the new IMR and store off our SW copy. */634HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);635OS_REG_WRITE(ah, AR_IMR, mask);636ahp->ah_mask2Reg &= ~(AR_IMR_S2_TIM |637AR_IMR_S2_DTIM |638AR_IMR_S2_DTIMSYNC |639AR_IMR_S2_CABEND |640AR_IMR_S2_CABTO |641AR_IMR_S2_TSFOOR |642AR_IMR_S2_GTT |643AR_IMR_S2_CST |644AR_IMR_S2_BBPANIC);645ahp->ah_mask2Reg |= mask2;646OS_REG_WRITE(ah, AR_IMR_S2, ahp->ah_mask2Reg );647ahp->ah_mask_reg = ints;648649if (! p_cap->halAutoSleepSupport) {650if (ints & HAL_INT_TIM_TIMER) {651OS_REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);652}653else {654OS_REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);655}656}657}658659/* Re-enable interrupts if they were enabled before. */660#if HAL_INTR_REFCOUNT_DISABLE661if ((ints & HAL_INT_GLOBAL)) {662#else663if ((ints & HAL_INT_GLOBAL) && (OS_ATOMIC_READ(&ahp->ah_ier_ref_count) == 0)) {664#endif665HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);666667if (!nortc) {668OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);669}670671mask = AR_INTR_MAC_IRQ;672#ifdef ATH_GPIO_USE_ASYNC_CAUSE673if (ints & HAL_INT_GPIO) {674if (ahp->ah_gpio_mask) {675mask |= SM(ahp->ah_gpio_mask, AR_INTR_ASYNC_MASK_GPIO);676}677}678#endif679680#if ATH_SUPPORT_MCI681if (ints & HAL_INT_MCI) {682mask |= AR_INTR_ASYNC_MASK_MCI;683}684#endif685686OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_ENABLE), mask);687OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_ASYNC_MASK), mask);688689if (ah->ah_config.ath_hal_enable_msi) {690OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_ENABLE),691msi_mask);692OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_PRIO_ASYNC_MASK),693msi_mask);694if (AR_SREV_POSEIDON(ah)) {695msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;696} else {697msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR;698}699OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_PCIE_MSI),700((ahp->ah_msi_reg | AR_PCIE_MSI_ENABLE) & msi_pend_addr_mask));701}702703/*704* debug - enable to see all synchronous interrupts status705* Enable synchronous GPIO interrupts as well, since some async706* GPIO interrupts don't wake the chip up.707*/708mask = 0;709#ifndef ATH_GPIO_USE_ASYNC_CAUSE710if (ints & HAL_INT_GPIO) {711mask |= SM(ahp->ah_gpio_mask, AR_INTR_SYNC_MASK_GPIO);712}713#endif714if (AR_SREV_POSEIDON(ah)) {715sync_en_def = AR9300_INTR_SYNC_DEF_NO_HOST1_PERR;716}717else if (AR_SREV_WASP(ah)) {718sync_en_def = AR9340_INTR_SYNC_DEFAULT;719}720721OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_ENABLE),722(sync_en_def | mask));723OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_INTR_SYNC_MASK),724(sync_en_def | mask));725726HALDEBUG(ah, HAL_DEBUG_INTERRUPT,727"AR_IMR 0x%x IER 0x%x\n",728OS_REG_READ(ah, AR_IMR), OS_REG_READ(ah, AR_IER));729}730731return omask;732}733734void735ar9300_set_intr_mitigation_timer(736struct ath_hal* ah,737HAL_INT_MITIGATION reg,738u_int32_t value)739{740#ifdef AR5416_INT_MITIGATION741switch (reg) {742case HAL_INT_THRESHOLD:743OS_REG_WRITE(ah, AR_MIRT, 0);744break;745case HAL_INT_RX_LASTPKT:746OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, value);747break;748case HAL_INT_RX_FIRSTPKT:749OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, value);750break;751case HAL_INT_TX_LASTPKT:752OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, value);753break;754case HAL_INT_TX_FIRSTPKT:755OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, value);756break;757default:758break;759}760#endif761}762763u_int32_t764ar9300_get_intr_mitigation_timer(struct ath_hal* ah, HAL_INT_MITIGATION reg)765{766u_int32_t val = 0;767#ifdef AR5416_INT_MITIGATION768switch (reg) {769case HAL_INT_THRESHOLD:770val = OS_REG_READ(ah, AR_MIRT);771break;772case HAL_INT_RX_LASTPKT:773val = OS_REG_READ(ah, AR_RIMT) & 0xFFFF;774break;775case HAL_INT_RX_FIRSTPKT:776val = OS_REG_READ(ah, AR_RIMT) >> 16;777break;778case HAL_INT_TX_LASTPKT:779val = OS_REG_READ(ah, AR_TIMT) & 0xFFFF;780break;781case HAL_INT_TX_FIRSTPKT:782val = OS_REG_READ(ah, AR_TIMT) >> 16;783break;784default:785break;786}787#endif788return val;789}790791792