Path: blob/main/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c
39566 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2002-2008 Sam Leffler, Errno Consulting4* Copyright (c) 2002-2008 Atheros Communications, Inc.5*6* Permission to use, copy, modify, and/or distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF16* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/18#include "opt_ah.h"1920#include "ah.h"21#include "ah_desc.h"22#include "ah_internal.h"2324#include "ar5416/ar5416.h"25#include "ar5416/ar5416reg.h"26#include "ar5416/ar5416desc.h"2728/*29* Get the receive filter.30*/31uint32_t32ar5416GetRxFilter(struct ath_hal *ah)33{34uint32_t bits = OS_REG_READ(ah, AR_RX_FILTER);35uint32_t phybits = OS_REG_READ(ah, AR_PHY_ERR);3637if (phybits & AR_PHY_ERR_RADAR)38bits |= HAL_RX_FILTER_PHYRADAR;39if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))40bits |= HAL_RX_FILTER_PHYERR;41return bits;42}4344/*45* Set the receive filter.46*/47void48ar5416SetRxFilter(struct ath_hal *ah, u_int32_t bits)49{50uint32_t phybits;5152OS_REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff));53phybits = 0;54if (bits & HAL_RX_FILTER_PHYRADAR)55phybits |= AR_PHY_ERR_RADAR;56if (bits & HAL_RX_FILTER_PHYERR)57phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;58OS_REG_WRITE(ah, AR_PHY_ERR, phybits);59if (phybits) {60OS_REG_WRITE(ah, AR_RXCFG,61OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);62} else {63OS_REG_WRITE(ah, AR_RXCFG,64OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA);65}66}6768/*69* Stop Receive at the DMA engine70*/71HAL_BOOL72ar5416StopDmaReceive(struct ath_hal *ah)73{74HAL_BOOL status;7576OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP);77OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); /* Set receive disable bit */78if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0)) {79OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP_ERR);80#ifdef AH_DEBUG81ath_hal_printf(ah, "%s: dma failed to stop in 10ms\n"82"AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",83__func__,84OS_REG_READ(ah, AR_CR),85OS_REG_READ(ah, AR_DIAG_SW));86#endif87status = AH_FALSE;88} else {89status = AH_TRUE;90}9192/*93* XXX Is this to flush whatever is in a FIFO somewhere?94* XXX If so, what should the correct behaviour should be?95*/96if (AR_SREV_9100(ah))97OS_DELAY(3000);9899return (status);100}101102/*103* Start receive at the PCU engine104*/105void106ar5416StartPcuReceive(struct ath_hal *ah, HAL_BOOL is_scanning)107{108struct ath_hal_private *ahp = AH_PRIVATE(ah);109110HALDEBUG(ah, HAL_DEBUG_RX, "%s: Start PCU Receive \n", __func__);111ar5212EnableMibCounters(ah);112/* NB: restore current settings if we're not scanning */113ar5416AniReset(ah, ahp->ah_curchan, ahp->ah_opmode, ! is_scanning);114/*115* NB: must do after enabling phy errors to avoid rx116* frames w/ corrupted descriptor status.117*/118OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);119}120121/*122* Stop receive at the PCU engine123* and abort current frame in PCU124*/125void126ar5416StopPcuReceive(struct ath_hal *ah)127{128OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);129130HALDEBUG(ah, HAL_DEBUG_RX, "%s: Stop PCU Receive \n", __func__);131ar5212DisableMibCounters(ah);132}133134/*135* Initialize RX descriptor, by clearing the status and setting136* the size (and any other flags).137*/138HAL_BOOL139ar5416SetupRxDesc(struct ath_hal *ah, struct ath_desc *ds,140uint32_t size, u_int flags)141{142struct ar5416_desc *ads = AR5416DESC(ds);143144HALASSERT((size &~ AR_BufLen) == 0);145146ads->ds_ctl1 = size & AR_BufLen;147if (flags & HAL_RXDESC_INTREQ)148ads->ds_ctl1 |= AR_RxIntrReq;149150/* this should be enough */151ads->ds_rxstatus8 &= ~AR_RxDone;152153/* clear the rest of the status fields */154OS_MEMZERO(&(ads->u), sizeof(ads->u));155156return AH_TRUE;157}158159/*160* Process an RX descriptor, and return the status to the caller.161* Copy some hardware specific items into the software portion162* of the descriptor.163*164* NB: the caller is responsible for validating the memory contents165* of the descriptor (e.g. flushing any cached copy).166*/167HAL_STATUS168ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,169uint32_t pa, struct ath_desc *nds, uint64_t tsf,170struct ath_rx_status *rs)171{172struct ar5416_desc *ads = AR5416DESC(ds);173174if ((ads->ds_rxstatus8 & AR_RxDone) == 0)175return HAL_EINPROGRESS;176177rs->rs_status = 0;178rs->rs_flags = 0;179180rs->rs_datalen = ads->ds_rxstatus1 & AR_DataLen;181rs->rs_tstamp = ads->AR_RcvTimestamp;182183rs->rs_rssi = MS(ads->ds_rxstatus4, AR_RxRSSICombined);184rs->rs_rssi_ctl[0] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt00);185rs->rs_rssi_ctl[1] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt01);186rs->rs_rssi_ctl[2] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt02);187rs->rs_rssi_ext[0] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt10);188rs->rs_rssi_ext[1] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt11);189rs->rs_rssi_ext[2] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt12);190191if (ads->ds_rxstatus8 & AR_RxKeyIdxValid)192rs->rs_keyix = MS(ads->ds_rxstatus8, AR_KeyIdx);193else194rs->rs_keyix = HAL_RXKEYIX_INVALID;195196/* NB: caller expected to do rate table mapping */197rs->rs_rate = RXSTATUS_RATE(ah, ads);198rs->rs_more = (ads->ds_rxstatus1 & AR_RxMore) ? 1 : 0;199200rs->rs_isaggr = (ads->ds_rxstatus8 & AR_RxAggr) ? 1 : 0;201rs->rs_moreaggr = (ads->ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;202rs->rs_antenna = MS(ads->ds_rxstatus3, AR_RxAntenna);203204if (ads->ds_rxstatus3 & AR_GI)205rs->rs_flags |= HAL_RX_GI;206if (ads->ds_rxstatus3 & AR_2040)207rs->rs_flags |= HAL_RX_2040;208209/*210* Only the AR9280 and later chips support STBC RX, so211* ensure we only set this bit for those chips.212*/213if (AR_SREV_MERLIN_10_OR_LATER(ah)214&& ads->ds_rxstatus3 & AR_STBCFrame)215rs->rs_flags |= HAL_RX_STBC;216217if (ads->ds_rxstatus8 & AR_PreDelimCRCErr)218rs->rs_flags |= HAL_RX_DELIM_CRC_PRE;219if (ads->ds_rxstatus8 & AR_PostDelimCRCErr)220rs->rs_flags |= HAL_RX_DELIM_CRC_POST;221if (ads->ds_rxstatus8 & AR_DecryptBusyErr)222rs->rs_flags |= HAL_RX_DECRYPT_BUSY;223if (ads->ds_rxstatus8 & AR_HiRxChain)224rs->rs_flags |= HAL_RX_HI_RX_CHAIN;225226if ((ads->ds_rxstatus8 & AR_RxFrameOK) == 0) {227/*228* These four bits should not be set together. The229* 5416 spec states a Michael error can only occur if230* DecryptCRCErr not set (and TKIP is used). Experience231* indicates however that you can also get Michael errors232* when a CRC error is detected, but these are specious.233* Consequently we filter them out here so we don't234* confuse and/or complicate drivers.235*/236237/*238* The AR5416 sometimes sets both AR_CRCErr and AR_PHYErr239* when reporting radar pulses. In this instance240* set HAL_RXERR_PHY as well as HAL_RXERR_CRC and241* let the driver layer figure out what to do.242*243* See PR kern/169362.244*/245if (ads->ds_rxstatus8 & AR_PHYErr) {246u_int phyerr;247248/*249* Packets with OFDM_RESTART on post delimiter are CRC OK and250* usable and MAC ACKs them.251* To avoid packet from being lost, we remove the PHY Err flag252* so that driver layer does not drop them.253*/254phyerr = MS(ads->ds_rxstatus8, AR_PHYErrCode);255256if ((phyerr == HAL_PHYERR_OFDM_RESTART) &&257(ads->ds_rxstatus8 & AR_PostDelimCRCErr)) {258ath_hal_printf(ah,259"%s: OFDM_RESTART on post-delim CRC error\n",260__func__);261rs->rs_phyerr = 0;262} else {263rs->rs_status |= HAL_RXERR_PHY;264rs->rs_phyerr = phyerr;265}266}267if (ads->ds_rxstatus8 & AR_CRCErr)268rs->rs_status |= HAL_RXERR_CRC;269else if (ads->ds_rxstatus8 & AR_DecryptCRCErr)270rs->rs_status |= HAL_RXERR_DECRYPT;271else if (ads->ds_rxstatus8 & AR_MichaelErr)272rs->rs_status |= HAL_RXERR_MIC;273}274275if (ads->ds_rxstatus8 & AR_KeyMiss)276rs->rs_status |= HAL_RXERR_KEYMISS;277278return HAL_OK;279}280281282