Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.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_desc.h"20#include "ah_internal.h"2122#include "ar9300/ar9300.h"23#include "ar9300/ar9300reg.h"24#include "ar9300/ar9300desc.h"2526/*27* Get the RXDP.28*/29u_int32_t30ar9300_get_rx_dp(struct ath_hal *ath, HAL_RX_QUEUE qtype)31{32if (qtype == HAL_RX_QUEUE_HP) {33return OS_REG_READ(ath, AR_HP_RXDP);34} else {35return OS_REG_READ(ath, AR_LP_RXDP);36}37}3839/*40* Set the rx_dp.41*/42void43ar9300_set_rx_dp(struct ath_hal *ah, u_int32_t rxdp, HAL_RX_QUEUE qtype)44{45HALASSERT((qtype == HAL_RX_QUEUE_HP) || (qtype == HAL_RX_QUEUE_LP));4647if (qtype == HAL_RX_QUEUE_HP) {48OS_REG_WRITE(ah, AR_HP_RXDP, rxdp);49} else {50OS_REG_WRITE(ah, AR_LP_RXDP, rxdp);51}52}5354/*55* Set Receive Enable bits.56*/57void58ar9300_enable_receive(struct ath_hal *ah)59{60OS_REG_WRITE(ah, AR_CR, 0);61}6263/*64* Set the RX abort bit.65*/66HAL_BOOL67ar9300_set_rx_abort(struct ath_hal *ah, HAL_BOOL set)68{69if (set) {70/* Set the force_rx_abort bit */71OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));7273if ( AH9300(ah)->ah_reset_reason == HAL_RESET_BBPANIC ){74/* depending upon the BB panic status, rx state may not return to 0,75* so skipping the wait for BB panic reset */76OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));77return AH_FALSE;78} else {79HAL_BOOL okay;80okay = ath_hal_wait(81ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0);82/* Wait for Rx state to return to 0 */83if (!okay) {84/* abort: chip rx failed to go idle in 10 ms */85OS_REG_CLR_BIT(ah, AR_DIAG_SW,86(AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));8788HALDEBUG(ah, HAL_DEBUG_RX,89"%s: rx failed to go idle in 10 ms RXSM=0x%x\n",90__func__, OS_REG_READ(ah, AR_OBS_BUS_1));9192return AH_FALSE; /* failure */93}94}95} else {96OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));97}9899return AH_TRUE; /* success */100}101102/*103* Stop Receive at the DMA engine104*/105HAL_BOOL106ar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout)107{108int wait;109HAL_BOOL status, okay;110u_int32_t org_value;111112#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */113#define AH_TIME_QUANTUM 100 /* usec */114115OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP);116117if (timeout == 0) {118timeout = AH_RX_STOP_DMA_TIMEOUT;119}120121org_value = OS_REG_READ(ah, AR_MACMISC);122123OS_REG_WRITE(ah, AR_MACMISC,124((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |125(AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S)));126127okay = ath_hal_wait(128ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0);129/* wait for Rx DMA state machine to become idle */130if (!okay) {131HALDEBUG(ah, HAL_DEBUG_RX,132"reg AR_DMADBG_7 is not 0, instead 0x%08x\n",133OS_REG_READ(ah, AR_DMADBG_7));134}135136/* Set receive disable bit */137OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);138139/* Wait for rx enable bit to go low */140for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) {141if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) {142break;143}144OS_DELAY(AH_TIME_QUANTUM);145}146147if (wait == 0) {148HALDEBUG(ah, HAL_DEBUG_RX, "%s: dma failed to stop in %d ms\n"149"AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",150__func__,151timeout / 1000,152OS_REG_READ(ah, AR_CR),153OS_REG_READ(ah, AR_DIAG_SW));154status = AH_FALSE;155} else {156status = AH_TRUE;157}158159OS_REG_WRITE(ah, AR_MACMISC, org_value);160161OS_MARK(ah, AH_MARK_RX_CTL,162status ? AH_MARK_RX_CTL_DMA_STOP_OK : AH_MARK_RX_CTL_DMA_STOP_ERR);163164return status;165#undef AH_RX_STOP_DMA_TIMEOUT166#undef AH_TIME_QUANTUM167}168169/*170* Start Transmit at the PCU engine (unpause receive)171*/172void173ar9300_start_pcu_receive(struct ath_hal *ah, HAL_BOOL is_scanning)174{175ar9300_enable_mib_counters(ah);176ar9300_ani_reset(ah, is_scanning);177/* Clear RX_DIS and RX_ABORT after enabling phy errors in ani_reset */178OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));179}180181/*182* Stop Transmit at the PCU engine (pause receive)183*/184void185ar9300_stop_pcu_receive(struct ath_hal *ah)186{187OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);188ar9300_disable_mib_counters(ah);189}190191/*192* Set multicast filter 0 (lower 32-bits)193* filter 1 (upper 32-bits)194*/195void196ar9300_set_multicast_filter(197struct ath_hal *ah,198u_int32_t filter0,199u_int32_t filter1)200{201OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);202OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);203}204205/*206* Get the receive filter.207*/208u_int32_t209ar9300_get_rx_filter(struct ath_hal *ah)210{211u_int32_t bits = OS_REG_READ(ah, AR_RX_FILTER);212u_int32_t phybits = OS_REG_READ(ah, AR_PHY_ERR);213if (phybits & AR_PHY_ERR_RADAR) {214bits |= HAL_RX_FILTER_PHYRADAR;215}216if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) {217bits |= HAL_RX_FILTER_PHYERR;218}219return bits;220}221222/*223* Set the receive filter.224*/225void226ar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits)227{228u_int32_t phybits;229230if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {231/* Enable Rx for 4 address frames */232bits |= AR_RX_4ADDRESS;233}234if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {235/* HW fix for rx hang and corruption. */236bits |= AR_RX_CONTROL_WRAPPER;237}238OS_REG_WRITE(ah, AR_RX_FILTER,239bits | AR_RX_UNCOM_BA_BAR | AR_RX_COMPR_BAR);240phybits = 0;241if (bits & HAL_RX_FILTER_PHYRADAR) {242phybits |= AR_PHY_ERR_RADAR;243}244if (bits & HAL_RX_FILTER_PHYERR) {245phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;246}247OS_REG_WRITE(ah, AR_PHY_ERR, phybits);248if (phybits) {249OS_REG_WRITE(ah, AR_RXCFG,250OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);251} else {252OS_REG_WRITE(ah, AR_RXCFG,253OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA);254}255}256257/*258* Select to pass PLCP headr or EVM data.259*/260HAL_BOOL261ar9300_set_rx_sel_evm(struct ath_hal *ah, HAL_BOOL sel_evm, HAL_BOOL just_query)262{263struct ath_hal_9300 *ahp = AH9300(ah);264HAL_BOOL old_value = ahp->ah_get_plcp_hdr == 0;265266if (just_query) {267return old_value;268}269if (sel_evm) {270OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);271} else {272OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);273}274275ahp->ah_get_plcp_hdr = !sel_evm;276277return old_value;278}279280void ar9300_promisc_mode(struct ath_hal *ah, HAL_BOOL enable)281{282u_int32_t reg_val = 0;283reg_val = OS_REG_READ(ah, AR_RX_FILTER);284if (enable){285reg_val |= AR_RX_PROM;286} else{ /*Disable promisc mode */287reg_val &= ~AR_RX_PROM;288}289OS_REG_WRITE(ah, AR_RX_FILTER, reg_val);290}291292void293ar9300_read_pktlog_reg(294struct ath_hal *ah,295u_int32_t *rxfilter_val,296u_int32_t *rxcfg_val,297u_int32_t *phy_err_mask_val,298u_int32_t *mac_pcu_phy_err_regval)299{300*rxfilter_val = OS_REG_READ(ah, AR_RX_FILTER);301*rxcfg_val = OS_REG_READ(ah, AR_RXCFG);302*phy_err_mask_val = OS_REG_READ(ah, AR_PHY_ERR);303*mac_pcu_phy_err_regval = OS_REG_READ(ah, 0x8338);304HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,305"%s[%d] rxfilter_val 0x%08x , rxcfg_val 0x%08x, "306"phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",307__func__, __LINE__,308*rxfilter_val, *rxcfg_val, *phy_err_mask_val, *mac_pcu_phy_err_regval);309}310311void312ar9300_write_pktlog_reg(313struct ath_hal *ah,314HAL_BOOL enable,315u_int32_t rxfilter_val,316u_int32_t rxcfg_val,317u_int32_t phy_err_mask_val,318u_int32_t mac_pcu_phy_err_reg_val)319{320if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {321/* HW fix for rx hang and corruption. */322rxfilter_val |= AR_RX_CONTROL_WRAPPER;323}324if (enable) { /* Enable pktlog phyerr setting */325OS_REG_WRITE(ah, AR_RX_FILTER, 0xffff | AR_RX_COMPR_BAR | rxfilter_val);326OS_REG_WRITE(ah, AR_PHY_ERR, 0xFFFFFFFF);327OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val | AR_RXCFG_ZLFDMA);328OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val | 0xFF);329} else { /* Disable phyerr and Restore regs */330OS_REG_WRITE(ah, AR_RX_FILTER, rxfilter_val);331OS_REG_WRITE(ah, AR_PHY_ERR, phy_err_mask_val);332OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val);333OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val);334}335HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,336"%s[%d] ena %d rxfilter_val 0x%08x , rxcfg_val 0x%08x, "337"phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",338__func__, __LINE__,339enable, rxfilter_val, rxcfg_val,340phy_err_mask_val, mac_pcu_phy_err_reg_val);341}342343344