162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2010-2011 Atheros Communications Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci#include <linux/export.h> 1762306a36Sopenharmony_ci#include "hw.h" 1862306a36Sopenharmony_ci#include "ar9003_mac.h" 1962306a36Sopenharmony_ci#include "ar9003_mci.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic void ar9003_hw_rx_enable(struct ath_hw *hw) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci REG_WRITE(hw, AR_CR, 0); 2462306a36Sopenharmony_ci} 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic void 2762306a36Sopenharmony_ciar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct ar9003_txc *ads = ds; 3062306a36Sopenharmony_ci int checksum = 0; 3162306a36Sopenharmony_ci u32 val, ctl12, ctl17; 3262306a36Sopenharmony_ci u8 desc_len; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci desc_len = ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x18 : 0x17); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci val = (ATHEROS_VENDOR_ID << AR_DescId_S) | 3762306a36Sopenharmony_ci (1 << AR_TxRxDesc_S) | 3862306a36Sopenharmony_ci (1 << AR_CtrlStat_S) | 3962306a36Sopenharmony_ci (i->qcu << AR_TxQcuNum_S) | desc_len; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci checksum += val; 4262306a36Sopenharmony_ci WRITE_ONCE(ads->info, val); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci checksum += i->link; 4562306a36Sopenharmony_ci WRITE_ONCE(ads->link, i->link); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci checksum += i->buf_addr[0]; 4862306a36Sopenharmony_ci WRITE_ONCE(ads->data0, i->buf_addr[0]); 4962306a36Sopenharmony_ci checksum += i->buf_addr[1]; 5062306a36Sopenharmony_ci WRITE_ONCE(ads->data1, i->buf_addr[1]); 5162306a36Sopenharmony_ci checksum += i->buf_addr[2]; 5262306a36Sopenharmony_ci WRITE_ONCE(ads->data2, i->buf_addr[2]); 5362306a36Sopenharmony_ci checksum += i->buf_addr[3]; 5462306a36Sopenharmony_ci WRITE_ONCE(ads->data3, i->buf_addr[3]); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen); 5762306a36Sopenharmony_ci WRITE_ONCE(ads->ctl3, val); 5862306a36Sopenharmony_ci checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen); 5962306a36Sopenharmony_ci WRITE_ONCE(ads->ctl5, val); 6062306a36Sopenharmony_ci checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen); 6162306a36Sopenharmony_ci WRITE_ONCE(ads->ctl7, val); 6262306a36Sopenharmony_ci checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen); 6362306a36Sopenharmony_ci WRITE_ONCE(ads->ctl9, val); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff); 6662306a36Sopenharmony_ci WRITE_ONCE(ads->ctl10, checksum); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if (i->is_first || i->is_last) { 6962306a36Sopenharmony_ci WRITE_ONCE(ads->ctl13, set11nTries(i->rates, 0) 7062306a36Sopenharmony_ci | set11nTries(i->rates, 1) 7162306a36Sopenharmony_ci | set11nTries(i->rates, 2) 7262306a36Sopenharmony_ci | set11nTries(i->rates, 3) 7362306a36Sopenharmony_ci | (i->dur_update ? AR_DurUpdateEna : 0) 7462306a36Sopenharmony_ci | SM(0, AR_BurstDur)); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci WRITE_ONCE(ads->ctl14, set11nRate(i->rates, 0) 7762306a36Sopenharmony_ci | set11nRate(i->rates, 1) 7862306a36Sopenharmony_ci | set11nRate(i->rates, 2) 7962306a36Sopenharmony_ci | set11nRate(i->rates, 3)); 8062306a36Sopenharmony_ci } else { 8162306a36Sopenharmony_ci WRITE_ONCE(ads->ctl13, 0); 8262306a36Sopenharmony_ci WRITE_ONCE(ads->ctl14, 0); 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci ads->ctl20 = 0; 8662306a36Sopenharmony_ci ads->ctl21 = 0; 8762306a36Sopenharmony_ci ads->ctl22 = 0; 8862306a36Sopenharmony_ci ads->ctl23 = 0; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci ctl17 = SM(i->keytype, AR_EncrType); 9162306a36Sopenharmony_ci if (!i->is_first) { 9262306a36Sopenharmony_ci WRITE_ONCE(ads->ctl11, 0); 9362306a36Sopenharmony_ci WRITE_ONCE(ads->ctl12, i->is_last ? 0 : AR_TxMore); 9462306a36Sopenharmony_ci WRITE_ONCE(ads->ctl15, 0); 9562306a36Sopenharmony_ci WRITE_ONCE(ads->ctl16, 0); 9662306a36Sopenharmony_ci WRITE_ONCE(ads->ctl17, ctl17); 9762306a36Sopenharmony_ci WRITE_ONCE(ads->ctl18, 0); 9862306a36Sopenharmony_ci WRITE_ONCE(ads->ctl19, 0); 9962306a36Sopenharmony_ci return; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci WRITE_ONCE(ads->ctl11, (i->pkt_len & AR_FrameLen) 10362306a36Sopenharmony_ci | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) 10462306a36Sopenharmony_ci | SM(i->txpower[0], AR_XmitPower0) 10562306a36Sopenharmony_ci | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) 10662306a36Sopenharmony_ci | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) 10762306a36Sopenharmony_ci | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) 10862306a36Sopenharmony_ci | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) 10962306a36Sopenharmony_ci | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : 11062306a36Sopenharmony_ci (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0))); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ? 11362306a36Sopenharmony_ci SM(i->keyix, AR_DestIdx) : 0) 11462306a36Sopenharmony_ci | SM(i->type, AR_FrameType) 11562306a36Sopenharmony_ci | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) 11662306a36Sopenharmony_ci | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) 11762306a36Sopenharmony_ci | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); 12062306a36Sopenharmony_ci switch (i->aggr) { 12162306a36Sopenharmony_ci case AGGR_BUF_FIRST: 12262306a36Sopenharmony_ci ctl17 |= SM(i->aggr_len, AR_AggrLen); 12362306a36Sopenharmony_ci fallthrough; 12462306a36Sopenharmony_ci case AGGR_BUF_MIDDLE: 12562306a36Sopenharmony_ci ctl12 |= AR_IsAggr | AR_MoreAggr; 12662306a36Sopenharmony_ci ctl17 |= SM(i->ndelim, AR_PadDelim); 12762306a36Sopenharmony_ci break; 12862306a36Sopenharmony_ci case AGGR_BUF_LAST: 12962306a36Sopenharmony_ci ctl12 |= AR_IsAggr; 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci case AGGR_BUF_NONE: 13262306a36Sopenharmony_ci break; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S; 13662306a36Sopenharmony_ci ctl12 |= SM(val, AR_PAPRDChainMask); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci WRITE_ONCE(ads->ctl12, ctl12); 13962306a36Sopenharmony_ci WRITE_ONCE(ads->ctl17, ctl17); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci WRITE_ONCE(ads->ctl15, set11nPktDurRTSCTS(i->rates, 0) 14262306a36Sopenharmony_ci | set11nPktDurRTSCTS(i->rates, 1)); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci WRITE_ONCE(ads->ctl16, set11nPktDurRTSCTS(i->rates, 2) 14562306a36Sopenharmony_ci | set11nPktDurRTSCTS(i->rates, 3)); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci WRITE_ONCE(ads->ctl18, 14862306a36Sopenharmony_ci set11nRateFlags(i->rates, 0) | set11nChainSel(i->rates, 0) 14962306a36Sopenharmony_ci | set11nRateFlags(i->rates, 1) | set11nChainSel(i->rates, 1) 15062306a36Sopenharmony_ci | set11nRateFlags(i->rates, 2) | set11nChainSel(i->rates, 2) 15162306a36Sopenharmony_ci | set11nRateFlags(i->rates, 3) | set11nChainSel(i->rates, 3) 15262306a36Sopenharmony_ci | SM(i->rtscts_rate, AR_RTSCTSRate)); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci WRITE_ONCE(ads->ctl19, AR_Not_Sounding); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci WRITE_ONCE(ads->ctl20, SM(i->txpower[1], AR_XmitPower1)); 15762306a36Sopenharmony_ci WRITE_ONCE(ads->ctl21, SM(i->txpower[2], AR_XmitPower2)); 15862306a36Sopenharmony_ci WRITE_ONCE(ads->ctl22, SM(i->txpower[3], AR_XmitPower3)); 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci int checksum; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci checksum = ads->info + ads->link 16662306a36Sopenharmony_ci + ads->data0 + ads->ctl3 16762306a36Sopenharmony_ci + ads->data1 + ads->ctl5 16862306a36Sopenharmony_ci + ads->data2 + ads->ctl7 16962306a36Sopenharmony_ci + ads->data3 + ads->ctl9; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic void ar9003_hw_set_desc_link(void *ds, u32 ds_link) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct ar9003_txc *ads = ds; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci ads->link = ds_link; 17962306a36Sopenharmony_ci ads->ctl10 &= ~AR_TxPtrChkSum; 18062306a36Sopenharmony_ci ads->ctl10 |= ar9003_calc_ptr_chksum(ads); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked, 18462306a36Sopenharmony_ci u32 *sync_cause_p) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci u32 isr = 0; 18762306a36Sopenharmony_ci u32 mask2 = 0; 18862306a36Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 18962306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 19062306a36Sopenharmony_ci u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ; 19162306a36Sopenharmony_ci bool fatal_int; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 19462306a36Sopenharmony_ci async_mask |= AR_INTR_ASYNC_MASK_MCI; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE(ah)); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci if (async_cause & async_mask) { 19962306a36Sopenharmony_ci if ((REG_READ(ah, AR_RTC_STATUS(ah)) & AR_RTC_STATUS_M(ah)) 20062306a36Sopenharmony_ci == AR_RTC_STATUS_ON) 20162306a36Sopenharmony_ci isr = REG_READ(ah, AR_ISR); 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE(ah)) & AR_INTR_SYNC_DEFAULT; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci *masked = 0; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci if (!isr && !sync_cause && !async_cause) 21062306a36Sopenharmony_ci return false; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (isr) { 21362306a36Sopenharmony_ci if (isr & AR_ISR_BCNMISC) { 21462306a36Sopenharmony_ci u32 isr2; 21562306a36Sopenharmony_ci isr2 = REG_READ(ah, AR_ISR_S2); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_TIM) >> 21862306a36Sopenharmony_ci MAP_ISR_S2_TIM); 21962306a36Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> 22062306a36Sopenharmony_ci MAP_ISR_S2_DTIM); 22162306a36Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> 22262306a36Sopenharmony_ci MAP_ISR_S2_DTIMSYNC); 22362306a36Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> 22462306a36Sopenharmony_ci MAP_ISR_S2_CABEND); 22562306a36Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_GTT) << 22662306a36Sopenharmony_ci MAP_ISR_S2_GTT); 22762306a36Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_CST) << 22862306a36Sopenharmony_ci MAP_ISR_S2_CST); 22962306a36Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> 23062306a36Sopenharmony_ci MAP_ISR_S2_TSFOOR); 23162306a36Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >> 23262306a36Sopenharmony_ci MAP_ISR_S2_BB_WATCHDOG); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 23562306a36Sopenharmony_ci REG_WRITE(ah, AR_ISR_S2, isr2); 23662306a36Sopenharmony_ci isr &= ~AR_ISR_BCNMISC; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) 24162306a36Sopenharmony_ci isr = REG_READ(ah, AR_ISR_RAC); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (isr == 0xffffffff) { 24462306a36Sopenharmony_ci *masked = 0; 24562306a36Sopenharmony_ci return false; 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci *masked = isr & ATH9K_INT_COMMON; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (ah->config.rx_intr_mitigation) 25162306a36Sopenharmony_ci if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) 25262306a36Sopenharmony_ci *masked |= ATH9K_INT_RXLP; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (ah->config.tx_intr_mitigation) 25562306a36Sopenharmony_ci if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) 25662306a36Sopenharmony_ci *masked |= ATH9K_INT_TX; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) 25962306a36Sopenharmony_ci *masked |= ATH9K_INT_RXLP; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (isr & AR_ISR_HP_RXOK) 26262306a36Sopenharmony_ci *masked |= ATH9K_INT_RXHP; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) { 26562306a36Sopenharmony_ci *masked |= ATH9K_INT_TX; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 26862306a36Sopenharmony_ci u32 s0, s1; 26962306a36Sopenharmony_ci s0 = REG_READ(ah, AR_ISR_S0); 27062306a36Sopenharmony_ci REG_WRITE(ah, AR_ISR_S0, s0); 27162306a36Sopenharmony_ci s1 = REG_READ(ah, AR_ISR_S1); 27262306a36Sopenharmony_ci REG_WRITE(ah, AR_ISR_S1, s1); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | 27562306a36Sopenharmony_ci AR_ISR_TXEOL); 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (isr & AR_ISR_GENTMR) { 28062306a36Sopenharmony_ci u32 s5; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) 28362306a36Sopenharmony_ci s5 = REG_READ(ah, AR_ISR_S5_S(ah)); 28462306a36Sopenharmony_ci else 28562306a36Sopenharmony_ci s5 = REG_READ(ah, AR_ISR_S5); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci ah->intr_gen_timer_trigger = 28862306a36Sopenharmony_ci MS(s5, AR_ISR_S5_GENTIMER_TRIG); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci ah->intr_gen_timer_thresh = 29162306a36Sopenharmony_ci MS(s5, AR_ISR_S5_GENTIMER_THRESH); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci if (ah->intr_gen_timer_trigger) 29462306a36Sopenharmony_ci *masked |= ATH9K_INT_GENTIMER; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 29762306a36Sopenharmony_ci REG_WRITE(ah, AR_ISR_S5, s5); 29862306a36Sopenharmony_ci isr &= ~AR_ISR_GENTMR; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci *masked |= mask2; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 30662306a36Sopenharmony_ci REG_WRITE(ah, AR_ISR, isr); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci (void) REG_READ(ah, AR_ISR); 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci if (*masked & ATH9K_INT_BB_WATCHDOG) 31262306a36Sopenharmony_ci ar9003_hw_bb_watchdog_read(ah); 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (async_cause & AR_INTR_ASYNC_MASK_MCI) 31662306a36Sopenharmony_ci ar9003_mci_get_isr(ah, masked); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci if (sync_cause) { 31962306a36Sopenharmony_ci if (sync_cause_p) 32062306a36Sopenharmony_ci *sync_cause_p = sync_cause; 32162306a36Sopenharmony_ci fatal_int = 32262306a36Sopenharmony_ci (sync_cause & 32362306a36Sopenharmony_ci (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) 32462306a36Sopenharmony_ci ? true : false; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (fatal_int) { 32762306a36Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { 32862306a36Sopenharmony_ci ath_dbg(common, ANY, 32962306a36Sopenharmony_ci "received PCI FATAL interrupt\n"); 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { 33262306a36Sopenharmony_ci ath_dbg(common, ANY, 33362306a36Sopenharmony_ci "received PCI PERR interrupt\n"); 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci *masked |= ATH9K_INT_FATAL; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { 33962306a36Sopenharmony_ci REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); 34062306a36Sopenharmony_ci REG_WRITE(ah, AR_RC, 0); 34162306a36Sopenharmony_ci *masked |= ATH9K_INT_FATAL; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) 34562306a36Sopenharmony_ci ath_dbg(common, INTERRUPT, 34662306a36Sopenharmony_ci "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR(ah), sync_cause); 34962306a36Sopenharmony_ci (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR(ah)); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci return true; 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, 35662306a36Sopenharmony_ci struct ath_tx_status *ts) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci struct ar9003_txs *ads; 35962306a36Sopenharmony_ci u32 status; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci ads = &ah->ts_ring[ah->ts_tail]; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci status = READ_ONCE(ads->status8); 36462306a36Sopenharmony_ci if ((status & AR_TxDone) == 0) 36562306a36Sopenharmony_ci return -EINPROGRESS; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || 37062306a36Sopenharmony_ci (MS(ads->ds_info, AR_TxRxDesc) != 1)) { 37162306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), XMIT, 37262306a36Sopenharmony_ci "Tx Descriptor error %x\n", ads->ds_info); 37362306a36Sopenharmony_ci memset(ads, 0, sizeof(*ads)); 37462306a36Sopenharmony_ci return -EIO; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci ts->ts_rateindex = MS(status, AR_FinalTxIdx); 37862306a36Sopenharmony_ci ts->ts_seqnum = MS(status, AR_SeqNum); 37962306a36Sopenharmony_ci ts->tid = MS(status, AR_TxTid); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci ts->qid = MS(ads->ds_info, AR_TxQcuNum); 38262306a36Sopenharmony_ci ts->desc_id = MS(ads->status1, AR_TxDescId); 38362306a36Sopenharmony_ci ts->ts_tstamp = ads->status4; 38462306a36Sopenharmony_ci ts->ts_status = 0; 38562306a36Sopenharmony_ci ts->ts_flags = 0; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if (status & AR_TxOpExceeded) 38862306a36Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_XTXOP; 38962306a36Sopenharmony_ci status = READ_ONCE(ads->status2); 39062306a36Sopenharmony_ci ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); 39162306a36Sopenharmony_ci ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); 39262306a36Sopenharmony_ci ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); 39362306a36Sopenharmony_ci if (status & AR_TxBaStatus) { 39462306a36Sopenharmony_ci ts->ts_flags |= ATH9K_TX_BA; 39562306a36Sopenharmony_ci ts->ba_low = ads->status5; 39662306a36Sopenharmony_ci ts->ba_high = ads->status6; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci status = READ_ONCE(ads->status3); 40062306a36Sopenharmony_ci if (status & AR_ExcessiveRetries) 40162306a36Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_XRETRY; 40262306a36Sopenharmony_ci if (status & AR_Filtered) 40362306a36Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_FILT; 40462306a36Sopenharmony_ci if (status & AR_FIFOUnderrun) { 40562306a36Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_FIFO; 40662306a36Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci if (status & AR_TxTimerExpired) 40962306a36Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; 41062306a36Sopenharmony_ci if (status & AR_DescCfgErr) 41162306a36Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; 41262306a36Sopenharmony_ci if (status & AR_TxDataUnderrun) { 41362306a36Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; 41462306a36Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci if (status & AR_TxDelimUnderrun) { 41762306a36Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; 41862306a36Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci ts->ts_shortretry = MS(status, AR_RTSFailCnt); 42162306a36Sopenharmony_ci ts->ts_longretry = MS(status, AR_DataFailCnt); 42262306a36Sopenharmony_ci ts->ts_virtcol = MS(status, AR_VirtRetryCnt); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci status = READ_ONCE(ads->status7); 42562306a36Sopenharmony_ci ts->ts_rssi = MS(status, AR_TxRSSICombined); 42662306a36Sopenharmony_ci ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); 42762306a36Sopenharmony_ci ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); 42862306a36Sopenharmony_ci ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci memset(ads, 0, sizeof(*ads)); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci return 0; 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci const struct ar9003_txc *adc = ds; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci switch (index) { 44062306a36Sopenharmony_ci case 0: 44162306a36Sopenharmony_ci return MS(READ_ONCE(adc->ctl15), AR_PacketDur0); 44262306a36Sopenharmony_ci case 1: 44362306a36Sopenharmony_ci return MS(READ_ONCE(adc->ctl15), AR_PacketDur1); 44462306a36Sopenharmony_ci case 2: 44562306a36Sopenharmony_ci return MS(READ_ONCE(adc->ctl16), AR_PacketDur2); 44662306a36Sopenharmony_ci case 3: 44762306a36Sopenharmony_ci return MS(READ_ONCE(adc->ctl16), AR_PacketDur3); 44862306a36Sopenharmony_ci default: 44962306a36Sopenharmony_ci return 0; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_civoid ar9003_hw_attach_mac_ops(struct ath_hw *hw) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci struct ath_hw_ops *ops = ath9k_hw_ops(hw); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci ops->rx_enable = ar9003_hw_rx_enable; 45862306a36Sopenharmony_ci ops->set_desc_link = ar9003_hw_set_desc_link; 45962306a36Sopenharmony_ci ops->get_isr = ar9003_hw_get_isr; 46062306a36Sopenharmony_ci ops->set_txdesc = ar9003_set_txdesc; 46162306a36Sopenharmony_ci ops->proc_txdesc = ar9003_hw_proc_txdesc; 46262306a36Sopenharmony_ci ops->get_duration = ar9003_hw_get_duration; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_civoid ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK); 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_set_rx_bufsize); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_civoid ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, 47262306a36Sopenharmony_ci enum ath9k_rx_qtype qtype) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci if (qtype == ATH9K_RX_QUEUE_HP) 47562306a36Sopenharmony_ci REG_WRITE(ah, AR_HP_RXDP, rxdp); 47662306a36Sopenharmony_ci else 47762306a36Sopenharmony_ci REG_WRITE(ah, AR_LP_RXDP, rxdp); 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_addrxbuf_edma); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ciint ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, 48262306a36Sopenharmony_ci void *buf_addr) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci struct ar9003_rxs *rxsp = buf_addr; 48562306a36Sopenharmony_ci unsigned int phyerr; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci if ((rxsp->status11 & AR_RxDone) == 0) 48862306a36Sopenharmony_ci return -EINPROGRESS; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci if (MS(rxsp->ds_info, AR_DescId) != 0x168c) 49162306a36Sopenharmony_ci return -EINVAL; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) 49462306a36Sopenharmony_ci return -EINPROGRESS; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci rxs->rs_status = 0; 49762306a36Sopenharmony_ci rxs->rs_flags = 0; 49862306a36Sopenharmony_ci rxs->enc_flags = 0; 49962306a36Sopenharmony_ci rxs->bw = RATE_INFO_BW_20; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci rxs->rs_datalen = rxsp->status2 & AR_DataLen; 50262306a36Sopenharmony_ci rxs->rs_tstamp = rxsp->status3; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* XXX: Keycache */ 50562306a36Sopenharmony_ci rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined); 50662306a36Sopenharmony_ci rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00); 50762306a36Sopenharmony_ci rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01); 50862306a36Sopenharmony_ci rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02); 50962306a36Sopenharmony_ci rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10); 51062306a36Sopenharmony_ci rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11); 51162306a36Sopenharmony_ci rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (rxsp->status11 & AR_RxKeyIdxValid) 51462306a36Sopenharmony_ci rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx); 51562306a36Sopenharmony_ci else 51662306a36Sopenharmony_ci rxs->rs_keyix = ATH9K_RXKEYIX_INVALID; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci rxs->rs_rate = MS(rxsp->status1, AR_RxRate); 51962306a36Sopenharmony_ci rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci rxs->rs_firstaggr = (rxsp->status11 & AR_RxFirstAggr) ? 1 : 0; 52262306a36Sopenharmony_ci rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; 52362306a36Sopenharmony_ci rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; 52462306a36Sopenharmony_ci rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); 52562306a36Sopenharmony_ci rxs->enc_flags |= (rxsp->status4 & AR_GI) ? RX_ENC_FLAG_SHORT_GI : 0; 52662306a36Sopenharmony_ci rxs->enc_flags |= 52762306a36Sopenharmony_ci (rxsp->status4 & AR_STBC) ? (1 << RX_ENC_FLAG_STBC_SHIFT) : 0; 52862306a36Sopenharmony_ci rxs->bw = (rxsp->status4 & AR_2040) ? RATE_INFO_BW_40 : RATE_INFO_BW_20; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci rxs->evm0 = rxsp->status6; 53162306a36Sopenharmony_ci rxs->evm1 = rxsp->status7; 53262306a36Sopenharmony_ci rxs->evm2 = rxsp->status8; 53362306a36Sopenharmony_ci rxs->evm3 = rxsp->status9; 53462306a36Sopenharmony_ci rxs->evm4 = (rxsp->status10 & 0xffff); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci if (rxsp->status11 & AR_PreDelimCRCErr) 53762306a36Sopenharmony_ci rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci if (rxsp->status11 & AR_PostDelimCRCErr) 54062306a36Sopenharmony_ci rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci if (rxsp->status11 & AR_DecryptBusyErr) 54362306a36Sopenharmony_ci rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if ((rxsp->status11 & AR_RxFrameOK) == 0) { 54662306a36Sopenharmony_ci /* 54762306a36Sopenharmony_ci * AR_CRCErr will bet set to true if we're on the last 54862306a36Sopenharmony_ci * subframe and the AR_PostDelimCRCErr is caught. 54962306a36Sopenharmony_ci * In a way this also gives us a guarantee that when 55062306a36Sopenharmony_ci * (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot 55162306a36Sopenharmony_ci * possibly be reviewing the last subframe. AR_CRCErr 55262306a36Sopenharmony_ci * is the CRC of the actual data. 55362306a36Sopenharmony_ci */ 55462306a36Sopenharmony_ci if (rxsp->status11 & AR_CRCErr) 55562306a36Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_CRC; 55662306a36Sopenharmony_ci else if (rxsp->status11 & AR_DecryptCRCErr) 55762306a36Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_DECRYPT; 55862306a36Sopenharmony_ci else if (rxsp->status11 & AR_MichaelErr) 55962306a36Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_MIC; 56062306a36Sopenharmony_ci if (rxsp->status11 & AR_PHYErr) { 56162306a36Sopenharmony_ci phyerr = MS(rxsp->status11, AR_PHYErrCode); 56262306a36Sopenharmony_ci /* 56362306a36Sopenharmony_ci * If we reach a point here where AR_PostDelimCRCErr is 56462306a36Sopenharmony_ci * true it implies we're *not* on the last subframe. In 56562306a36Sopenharmony_ci * in that case that we know already that the CRC of 56662306a36Sopenharmony_ci * the frame was OK, and MAC would send an ACK for that 56762306a36Sopenharmony_ci * subframe, even if we did get a phy error of type 56862306a36Sopenharmony_ci * ATH9K_PHYERR_OFDM_RESTART. This is only applicable 56962306a36Sopenharmony_ci * to frame that are prior to the last subframe. 57062306a36Sopenharmony_ci * The AR_PostDelimCRCErr is the CRC for the MPDU 57162306a36Sopenharmony_ci * delimiter, which contains the 4 reserved bits, 57262306a36Sopenharmony_ci * the MPDU length (12 bits), and follows the MPDU 57362306a36Sopenharmony_ci * delimiter for an A-MPDU subframe (0x4E = 'N' ASCII). 57462306a36Sopenharmony_ci */ 57562306a36Sopenharmony_ci if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) && 57662306a36Sopenharmony_ci (rxsp->status11 & AR_PostDelimCRCErr)) { 57762306a36Sopenharmony_ci rxs->rs_phyerr = 0; 57862306a36Sopenharmony_ci } else { 57962306a36Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_PHY; 58062306a36Sopenharmony_ci rxs->rs_phyerr = phyerr; 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci } 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (rxsp->status11 & AR_KeyMiss) 58662306a36Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_KEYMISS; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci return 0; 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_civoid ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci ah->ts_tail = 0; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci memset((void *) ah->ts_ring, 0, 59762306a36Sopenharmony_ci ah->ts_size * sizeof(struct ar9003_txs)); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), XMIT, 60062306a36Sopenharmony_ci "TS Start 0x%x End 0x%x Virt %p, Size %d\n", 60162306a36Sopenharmony_ci ah->ts_paddr_start, ah->ts_paddr_end, 60262306a36Sopenharmony_ci ah->ts_ring, ah->ts_size); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start); 60562306a36Sopenharmony_ci REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end); 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_civoid ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start, 60962306a36Sopenharmony_ci u32 ts_paddr_start, 61062306a36Sopenharmony_ci u16 size) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci ah->ts_paddr_start = ts_paddr_start; 61462306a36Sopenharmony_ci ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs)); 61562306a36Sopenharmony_ci ah->ts_size = size; 61662306a36Sopenharmony_ci ah->ts_ring = ts_start; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci ath9k_hw_reset_txstatus_ring(ah); 61962306a36Sopenharmony_ci} 62062306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setup_statusring); 621