18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2010-2011 Atheros Communications Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 58c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 68c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 98c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 108c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 118c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 148c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci#include <linux/export.h> 178c2ecf20Sopenharmony_ci#include "hw.h" 188c2ecf20Sopenharmony_ci#include "ar9003_mac.h" 198c2ecf20Sopenharmony_ci#include "ar9003_mci.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic void ar9003_hw_rx_enable(struct ath_hw *hw) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci REG_WRITE(hw, AR_CR, 0); 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic void 278c2ecf20Sopenharmony_ciar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci struct ar9003_txc *ads = ds; 308c2ecf20Sopenharmony_ci int checksum = 0; 318c2ecf20Sopenharmony_ci u32 val, ctl12, ctl17; 328c2ecf20Sopenharmony_ci u8 desc_len; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci desc_len = ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x18 : 0x17); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci val = (ATHEROS_VENDOR_ID << AR_DescId_S) | 378c2ecf20Sopenharmony_ci (1 << AR_TxRxDesc_S) | 388c2ecf20Sopenharmony_ci (1 << AR_CtrlStat_S) | 398c2ecf20Sopenharmony_ci (i->qcu << AR_TxQcuNum_S) | desc_len; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci checksum += val; 428c2ecf20Sopenharmony_ci WRITE_ONCE(ads->info, val); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci checksum += i->link; 458c2ecf20Sopenharmony_ci WRITE_ONCE(ads->link, i->link); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci checksum += i->buf_addr[0]; 488c2ecf20Sopenharmony_ci WRITE_ONCE(ads->data0, i->buf_addr[0]); 498c2ecf20Sopenharmony_ci checksum += i->buf_addr[1]; 508c2ecf20Sopenharmony_ci WRITE_ONCE(ads->data1, i->buf_addr[1]); 518c2ecf20Sopenharmony_ci checksum += i->buf_addr[2]; 528c2ecf20Sopenharmony_ci WRITE_ONCE(ads->data2, i->buf_addr[2]); 538c2ecf20Sopenharmony_ci checksum += i->buf_addr[3]; 548c2ecf20Sopenharmony_ci WRITE_ONCE(ads->data3, i->buf_addr[3]); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen); 578c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl3, val); 588c2ecf20Sopenharmony_ci checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen); 598c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl5, val); 608c2ecf20Sopenharmony_ci checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen); 618c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl7, val); 628c2ecf20Sopenharmony_ci checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen); 638c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl9, val); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff); 668c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl10, checksum); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (i->is_first || i->is_last) { 698c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl13, set11nTries(i->rates, 0) 708c2ecf20Sopenharmony_ci | set11nTries(i->rates, 1) 718c2ecf20Sopenharmony_ci | set11nTries(i->rates, 2) 728c2ecf20Sopenharmony_ci | set11nTries(i->rates, 3) 738c2ecf20Sopenharmony_ci | (i->dur_update ? AR_DurUpdateEna : 0) 748c2ecf20Sopenharmony_ci | SM(0, AR_BurstDur)); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl14, set11nRate(i->rates, 0) 778c2ecf20Sopenharmony_ci | set11nRate(i->rates, 1) 788c2ecf20Sopenharmony_ci | set11nRate(i->rates, 2) 798c2ecf20Sopenharmony_ci | set11nRate(i->rates, 3)); 808c2ecf20Sopenharmony_ci } else { 818c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl13, 0); 828c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl14, 0); 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci ads->ctl20 = 0; 868c2ecf20Sopenharmony_ci ads->ctl21 = 0; 878c2ecf20Sopenharmony_ci ads->ctl22 = 0; 888c2ecf20Sopenharmony_ci ads->ctl23 = 0; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci ctl17 = SM(i->keytype, AR_EncrType); 918c2ecf20Sopenharmony_ci if (!i->is_first) { 928c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl11, 0); 938c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl12, i->is_last ? 0 : AR_TxMore); 948c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl15, 0); 958c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl16, 0); 968c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl17, ctl17); 978c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl18, 0); 988c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl19, 0); 998c2ecf20Sopenharmony_ci return; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl11, (i->pkt_len & AR_FrameLen) 1038c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) 1048c2ecf20Sopenharmony_ci | SM(i->txpower[0], AR_XmitPower0) 1058c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) 1068c2ecf20Sopenharmony_ci | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) 1078c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) 1088c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) 1098c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : 1108c2ecf20Sopenharmony_ci (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0))); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ? 1138c2ecf20Sopenharmony_ci SM(i->keyix, AR_DestIdx) : 0) 1148c2ecf20Sopenharmony_ci | SM(i->type, AR_FrameType) 1158c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) 1168c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) 1178c2ecf20Sopenharmony_ci | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); 1208c2ecf20Sopenharmony_ci switch (i->aggr) { 1218c2ecf20Sopenharmony_ci case AGGR_BUF_FIRST: 1228c2ecf20Sopenharmony_ci ctl17 |= SM(i->aggr_len, AR_AggrLen); 1238c2ecf20Sopenharmony_ci fallthrough; 1248c2ecf20Sopenharmony_ci case AGGR_BUF_MIDDLE: 1258c2ecf20Sopenharmony_ci ctl12 |= AR_IsAggr | AR_MoreAggr; 1268c2ecf20Sopenharmony_ci ctl17 |= SM(i->ndelim, AR_PadDelim); 1278c2ecf20Sopenharmony_ci break; 1288c2ecf20Sopenharmony_ci case AGGR_BUF_LAST: 1298c2ecf20Sopenharmony_ci ctl12 |= AR_IsAggr; 1308c2ecf20Sopenharmony_ci break; 1318c2ecf20Sopenharmony_ci case AGGR_BUF_NONE: 1328c2ecf20Sopenharmony_ci break; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S; 1368c2ecf20Sopenharmony_ci ctl12 |= SM(val, AR_PAPRDChainMask); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl12, ctl12); 1398c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl17, ctl17); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl15, set11nPktDurRTSCTS(i->rates, 0) 1428c2ecf20Sopenharmony_ci | set11nPktDurRTSCTS(i->rates, 1)); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl16, set11nPktDurRTSCTS(i->rates, 2) 1458c2ecf20Sopenharmony_ci | set11nPktDurRTSCTS(i->rates, 3)); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl18, set11nRateFlags(i->rates, 0) 1488c2ecf20Sopenharmony_ci | set11nRateFlags(i->rates, 1) 1498c2ecf20Sopenharmony_ci | set11nRateFlags(i->rates, 2) 1508c2ecf20Sopenharmony_ci | set11nRateFlags(i->rates, 3) 1518c2ecf20Sopenharmony_ci | SM(i->rtscts_rate, AR_RTSCTSRate)); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl19, AR_Not_Sounding); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl20, SM(i->txpower[1], AR_XmitPower1)); 1568c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl21, SM(i->txpower[2], AR_XmitPower2)); 1578c2ecf20Sopenharmony_ci WRITE_ONCE(ads->ctl22, SM(i->txpower[3], AR_XmitPower3)); 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci int checksum; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci checksum = ads->info + ads->link 1658c2ecf20Sopenharmony_ci + ads->data0 + ads->ctl3 1668c2ecf20Sopenharmony_ci + ads->data1 + ads->ctl5 1678c2ecf20Sopenharmony_ci + ads->data2 + ads->ctl7 1688c2ecf20Sopenharmony_ci + ads->data3 + ads->ctl9; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic void ar9003_hw_set_desc_link(void *ds, u32 ds_link) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci struct ar9003_txc *ads = ds; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci ads->link = ds_link; 1788c2ecf20Sopenharmony_ci ads->ctl10 &= ~AR_TxPtrChkSum; 1798c2ecf20Sopenharmony_ci ads->ctl10 |= ar9003_calc_ptr_chksum(ads); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked, 1838c2ecf20Sopenharmony_ci u32 *sync_cause_p) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci u32 isr = 0; 1868c2ecf20Sopenharmony_ci u32 mask2 = 0; 1878c2ecf20Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 1888c2ecf20Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 1898c2ecf20Sopenharmony_ci u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ; 1908c2ecf20Sopenharmony_ci bool fatal_int; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 1938c2ecf20Sopenharmony_ci async_mask |= AR_INTR_ASYNC_MASK_MCI; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (async_cause & async_mask) { 1988c2ecf20Sopenharmony_ci if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) 1998c2ecf20Sopenharmony_ci == AR_RTC_STATUS_ON) 2008c2ecf20Sopenharmony_ci isr = REG_READ(ah, AR_ISR); 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci *masked = 0; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (!isr && !sync_cause && !async_cause) 2098c2ecf20Sopenharmony_ci return false; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (isr) { 2128c2ecf20Sopenharmony_ci if (isr & AR_ISR_BCNMISC) { 2138c2ecf20Sopenharmony_ci u32 isr2; 2148c2ecf20Sopenharmony_ci isr2 = REG_READ(ah, AR_ISR_S2); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_TIM) >> 2178c2ecf20Sopenharmony_ci MAP_ISR_S2_TIM); 2188c2ecf20Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> 2198c2ecf20Sopenharmony_ci MAP_ISR_S2_DTIM); 2208c2ecf20Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> 2218c2ecf20Sopenharmony_ci MAP_ISR_S2_DTIMSYNC); 2228c2ecf20Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> 2238c2ecf20Sopenharmony_ci MAP_ISR_S2_CABEND); 2248c2ecf20Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_GTT) << 2258c2ecf20Sopenharmony_ci MAP_ISR_S2_GTT); 2268c2ecf20Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_CST) << 2278c2ecf20Sopenharmony_ci MAP_ISR_S2_CST); 2288c2ecf20Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> 2298c2ecf20Sopenharmony_ci MAP_ISR_S2_TSFOOR); 2308c2ecf20Sopenharmony_ci mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >> 2318c2ecf20Sopenharmony_ci MAP_ISR_S2_BB_WATCHDOG); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 2348c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR_S2, isr2); 2358c2ecf20Sopenharmony_ci isr &= ~AR_ISR_BCNMISC; 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) 2408c2ecf20Sopenharmony_ci isr = REG_READ(ah, AR_ISR_RAC); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (isr == 0xffffffff) { 2438c2ecf20Sopenharmony_ci *masked = 0; 2448c2ecf20Sopenharmony_ci return false; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci *masked = isr & ATH9K_INT_COMMON; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (ah->config.rx_intr_mitigation) 2508c2ecf20Sopenharmony_ci if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) 2518c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_RXLP; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci if (ah->config.tx_intr_mitigation) 2548c2ecf20Sopenharmony_ci if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) 2558c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_TX; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) 2588c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_RXLP; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci if (isr & AR_ISR_HP_RXOK) 2618c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_RXHP; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) { 2648c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_TX; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 2678c2ecf20Sopenharmony_ci u32 s0, s1; 2688c2ecf20Sopenharmony_ci s0 = REG_READ(ah, AR_ISR_S0); 2698c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR_S0, s0); 2708c2ecf20Sopenharmony_ci s1 = REG_READ(ah, AR_ISR_S1); 2718c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR_S1, s1); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | 2748c2ecf20Sopenharmony_ci AR_ISR_TXEOL); 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (isr & AR_ISR_GENTMR) { 2798c2ecf20Sopenharmony_ci u32 s5; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) 2828c2ecf20Sopenharmony_ci s5 = REG_READ(ah, AR_ISR_S5_S); 2838c2ecf20Sopenharmony_ci else 2848c2ecf20Sopenharmony_ci s5 = REG_READ(ah, AR_ISR_S5); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci ah->intr_gen_timer_trigger = 2878c2ecf20Sopenharmony_ci MS(s5, AR_ISR_S5_GENTIMER_TRIG); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci ah->intr_gen_timer_thresh = 2908c2ecf20Sopenharmony_ci MS(s5, AR_ISR_S5_GENTIMER_THRESH); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci if (ah->intr_gen_timer_trigger) 2938c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_GENTIMER; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 2968c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR_S5, s5); 2978c2ecf20Sopenharmony_ci isr &= ~AR_ISR_GENTMR; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci *masked |= mask2; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 3058c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_ISR, isr); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci (void) REG_READ(ah, AR_ISR); 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci if (*masked & ATH9K_INT_BB_WATCHDOG) 3118c2ecf20Sopenharmony_ci ar9003_hw_bb_watchdog_read(ah); 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (async_cause & AR_INTR_ASYNC_MASK_MCI) 3158c2ecf20Sopenharmony_ci ar9003_mci_get_isr(ah, masked); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (sync_cause) { 3188c2ecf20Sopenharmony_ci if (sync_cause_p) 3198c2ecf20Sopenharmony_ci *sync_cause_p = sync_cause; 3208c2ecf20Sopenharmony_ci fatal_int = 3218c2ecf20Sopenharmony_ci (sync_cause & 3228c2ecf20Sopenharmony_ci (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) 3238c2ecf20Sopenharmony_ci ? true : false; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (fatal_int) { 3268c2ecf20Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { 3278c2ecf20Sopenharmony_ci ath_dbg(common, ANY, 3288c2ecf20Sopenharmony_ci "received PCI FATAL interrupt\n"); 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { 3318c2ecf20Sopenharmony_ci ath_dbg(common, ANY, 3328c2ecf20Sopenharmony_ci "received PCI PERR interrupt\n"); 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_FATAL; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { 3388c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); 3398c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_RC, 0); 3408c2ecf20Sopenharmony_ci *masked |= ATH9K_INT_FATAL; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) 3448c2ecf20Sopenharmony_ci ath_dbg(common, INTERRUPT, 3458c2ecf20Sopenharmony_ci "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); 3488c2ecf20Sopenharmony_ci (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci return true; 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, 3558c2ecf20Sopenharmony_ci struct ath_tx_status *ts) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci struct ar9003_txs *ads; 3588c2ecf20Sopenharmony_ci u32 status; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci ads = &ah->ts_ring[ah->ts_tail]; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci status = READ_ONCE(ads->status8); 3638c2ecf20Sopenharmony_ci if ((status & AR_TxDone) == 0) 3648c2ecf20Sopenharmony_ci return -EINPROGRESS; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || 3698c2ecf20Sopenharmony_ci (MS(ads->ds_info, AR_TxRxDesc) != 1)) { 3708c2ecf20Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), XMIT, 3718c2ecf20Sopenharmony_ci "Tx Descriptor error %x\n", ads->ds_info); 3728c2ecf20Sopenharmony_ci memset(ads, 0, sizeof(*ads)); 3738c2ecf20Sopenharmony_ci return -EIO; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci ts->ts_rateindex = MS(status, AR_FinalTxIdx); 3778c2ecf20Sopenharmony_ci ts->ts_seqnum = MS(status, AR_SeqNum); 3788c2ecf20Sopenharmony_ci ts->tid = MS(status, AR_TxTid); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci ts->qid = MS(ads->ds_info, AR_TxQcuNum); 3818c2ecf20Sopenharmony_ci ts->desc_id = MS(ads->status1, AR_TxDescId); 3828c2ecf20Sopenharmony_ci ts->ts_tstamp = ads->status4; 3838c2ecf20Sopenharmony_ci ts->ts_status = 0; 3848c2ecf20Sopenharmony_ci ts->ts_flags = 0; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci if (status & AR_TxOpExceeded) 3878c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_XTXOP; 3888c2ecf20Sopenharmony_ci status = READ_ONCE(ads->status2); 3898c2ecf20Sopenharmony_ci ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); 3908c2ecf20Sopenharmony_ci ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); 3918c2ecf20Sopenharmony_ci ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); 3928c2ecf20Sopenharmony_ci if (status & AR_TxBaStatus) { 3938c2ecf20Sopenharmony_ci ts->ts_flags |= ATH9K_TX_BA; 3948c2ecf20Sopenharmony_ci ts->ba_low = ads->status5; 3958c2ecf20Sopenharmony_ci ts->ba_high = ads->status6; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci status = READ_ONCE(ads->status3); 3998c2ecf20Sopenharmony_ci if (status & AR_ExcessiveRetries) 4008c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_XRETRY; 4018c2ecf20Sopenharmony_ci if (status & AR_Filtered) 4028c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_FILT; 4038c2ecf20Sopenharmony_ci if (status & AR_FIFOUnderrun) { 4048c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_FIFO; 4058c2ecf20Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci if (status & AR_TxTimerExpired) 4088c2ecf20Sopenharmony_ci ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; 4098c2ecf20Sopenharmony_ci if (status & AR_DescCfgErr) 4108c2ecf20Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; 4118c2ecf20Sopenharmony_ci if (status & AR_TxDataUnderrun) { 4128c2ecf20Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; 4138c2ecf20Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci if (status & AR_TxDelimUnderrun) { 4168c2ecf20Sopenharmony_ci ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; 4178c2ecf20Sopenharmony_ci ath9k_hw_updatetxtriglevel(ah, true); 4188c2ecf20Sopenharmony_ci } 4198c2ecf20Sopenharmony_ci ts->ts_shortretry = MS(status, AR_RTSFailCnt); 4208c2ecf20Sopenharmony_ci ts->ts_longretry = MS(status, AR_DataFailCnt); 4218c2ecf20Sopenharmony_ci ts->ts_virtcol = MS(status, AR_VirtRetryCnt); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci status = READ_ONCE(ads->status7); 4248c2ecf20Sopenharmony_ci ts->ts_rssi = MS(status, AR_TxRSSICombined); 4258c2ecf20Sopenharmony_ci ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); 4268c2ecf20Sopenharmony_ci ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); 4278c2ecf20Sopenharmony_ci ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci memset(ads, 0, sizeof(*ads)); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci return 0; 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci const struct ar9003_txc *adc = ds; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci switch (index) { 4398c2ecf20Sopenharmony_ci case 0: 4408c2ecf20Sopenharmony_ci return MS(READ_ONCE(adc->ctl15), AR_PacketDur0); 4418c2ecf20Sopenharmony_ci case 1: 4428c2ecf20Sopenharmony_ci return MS(READ_ONCE(adc->ctl15), AR_PacketDur1); 4438c2ecf20Sopenharmony_ci case 2: 4448c2ecf20Sopenharmony_ci return MS(READ_ONCE(adc->ctl16), AR_PacketDur2); 4458c2ecf20Sopenharmony_ci case 3: 4468c2ecf20Sopenharmony_ci return MS(READ_ONCE(adc->ctl16), AR_PacketDur3); 4478c2ecf20Sopenharmony_ci default: 4488c2ecf20Sopenharmony_ci return 0; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_civoid ar9003_hw_attach_mac_ops(struct ath_hw *hw) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci struct ath_hw_ops *ops = ath9k_hw_ops(hw); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci ops->rx_enable = ar9003_hw_rx_enable; 4578c2ecf20Sopenharmony_ci ops->set_desc_link = ar9003_hw_set_desc_link; 4588c2ecf20Sopenharmony_ci ops->get_isr = ar9003_hw_get_isr; 4598c2ecf20Sopenharmony_ci ops->set_txdesc = ar9003_set_txdesc; 4608c2ecf20Sopenharmony_ci ops->proc_txdesc = ar9003_hw_proc_txdesc; 4618c2ecf20Sopenharmony_ci ops->get_duration = ar9003_hw_get_duration; 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_civoid ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK); 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_set_rx_bufsize); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_civoid ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, 4718c2ecf20Sopenharmony_ci enum ath9k_rx_qtype qtype) 4728c2ecf20Sopenharmony_ci{ 4738c2ecf20Sopenharmony_ci if (qtype == ATH9K_RX_QUEUE_HP) 4748c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_HP_RXDP, rxdp); 4758c2ecf20Sopenharmony_ci else 4768c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_LP_RXDP, rxdp); 4778c2ecf20Sopenharmony_ci} 4788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_addrxbuf_edma); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ciint ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, 4818c2ecf20Sopenharmony_ci void *buf_addr) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci struct ar9003_rxs *rxsp = buf_addr; 4848c2ecf20Sopenharmony_ci unsigned int phyerr; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci if ((rxsp->status11 & AR_RxDone) == 0) 4878c2ecf20Sopenharmony_ci return -EINPROGRESS; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (MS(rxsp->ds_info, AR_DescId) != 0x168c) 4908c2ecf20Sopenharmony_ci return -EINVAL; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) 4938c2ecf20Sopenharmony_ci return -EINPROGRESS; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci rxs->rs_status = 0; 4968c2ecf20Sopenharmony_ci rxs->rs_flags = 0; 4978c2ecf20Sopenharmony_ci rxs->enc_flags = 0; 4988c2ecf20Sopenharmony_ci rxs->bw = RATE_INFO_BW_20; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci rxs->rs_datalen = rxsp->status2 & AR_DataLen; 5018c2ecf20Sopenharmony_ci rxs->rs_tstamp = rxsp->status3; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci /* XXX: Keycache */ 5048c2ecf20Sopenharmony_ci rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined); 5058c2ecf20Sopenharmony_ci rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00); 5068c2ecf20Sopenharmony_ci rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01); 5078c2ecf20Sopenharmony_ci rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02); 5088c2ecf20Sopenharmony_ci rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10); 5098c2ecf20Sopenharmony_ci rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11); 5108c2ecf20Sopenharmony_ci rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (rxsp->status11 & AR_RxKeyIdxValid) 5138c2ecf20Sopenharmony_ci rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx); 5148c2ecf20Sopenharmony_ci else 5158c2ecf20Sopenharmony_ci rxs->rs_keyix = ATH9K_RXKEYIX_INVALID; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci rxs->rs_rate = MS(rxsp->status1, AR_RxRate); 5188c2ecf20Sopenharmony_ci rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci rxs->rs_firstaggr = (rxsp->status11 & AR_RxFirstAggr) ? 1 : 0; 5218c2ecf20Sopenharmony_ci rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; 5228c2ecf20Sopenharmony_ci rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; 5238c2ecf20Sopenharmony_ci rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); 5248c2ecf20Sopenharmony_ci rxs->enc_flags |= (rxsp->status4 & AR_GI) ? RX_ENC_FLAG_SHORT_GI : 0; 5258c2ecf20Sopenharmony_ci rxs->bw = (rxsp->status4 & AR_2040) ? RATE_INFO_BW_40 : RATE_INFO_BW_20; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci rxs->evm0 = rxsp->status6; 5288c2ecf20Sopenharmony_ci rxs->evm1 = rxsp->status7; 5298c2ecf20Sopenharmony_ci rxs->evm2 = rxsp->status8; 5308c2ecf20Sopenharmony_ci rxs->evm3 = rxsp->status9; 5318c2ecf20Sopenharmony_ci rxs->evm4 = (rxsp->status10 & 0xffff); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci if (rxsp->status11 & AR_PreDelimCRCErr) 5348c2ecf20Sopenharmony_ci rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (rxsp->status11 & AR_PostDelimCRCErr) 5378c2ecf20Sopenharmony_ci rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci if (rxsp->status11 & AR_DecryptBusyErr) 5408c2ecf20Sopenharmony_ci rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci if ((rxsp->status11 & AR_RxFrameOK) == 0) { 5438c2ecf20Sopenharmony_ci /* 5448c2ecf20Sopenharmony_ci * AR_CRCErr will bet set to true if we're on the last 5458c2ecf20Sopenharmony_ci * subframe and the AR_PostDelimCRCErr is caught. 5468c2ecf20Sopenharmony_ci * In a way this also gives us a guarantee that when 5478c2ecf20Sopenharmony_ci * (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot 5488c2ecf20Sopenharmony_ci * possibly be reviewing the last subframe. AR_CRCErr 5498c2ecf20Sopenharmony_ci * is the CRC of the actual data. 5508c2ecf20Sopenharmony_ci */ 5518c2ecf20Sopenharmony_ci if (rxsp->status11 & AR_CRCErr) 5528c2ecf20Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_CRC; 5538c2ecf20Sopenharmony_ci else if (rxsp->status11 & AR_DecryptCRCErr) 5548c2ecf20Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_DECRYPT; 5558c2ecf20Sopenharmony_ci else if (rxsp->status11 & AR_MichaelErr) 5568c2ecf20Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_MIC; 5578c2ecf20Sopenharmony_ci if (rxsp->status11 & AR_PHYErr) { 5588c2ecf20Sopenharmony_ci phyerr = MS(rxsp->status11, AR_PHYErrCode); 5598c2ecf20Sopenharmony_ci /* 5608c2ecf20Sopenharmony_ci * If we reach a point here where AR_PostDelimCRCErr is 5618c2ecf20Sopenharmony_ci * true it implies we're *not* on the last subframe. In 5628c2ecf20Sopenharmony_ci * in that case that we know already that the CRC of 5638c2ecf20Sopenharmony_ci * the frame was OK, and MAC would send an ACK for that 5648c2ecf20Sopenharmony_ci * subframe, even if we did get a phy error of type 5658c2ecf20Sopenharmony_ci * ATH9K_PHYERR_OFDM_RESTART. This is only applicable 5668c2ecf20Sopenharmony_ci * to frame that are prior to the last subframe. 5678c2ecf20Sopenharmony_ci * The AR_PostDelimCRCErr is the CRC for the MPDU 5688c2ecf20Sopenharmony_ci * delimiter, which contains the 4 reserved bits, 5698c2ecf20Sopenharmony_ci * the MPDU length (12 bits), and follows the MPDU 5708c2ecf20Sopenharmony_ci * delimiter for an A-MPDU subframe (0x4E = 'N' ASCII). 5718c2ecf20Sopenharmony_ci */ 5728c2ecf20Sopenharmony_ci if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) && 5738c2ecf20Sopenharmony_ci (rxsp->status11 & AR_PostDelimCRCErr)) { 5748c2ecf20Sopenharmony_ci rxs->rs_phyerr = 0; 5758c2ecf20Sopenharmony_ci } else { 5768c2ecf20Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_PHY; 5778c2ecf20Sopenharmony_ci rxs->rs_phyerr = phyerr; 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci } 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci if (rxsp->status11 & AR_KeyMiss) 5838c2ecf20Sopenharmony_ci rxs->rs_status |= ATH9K_RXERR_KEYMISS; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci return 0; 5868c2ecf20Sopenharmony_ci} 5878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_civoid ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci ah->ts_tail = 0; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci memset((void *) ah->ts_ring, 0, 5948c2ecf20Sopenharmony_ci ah->ts_size * sizeof(struct ar9003_txs)); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), XMIT, 5978c2ecf20Sopenharmony_ci "TS Start 0x%x End 0x%x Virt %p, Size %d\n", 5988c2ecf20Sopenharmony_ci ah->ts_paddr_start, ah->ts_paddr_end, 5998c2ecf20Sopenharmony_ci ah->ts_ring, ah->ts_size); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start); 6028c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end); 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_civoid ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start, 6068c2ecf20Sopenharmony_ci u32 ts_paddr_start, 6078c2ecf20Sopenharmony_ci u16 size) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci ah->ts_paddr_start = ts_paddr_start; 6118c2ecf20Sopenharmony_ci ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs)); 6128c2ecf20Sopenharmony_ci ah->ts_size = size; 6138c2ecf20Sopenharmony_ci ah->ts_ring = ts_start; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci ath9k_hw_reset_txstatus_ring(ah); 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setup_statusring); 618