xref: /freebsd/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
16e778a7eSPedro F. Giffuni /*-
26e778a7eSPedro F. Giffuni  * SPDX-License-Identifier: ISC
36e778a7eSPedro F. Giffuni  *
459efa8b5SSam Leffler  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
514779705SSam Leffler  * Copyright (c) 2002-2008 Atheros Communications, Inc.
614779705SSam Leffler  *
714779705SSam Leffler  * Permission to use, copy, modify, and/or distribute this software for any
814779705SSam Leffler  * purpose with or without fee is hereby granted, provided that the above
914779705SSam Leffler  * copyright notice and this permission notice appear in all copies.
1014779705SSam Leffler  *
1114779705SSam Leffler  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1214779705SSam Leffler  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1314779705SSam Leffler  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1414779705SSam Leffler  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1514779705SSam Leffler  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1614779705SSam Leffler  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1714779705SSam Leffler  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1814779705SSam Leffler  */
1914779705SSam Leffler #include "opt_ah.h"
2014779705SSam Leffler 
2114779705SSam Leffler /*
2214779705SSam Leffler  * XXX this is virtually the same code as for 5212; we reuse
2314779705SSam Leffler  * storage in the 5212 state block; need to refactor.
2414779705SSam Leffler  */
2514779705SSam Leffler #include "ah.h"
2614779705SSam Leffler #include "ah_internal.h"
2714779705SSam Leffler #include "ah_desc.h"
2814779705SSam Leffler 
2914779705SSam Leffler #include "ar5416/ar5416.h"
3014779705SSam Leffler #include "ar5416/ar5416reg.h"
3114779705SSam Leffler #include "ar5416/ar5416phy.h"
3214779705SSam Leffler 
3314779705SSam Leffler /*
3414779705SSam Leffler  * Anti noise immunity support.  We track phy errors and react
3514779705SSam Leffler  * to excessive errors by adjusting the noise immunity parameters.
3614779705SSam Leffler  */
3714779705SSam Leffler 
3814779705SSam Leffler #define HAL_EP_RND(x, mul) \
3914779705SSam Leffler 	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
4014779705SSam Leffler #define	BEACON_RSSI(ahp) \
4114779705SSam Leffler 	HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \
4214779705SSam Leffler 		HAL_RSSI_EP_MULTIPLIER)
4314779705SSam Leffler 
4414779705SSam Leffler /*
4514779705SSam Leffler  * ANI processing tunes radio parameters according to PHY errors
46*6cff32b3SGordon Bergling  * and related information.  This is done for noise and spur
4714779705SSam Leffler  * immunity in all operating modes if the device indicates it's
4814779705SSam Leffler  * capable at attach time.  In addition, when there is a reference
4914779705SSam Leffler  * rssi value (e.g. beacon frames from an ap in station mode)
5014779705SSam Leffler  * further tuning is done.
5114779705SSam Leffler  *
5214779705SSam Leffler  * ANI_ENA indicates whether any ANI processing should be done;
5314779705SSam Leffler  * this is specified at attach time.
5414779705SSam Leffler  *
5514779705SSam Leffler  * ANI_ENA_RSSI indicates whether rssi-based processing should
5614779705SSam Leffler  * done, this is enabled based on operating mode and is meaningful
5714779705SSam Leffler  * only if ANI_ENA is true.
5814779705SSam Leffler  *
5914779705SSam Leffler  * ANI parameters are typically controlled only by the hal.  The
6014779705SSam Leffler  * AniControl interface however permits manual tuning through the
6114779705SSam Leffler  * diagnostic api.
6214779705SSam Leffler  */
6314779705SSam Leffler #define ANI_ENA(ah) \
6414779705SSam Leffler 	(AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA)
6514779705SSam Leffler #define ANI_ENA_RSSI(ah) \
6614779705SSam Leffler 	(AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA)
6714779705SSam Leffler 
6814779705SSam Leffler #define	ah_mibStats	ah_stats.ast_mibstats
6914779705SSam Leffler 
7014779705SSam Leffler static void
enableAniMIBCounters(struct ath_hal * ah,const struct ar5212AniParams * params)7114779705SSam Leffler enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params)
7214779705SSam Leffler {
7314779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
7414779705SSam Leffler 
7514779705SSam Leffler 	HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: "
7614779705SSam Leffler 	    "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n",
7714779705SSam Leffler 	    __func__, params->ofdmPhyErrBase, params->cckPhyErrBase);
7814779705SSam Leffler 
7914779705SSam Leffler 	OS_REG_WRITE(ah, AR_FILTOFDM, 0);
8014779705SSam Leffler 	OS_REG_WRITE(ah, AR_FILTCCK, 0);
8114779705SSam Leffler 
8214779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase);
8314779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase);
8414779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
8514779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
8614779705SSam Leffler 
8714779705SSam Leffler 	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);	/* save+clear counters*/
8814779705SSam Leffler 	ar5212EnableMibCounters(ah);			/* enable everything */
8914779705SSam Leffler }
9014779705SSam Leffler 
9114779705SSam Leffler static void
disableAniMIBCounters(struct ath_hal * ah)9214779705SSam Leffler disableAniMIBCounters(struct ath_hal *ah)
9314779705SSam Leffler {
9414779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
9514779705SSam Leffler 
9614779705SSam Leffler 	HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n");
9714779705SSam Leffler 
9814779705SSam Leffler 	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);	/* save stats */
9914779705SSam Leffler 	ar5212DisableMibCounters(ah);			/* disable everything */
10014779705SSam Leffler 
10114779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, 0);
10214779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, 0);
10314779705SSam Leffler }
10414779705SSam Leffler 
10514779705SSam Leffler static void
setPhyErrBase(struct ath_hal * ah,struct ar5212AniParams * params)10614779705SSam Leffler setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params)
10714779705SSam Leffler {
10814779705SSam Leffler 	if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) {
10914779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
11014779705SSam Leffler 		    "OFDM Trigger %d is too high for hw counters, using max\n",
11114779705SSam Leffler 		    params->ofdmTrigHigh);
11214779705SSam Leffler 		params->ofdmPhyErrBase = 0;
11314779705SSam Leffler 	} else
11414779705SSam Leffler 		params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh;
11514779705SSam Leffler 	if (params->cckTrigHigh >= AR_PHY_COUNTMAX) {
11614779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
11714779705SSam Leffler 		    "CCK Trigger %d is too high for hw counters, using max\n",
11814779705SSam Leffler 		    params->cckTrigHigh);
11914779705SSam Leffler 		params->cckPhyErrBase = 0;
12014779705SSam Leffler 	} else
12114779705SSam Leffler 		params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh;
12214779705SSam Leffler }
12314779705SSam Leffler 
12414779705SSam Leffler /*
12514779705SSam Leffler  * Setup ANI handling.  Sets all thresholds and reset the
12614779705SSam Leffler  * channel statistics.  Note that ar5416AniReset should be
12714779705SSam Leffler  * called by ar5416Reset before anything else happens and
12814779705SSam Leffler  * that's where we force initial settings.
12914779705SSam Leffler  */
13014779705SSam Leffler void
ar5416AniAttach(struct ath_hal * ah,const struct ar5212AniParams * params24,const struct ar5212AniParams * params5,HAL_BOOL enable)13114779705SSam Leffler ar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24,
13214779705SSam Leffler 	const struct ar5212AniParams *params5, HAL_BOOL enable)
13314779705SSam Leffler {
13414779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
13514779705SSam Leffler 
13614779705SSam Leffler 	if (params24 != AH_NULL) {
13714779705SSam Leffler 		OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));
13814779705SSam Leffler 		setPhyErrBase(ah, &ahp->ah_aniParams24);
13914779705SSam Leffler 	}
14014779705SSam Leffler 	if (params5 != AH_NULL) {
14114779705SSam Leffler 		OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));
14214779705SSam Leffler 		setPhyErrBase(ah, &ahp->ah_aniParams5);
14314779705SSam Leffler 	}
14414779705SSam Leffler 
14514779705SSam Leffler 	OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));
14614779705SSam Leffler 	/* Enable MIB Counters */
14714779705SSam Leffler 	enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/);
14814779705SSam Leffler 
14914779705SSam Leffler 	if (enable) {		/* Enable ani now */
15014779705SSam Leffler 		HALASSERT(params24 != AH_NULL && params5 != AH_NULL);
15114779705SSam Leffler 		ahp->ah_procPhyErr |= HAL_ANI_ENA;
15214779705SSam Leffler 	} else {
15314779705SSam Leffler 		ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
15414779705SSam Leffler 	}
15514779705SSam Leffler }
15614779705SSam Leffler 
15714779705SSam Leffler /*
15814779705SSam Leffler  * Cleanup any ANI state setup.
159e875139aSAdrian Chadd  *
160e875139aSAdrian Chadd  * This doesn't restore registers to their default settings!
16114779705SSam Leffler  */
16214779705SSam Leffler void
ar5416AniDetach(struct ath_hal * ah)16314779705SSam Leffler ar5416AniDetach(struct ath_hal *ah)
16414779705SSam Leffler {
16514779705SSam Leffler 	HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n");
16614779705SSam Leffler 	disableAniMIBCounters(ah);
16714779705SSam Leffler }
16814779705SSam Leffler 
16914779705SSam Leffler /*
17014779705SSam Leffler  * Control Adaptive Noise Immunity Parameters
17114779705SSam Leffler  */
17214779705SSam Leffler HAL_BOOL
ar5416AniControl(struct ath_hal * ah,HAL_ANI_CMD cmd,int param)17314779705SSam Leffler ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
17414779705SSam Leffler {
17514779705SSam Leffler 	typedef int TABLE[];
17614779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
17714779705SSam Leffler 	struct ar5212AniState *aniState = ahp->ah_curani;
178e875139aSAdrian Chadd 	const struct ar5212AniParams *params = AH_NULL;
179e875139aSAdrian Chadd 
180e875139aSAdrian Chadd 	/*
181e875139aSAdrian Chadd 	 * This function may be called before there's a current
182e875139aSAdrian Chadd 	 * channel (eg to disable ANI.)
183e875139aSAdrian Chadd 	 */
184e875139aSAdrian Chadd 	if (aniState != AH_NULL)
185e875139aSAdrian Chadd 		params = aniState->params;
186e875139aSAdrian Chadd 
187e875139aSAdrian Chadd 	OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);
188e875139aSAdrian Chadd 
189e875139aSAdrian Chadd 	/* These commands can't be disabled */
190e875139aSAdrian Chadd 	if (cmd == HAL_ANI_PRESENT)
191e875139aSAdrian Chadd 		return AH_TRUE;
192e875139aSAdrian Chadd 
193e875139aSAdrian Chadd 	if (cmd == HAL_ANI_MODE) {
194e875139aSAdrian Chadd 		if (param == 0) {
195e875139aSAdrian Chadd 			ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
196e875139aSAdrian Chadd 			/* Turn off HW counters if we have them */
197e875139aSAdrian Chadd 			ar5416AniDetach(ah);
198e875139aSAdrian Chadd 		} else {			/* normal/auto mode */
199e875139aSAdrian Chadd 			/* don't mess with state if already enabled */
200e875139aSAdrian Chadd 			if (! (ahp->ah_procPhyErr & HAL_ANI_ENA)) {
201e875139aSAdrian Chadd 				/* Enable MIB Counters */
202e875139aSAdrian Chadd 				/*
203e875139aSAdrian Chadd 				 * XXX use 2.4ghz params if no channel is
204e875139aSAdrian Chadd 				 * available
205e875139aSAdrian Chadd 				 */
206e875139aSAdrian Chadd 				enableAniMIBCounters(ah,
207e875139aSAdrian Chadd 				    ahp->ah_curani != AH_NULL ?
208e875139aSAdrian Chadd 				      ahp->ah_curani->params:
209e875139aSAdrian Chadd 				      &ahp->ah_aniParams24);
210e875139aSAdrian Chadd 				ahp->ah_procPhyErr |= HAL_ANI_ENA;
211e875139aSAdrian Chadd 			}
212e875139aSAdrian Chadd 		}
213e875139aSAdrian Chadd 		return AH_TRUE;
214e875139aSAdrian Chadd 	}
21514779705SSam Leffler 
216241d9a34SAdrian Chadd 	/* Check whether the particular function is enabled */
217241d9a34SAdrian Chadd 	if (((1 << cmd) & AH5416(ah)->ah_ani_function) == 0) {
218241d9a34SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: command %d disabled\n",
219241d9a34SAdrian Chadd 		    __func__, cmd);
220241d9a34SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: cmd %d; mask %x\n", __func__, cmd, AH5416(ah)->ah_ani_function);
221241d9a34SAdrian Chadd 		return AH_FALSE;
222241d9a34SAdrian Chadd 	}
223241d9a34SAdrian Chadd 
224241d9a34SAdrian Chadd 	switch (cmd) {
22514779705SSam Leffler 	case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
22614779705SSam Leffler 		u_int level = param;
22714779705SSam Leffler 
228a108ab63SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_NOISE_IMMUNITY_LEVEL: set level = %d\n", __func__, level);
229581449cbSAdrian Chadd 		if (level > params->maxNoiseImmunityLevel) {
2304ceb8559SAdrian Chadd 			HALDEBUG(ah, HAL_DEBUG_ANI,
231f3d3bf87SRui Paulo 			    "%s: immunity level out of range (%u > %u)\n",
23214779705SSam Leffler 			    __func__, level, params->maxNoiseImmunityLevel);
23314779705SSam Leffler 			return AH_FALSE;
23414779705SSam Leffler 		}
23514779705SSam Leffler 
23614779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
23714779705SSam Leffler 		    AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]);
23814779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
23914779705SSam Leffler 		    AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]);
24014779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
24114779705SSam Leffler 		    AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]);
24214779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
24314779705SSam Leffler 		    AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]);
24414779705SSam Leffler 
24514779705SSam Leffler 		if (level > aniState->noiseImmunityLevel)
24614779705SSam Leffler 			ahp->ah_stats.ast_ani_niup++;
24714779705SSam Leffler 		else if (level < aniState->noiseImmunityLevel)
24814779705SSam Leffler 			ahp->ah_stats.ast_ani_nidown++;
24914779705SSam Leffler 		aniState->noiseImmunityLevel = level;
25014779705SSam Leffler 		break;
25114779705SSam Leffler 	}
25214779705SSam Leffler 	case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
25314779705SSam Leffler 		static const TABLE m1ThreshLow   = { 127,   50 };
25414779705SSam Leffler 		static const TABLE m2ThreshLow   = { 127,   40 };
25514779705SSam Leffler 		static const TABLE m1Thresh      = { 127, 0x4d };
25614779705SSam Leffler 		static const TABLE m2Thresh      = { 127, 0x40 };
25714779705SSam Leffler 		static const TABLE m2CountThr    = {  31,   16 };
25814779705SSam Leffler 		static const TABLE m2CountThrLow = {  63,   48 };
25914779705SSam Leffler 		u_int on = param ? 1 : 0;
26014779705SSam Leffler 
261a108ab63SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: %s\n", __func__, on ? "enabled" : "disabled");
26214779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
26314779705SSam Leffler 			AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]);
26414779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
26514779705SSam Leffler 			AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]);
26614779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
26714779705SSam Leffler 			AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]);
26814779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
26914779705SSam Leffler 			AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]);
27014779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
27114779705SSam Leffler 			AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]);
27214779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
27314779705SSam Leffler 			AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]);
27414779705SSam Leffler 
27514779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
27614779705SSam Leffler 			AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]);
27714779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
27814779705SSam Leffler 			AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]);
27914779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
28014779705SSam Leffler 			AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]);
28114779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
28214779705SSam Leffler 			AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]);
28314779705SSam Leffler 
28414779705SSam Leffler 		if (on) {
28514779705SSam Leffler 			OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
28614779705SSam Leffler 				AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
28714779705SSam Leffler 		} else {
28814779705SSam Leffler 			OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
28914779705SSam Leffler 				AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
29014779705SSam Leffler 		}
29114779705SSam Leffler 		if (on)
29214779705SSam Leffler 			ahp->ah_stats.ast_ani_ofdmon++;
29314779705SSam Leffler 		else
29414779705SSam Leffler 			ahp->ah_stats.ast_ani_ofdmoff++;
29514779705SSam Leffler 		aniState->ofdmWeakSigDetectOff = !on;
29614779705SSam Leffler 		break;
29714779705SSam Leffler 	}
29814779705SSam Leffler 	case HAL_ANI_CCK_WEAK_SIGNAL_THR: {
29914779705SSam Leffler 		static const TABLE weakSigThrCck = { 8, 6 };
30014779705SSam Leffler 		u_int high = param ? 1 : 0;
30114779705SSam Leffler 
302a108ab63SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_CCK_WEAK_SIGNAL_THR: %s\n", __func__, high ? "high" : "low");
30314779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
30414779705SSam Leffler 		    AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]);
30514779705SSam Leffler 		if (high)
30614779705SSam Leffler 			ahp->ah_stats.ast_ani_cckhigh++;
30714779705SSam Leffler 		else
30814779705SSam Leffler 			ahp->ah_stats.ast_ani_ccklow++;
30914779705SSam Leffler 		aniState->cckWeakSigThreshold = high;
31014779705SSam Leffler 		break;
31114779705SSam Leffler 	}
31214779705SSam Leffler 	case HAL_ANI_FIRSTEP_LEVEL: {
31314779705SSam Leffler 		u_int level = param;
31414779705SSam Leffler 
315a108ab63SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_FIRSTEP_LEVEL: level = %d\n", __func__, level);
316581449cbSAdrian Chadd 		if (level > params->maxFirstepLevel) {
3174ceb8559SAdrian Chadd 			HALDEBUG(ah, HAL_DEBUG_ANI,
318f3d3bf87SRui Paulo 			    "%s: firstep level out of range (%u > %u)\n",
31914779705SSam Leffler 			    __func__, level, params->maxFirstepLevel);
32014779705SSam Leffler 			return AH_FALSE;
32114779705SSam Leffler 		}
32214779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
32314779705SSam Leffler 		    AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]);
32414779705SSam Leffler 		if (level > aniState->firstepLevel)
32514779705SSam Leffler 			ahp->ah_stats.ast_ani_stepup++;
32614779705SSam Leffler 		else if (level < aniState->firstepLevel)
32714779705SSam Leffler 			ahp->ah_stats.ast_ani_stepdown++;
32814779705SSam Leffler 		aniState->firstepLevel = level;
32914779705SSam Leffler 		break;
33014779705SSam Leffler 	}
33114779705SSam Leffler 	case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
33214779705SSam Leffler 		u_int level = param;
33314779705SSam Leffler 
334a108ab63SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: HAL_ANI_SPUR_IMMUNITY_LEVEL: level = %d\n", __func__, level);
335581449cbSAdrian Chadd 		if (level > params->maxSpurImmunityLevel) {
3364ceb8559SAdrian Chadd 			HALDEBUG(ah, HAL_DEBUG_ANI,
337f3d3bf87SRui Paulo 			    "%s: spur immunity level out of range (%u > %u)\n",
33814779705SSam Leffler 			    __func__, level, params->maxSpurImmunityLevel);
33914779705SSam Leffler 			return AH_FALSE;
34014779705SSam Leffler 		}
34114779705SSam Leffler 		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5,
34214779705SSam Leffler 		    AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]);
343b657b11dSAdrian Chadd 
34414779705SSam Leffler 		if (level > aniState->spurImmunityLevel)
34514779705SSam Leffler 			ahp->ah_stats.ast_ani_spurup++;
34614779705SSam Leffler 		else if (level < aniState->spurImmunityLevel)
34714779705SSam Leffler 			ahp->ah_stats.ast_ani_spurdown++;
34814779705SSam Leffler 		aniState->spurImmunityLevel = level;
34914779705SSam Leffler 		break;
35014779705SSam Leffler 	}
35114779705SSam Leffler #ifdef AH_PRIVATE_DIAG
35214779705SSam Leffler 	case HAL_ANI_PHYERR_RESET:
35314779705SSam Leffler 		ahp->ah_stats.ast_ani_ofdmerrs = 0;
35414779705SSam Leffler 		ahp->ah_stats.ast_ani_cckerrs = 0;
35514779705SSam Leffler 		break;
35614779705SSam Leffler #endif /* AH_PRIVATE_DIAG */
35714779705SSam Leffler 	default:
3584ceb8559SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: invalid cmd %u\n",
35914779705SSam Leffler 		    __func__, cmd);
36014779705SSam Leffler 		return AH_FALSE;
36114779705SSam Leffler 	}
36214779705SSam Leffler 	return AH_TRUE;
36314779705SSam Leffler }
36414779705SSam Leffler 
36514779705SSam Leffler static void
ar5416AniOfdmErrTrigger(struct ath_hal * ah)36614779705SSam Leffler ar5416AniOfdmErrTrigger(struct ath_hal *ah)
36714779705SSam Leffler {
36814779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
36959efa8b5SSam Leffler 	const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
37014779705SSam Leffler 	struct ar5212AniState *aniState;
37114779705SSam Leffler 	const struct ar5212AniParams *params;
37214779705SSam Leffler 
37314779705SSam Leffler 	HALASSERT(chan != AH_NULL);
37414779705SSam Leffler 
37514779705SSam Leffler 	if (!ANI_ENA(ah))
37614779705SSam Leffler 		return;
37714779705SSam Leffler 
37814779705SSam Leffler 	aniState = ahp->ah_curani;
37914779705SSam Leffler 	params = aniState->params;
38014779705SSam Leffler 	/* First, raise noise immunity level, up to max */
381fcf3bb80SAdrian Chadd 	if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
382fcf3bb80SAdrian Chadd 		if (ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
383fcf3bb80SAdrian Chadd 				 aniState->noiseImmunityLevel + 1))
38414779705SSam Leffler 			return;
38514779705SSam Leffler 	}
38614779705SSam Leffler 	/* then, raise spur immunity level, up to max */
387fcf3bb80SAdrian Chadd 	if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) {
388fcf3bb80SAdrian Chadd 		if (ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
389fcf3bb80SAdrian Chadd 				 aniState->spurImmunityLevel + 1))
39014779705SSam Leffler 			return;
39114779705SSam Leffler 	}
39214779705SSam Leffler 
3937f6a8ccaSAdrian Chadd 	/*
3947f6a8ccaSAdrian Chadd 	 * In the case of AP mode operation, we cannot bucketize beacons
3957f6a8ccaSAdrian Chadd 	 * according to RSSI.  Instead, raise Firstep level, up to max, and
3967f6a8ccaSAdrian Chadd 	 * simply return.
3977f6a8ccaSAdrian Chadd 	 */
3987f6a8ccaSAdrian Chadd 	if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
3997f6a8ccaSAdrian Chadd 		if (aniState->firstepLevel < params->maxFirstepLevel) {
4007f6a8ccaSAdrian Chadd 			if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
4017f6a8ccaSAdrian Chadd 			    aniState->firstepLevel + 1))
4027f6a8ccaSAdrian Chadd 				return;
4037f6a8ccaSAdrian Chadd 		}
4047f6a8ccaSAdrian Chadd 	}
40514779705SSam Leffler 	if (ANI_ENA_RSSI(ah)) {
40614779705SSam Leffler 		int32_t rssi = BEACON_RSSI(ahp);
40714779705SSam Leffler 		if (rssi > params->rssiThrHigh) {
40814779705SSam Leffler 			/*
40914779705SSam Leffler 			 * Beacon rssi is high, can turn off ofdm
41014779705SSam Leffler 			 * weak sig detect.
41114779705SSam Leffler 			 */
41214779705SSam Leffler 			if (!aniState->ofdmWeakSigDetectOff) {
41314779705SSam Leffler 				ar5416AniControl(ah,
41414779705SSam Leffler 				    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
41514779705SSam Leffler 				    AH_FALSE);
41614779705SSam Leffler 				ar5416AniControl(ah,
41714779705SSam Leffler 				    HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
41814779705SSam Leffler 				return;
41914779705SSam Leffler 			}
42014779705SSam Leffler 			/*
42114779705SSam Leffler 			 * If weak sig detect is already off, as last resort,
42214779705SSam Leffler 			 * raise firstep level
42314779705SSam Leffler 			 */
4245b0c1ea0SAdrian Chadd 			if (aniState->firstepLevel < params->maxFirstepLevel) {
425581449cbSAdrian Chadd 				if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
426581449cbSAdrian Chadd 						 aniState->firstepLevel + 1))
42714779705SSam Leffler 					return;
42814779705SSam Leffler 			}
42914779705SSam Leffler 		} else if (rssi > params->rssiThrLow) {
43014779705SSam Leffler 			/*
43114779705SSam Leffler 			 * Beacon rssi in mid range, need ofdm weak signal
43214779705SSam Leffler 			 * detect, but we can raise firststepLevel.
43314779705SSam Leffler 			 */
43414779705SSam Leffler 			if (aniState->ofdmWeakSigDetectOff)
43514779705SSam Leffler 				ar5416AniControl(ah,
43614779705SSam Leffler 				    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
43714779705SSam Leffler 				    AH_TRUE);
4385b0c1ea0SAdrian Chadd 			if (aniState->firstepLevel < params->maxFirstepLevel)
439581449cbSAdrian Chadd 				if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
440581449cbSAdrian Chadd 				     aniState->firstepLevel + 1))
44114779705SSam Leffler 				return;
44214779705SSam Leffler 		} else {
44314779705SSam Leffler 			/*
44414779705SSam Leffler 			 * Beacon rssi is low, if in 11b/g mode, turn off ofdm
44514779705SSam Leffler 			 * weak signal detection and zero firstepLevel to
44614779705SSam Leffler 			 * maximize CCK sensitivity
44714779705SSam Leffler 			 */
44859efa8b5SSam Leffler 			if (IEEE80211_IS_CHAN_CCK(chan)) {
44914779705SSam Leffler 				if (!aniState->ofdmWeakSigDetectOff)
45014779705SSam Leffler 					ar5416AniControl(ah,
45114779705SSam Leffler 					    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
45214779705SSam Leffler 					    AH_FALSE);
45314779705SSam Leffler 				if (aniState->firstepLevel > 0)
454581449cbSAdrian Chadd 					if (ar5416AniControl(ah,
455581449cbSAdrian Chadd 					     HAL_ANI_FIRSTEP_LEVEL, 0))
45614779705SSam Leffler 						return;
45714779705SSam Leffler 			}
45814779705SSam Leffler 		}
45914779705SSam Leffler 	}
46014779705SSam Leffler }
46114779705SSam Leffler 
46214779705SSam Leffler static void
ar5416AniCckErrTrigger(struct ath_hal * ah)46314779705SSam Leffler ar5416AniCckErrTrigger(struct ath_hal *ah)
46414779705SSam Leffler {
46514779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
46659efa8b5SSam Leffler 	const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
46714779705SSam Leffler 	struct ar5212AniState *aniState;
46814779705SSam Leffler 	const struct ar5212AniParams *params;
46914779705SSam Leffler 
47014779705SSam Leffler 	HALASSERT(chan != AH_NULL);
47114779705SSam Leffler 
47214779705SSam Leffler 	if (!ANI_ENA(ah))
47314779705SSam Leffler 		return;
47414779705SSam Leffler 
47514779705SSam Leffler 	/* first, raise noise immunity level, up to max */
47614779705SSam Leffler 	aniState = ahp->ah_curani;
47714779705SSam Leffler 	params = aniState->params;
478241d9a34SAdrian Chadd 	if ((AH5416(ah)->ah_ani_function & (1 << HAL_ANI_NOISE_IMMUNITY_LEVEL) &&
479241d9a34SAdrian Chadd 	    aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel)) {
48014779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
48114779705SSam Leffler 				 aniState->noiseImmunityLevel + 1);
48214779705SSam Leffler 		return;
48314779705SSam Leffler 	}
48414779705SSam Leffler 
48514779705SSam Leffler 	if (ANI_ENA_RSSI(ah)) {
48614779705SSam Leffler 		int32_t rssi = BEACON_RSSI(ahp);
48714779705SSam Leffler 		if (rssi >  params->rssiThrLow) {
48814779705SSam Leffler 			/*
48914779705SSam Leffler 			 * Beacon signal in mid and high range,
49014779705SSam Leffler 			 * raise firstep level.
49114779705SSam Leffler 			 */
4925b0c1ea0SAdrian Chadd 			if (aniState->firstepLevel < params->maxFirstepLevel)
49314779705SSam Leffler 				ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
49414779705SSam Leffler 						 aniState->firstepLevel + 1);
49514779705SSam Leffler 		} else {
49614779705SSam Leffler 			/*
49714779705SSam Leffler 			 * Beacon rssi is low, zero firstep level to maximize
49814779705SSam Leffler 			 * CCK sensitivity in 11b/g mode.
49914779705SSam Leffler 			 */
50059efa8b5SSam Leffler 			if (IEEE80211_IS_CHAN_CCK(chan)) {
50114779705SSam Leffler 				if (aniState->firstepLevel > 0)
50214779705SSam Leffler 					ar5416AniControl(ah,
50314779705SSam Leffler 					    HAL_ANI_FIRSTEP_LEVEL, 0);
50414779705SSam Leffler 			}
50514779705SSam Leffler 		}
50614779705SSam Leffler 	}
50714779705SSam Leffler }
50814779705SSam Leffler 
50914779705SSam Leffler static void
ar5416AniRestart(struct ath_hal * ah,struct ar5212AniState * aniState)51014779705SSam Leffler ar5416AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState)
51114779705SSam Leffler {
51214779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
51314779705SSam Leffler 	const struct ar5212AniParams *params = aniState->params;
51414779705SSam Leffler 
51514779705SSam Leffler 	aniState->listenTime = 0;
51614779705SSam Leffler 	/*
51714779705SSam Leffler 	 * NB: these are written on reset based on the
51814779705SSam Leffler 	 *     ini so we must re-write them!
51914779705SSam Leffler 	 */
52014779705SSam Leffler 	HALDEBUG(ah, HAL_DEBUG_ANI,
52114779705SSam Leffler 	    "%s: Writing ofdmbase=%u   cckbase=%u\n", __func__,
52214779705SSam Leffler 	    params->ofdmPhyErrBase, params->cckPhyErrBase);
52314779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY_ERR_1, params->ofdmPhyErrBase);
52414779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY_ERR_2, params->cckPhyErrBase);
52514779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
526507de802SAdrian Chadd 	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
52714779705SSam Leffler 
52814779705SSam Leffler 	/* Clear the mib counters and save them in the stats */
52914779705SSam Leffler 	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
53014779705SSam Leffler 	aniState->ofdmPhyErrCount = 0;
53114779705SSam Leffler 	aniState->cckPhyErrCount = 0;
53214779705SSam Leffler }
53314779705SSam Leffler 
53414779705SSam Leffler /*
53514779705SSam Leffler  * Restore/reset the ANI parameters and reset the statistics.
53614779705SSam Leffler  * This routine must be called for every channel change.
53714779705SSam Leffler  *
53814779705SSam Leffler  * NOTE: This is where ah_curani is set; other ani code assumes
53914779705SSam Leffler  *       it is setup to reflect the current channel.
54014779705SSam Leffler  */
54114779705SSam Leffler void
ar5416AniReset(struct ath_hal * ah,const struct ieee80211_channel * chan,HAL_OPMODE opmode,int restore)54259efa8b5SSam Leffler ar5416AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan,
54314779705SSam Leffler 	HAL_OPMODE opmode, int restore)
54414779705SSam Leffler {
54514779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
54659efa8b5SSam Leffler 	HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
54759efa8b5SSam Leffler 	/* XXX bounds check ic_devdata */
54859efa8b5SSam Leffler 	struct ar5212AniState *aniState = &ahp->ah_ani[chan->ic_devdata];
54914779705SSam Leffler 	uint32_t rxfilter;
55014779705SSam Leffler 
55159efa8b5SSam Leffler 	if ((ichan->privFlags & CHANNEL_ANI_INIT) == 0) {
55259efa8b5SSam Leffler 		OS_MEMZERO(aniState, sizeof(*aniState));
55359efa8b5SSam Leffler 		if (IEEE80211_IS_CHAN_2GHZ(chan))
55459efa8b5SSam Leffler 			aniState->params = &ahp->ah_aniParams24;
55559efa8b5SSam Leffler 		else
55659efa8b5SSam Leffler 			aniState->params = &ahp->ah_aniParams5;
55759efa8b5SSam Leffler 		ichan->privFlags |= CHANNEL_ANI_INIT;
55859efa8b5SSam Leffler 		HALASSERT((ichan->privFlags & CHANNEL_ANI_SETUP) == 0);
55959efa8b5SSam Leffler 	}
56014779705SSam Leffler 	ahp->ah_curani = aniState;
56114779705SSam Leffler #if 0
56259efa8b5SSam Leffler 	ath_hal_printf(ah,"%s: chan %u/0x%x restore %d opmode %u%s\n",
56359efa8b5SSam Leffler 	    __func__, chan->ic_freq, chan->ic_flags, restore, opmode,
56459efa8b5SSam Leffler 	    ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : "");
56514779705SSam Leffler #else
56659efa8b5SSam Leffler 	HALDEBUG(ah, HAL_DEBUG_ANI, "%s: chan %u/0x%x restore %d opmode %u%s\n",
56759efa8b5SSam Leffler 	    __func__, chan->ic_freq, chan->ic_flags, restore, opmode,
56859efa8b5SSam Leffler 	    ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : "");
56914779705SSam Leffler #endif
57014779705SSam Leffler 	OS_MARK(ah, AH_MARK_ANI_RESET, opmode);
57114779705SSam Leffler 
57214779705SSam Leffler 	/*
57314779705SSam Leffler 	 * Turn off PHY error frame delivery while we futz with settings.
57414779705SSam Leffler 	 */
575e875139aSAdrian Chadd 	rxfilter = ah->ah_getRxFilter(ah);
576e875139aSAdrian Chadd 	ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
577e875139aSAdrian Chadd 
578e875139aSAdrian Chadd 	/*
579e875139aSAdrian Chadd 	 * If ANI is disabled at this point, don't set the default
580e875139aSAdrian Chadd 	 * ANI parameter settings - leave the HAL settings there.
581e875139aSAdrian Chadd 	 * This is (currently) needed for reliable radar detection.
582e875139aSAdrian Chadd 	 */
583e875139aSAdrian Chadd 	if (! ANI_ENA(ah)) {
584e875139aSAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n",
585e875139aSAdrian Chadd 		    __func__);
586e875139aSAdrian Chadd 		goto finish;
587e875139aSAdrian Chadd 	}
588e875139aSAdrian Chadd 
589eb81a8f6SAdrian Chadd 	/*
590eb81a8f6SAdrian Chadd 	 * Use a restrictive set of ANI parameters for hostap mode.
591eb81a8f6SAdrian Chadd 	 */
592eb81a8f6SAdrian Chadd 	if (opmode == HAL_M_HOSTAP) {
593eb81a8f6SAdrian Chadd 		if (IEEE80211_IS_CHAN_2GHZ(chan))
594eb81a8f6SAdrian Chadd 			AH5416(ah)->ah_ani_function =
595eb81a8f6SAdrian Chadd 			    HAL_ANI_SPUR_IMMUNITY_LEVEL | HAL_ANI_FIRSTEP_LEVEL;
596eb81a8f6SAdrian Chadd 		else
597eb81a8f6SAdrian Chadd 			AH5416(ah)->ah_ani_function = 0;
598eb81a8f6SAdrian Chadd 	}
599e875139aSAdrian Chadd 
60014779705SSam Leffler 	/*
60114779705SSam Leffler 	 * Automatic processing is done only in station mode right now.
60214779705SSam Leffler 	 */
60314779705SSam Leffler 	if (opmode == HAL_M_STA)
60414779705SSam Leffler 		ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA;
60514779705SSam Leffler 	else
60614779705SSam Leffler 		ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA;
60714779705SSam Leffler 	/*
60814779705SSam Leffler 	 * Set all ani parameters.  We either set them to initial
60914779705SSam Leffler 	 * values or restore the previous ones for the channel.
61014779705SSam Leffler 	 * XXX if ANI follows hardware, we don't care what mode we're
61114779705SSam Leffler 	 * XXX in, we should keep the ani parameters
61214779705SSam Leffler 	 */
61359efa8b5SSam Leffler 	if (restore && (ichan->privFlags & CHANNEL_ANI_SETUP)) {
61414779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
61514779705SSam Leffler 				 aniState->noiseImmunityLevel);
61614779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
61714779705SSam Leffler 				 aniState->spurImmunityLevel);
61814779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
61914779705SSam Leffler 				 !aniState->ofdmWeakSigDetectOff);
62014779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
62114779705SSam Leffler 				 aniState->cckWeakSigThreshold);
62214779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
62314779705SSam Leffler 				 aniState->firstepLevel);
62414779705SSam Leffler 	} else {
62514779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
62614779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
62714779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
62826ae0bb4SAdrian Chadd 			AH_FALSE);
62914779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);
63014779705SSam Leffler 		ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
63159efa8b5SSam Leffler 		ichan->privFlags |= CHANNEL_ANI_SETUP;
63214779705SSam Leffler 	}
633e875139aSAdrian Chadd 
634e875139aSAdrian Chadd 	/*
635e875139aSAdrian Chadd 	 * In case the counters haven't yet been setup; set them up.
636e875139aSAdrian Chadd 	 */
637e875139aSAdrian Chadd 	enableAniMIBCounters(ah, aniState->params);
63814779705SSam Leffler 	ar5416AniRestart(ah, aniState);
63914779705SSam Leffler 
640e875139aSAdrian Chadd finish:
64114779705SSam Leffler 	/* restore RX filter mask */
642e875139aSAdrian Chadd 	ah->ah_setRxFilter(ah, rxfilter);
64314779705SSam Leffler }
64414779705SSam Leffler 
64514779705SSam Leffler /*
64614779705SSam Leffler  * Process a MIB interrupt.  We may potentially be invoked because
64714779705SSam Leffler  * any of the MIB counters overflow/trigger so don't assume we're
64814779705SSam Leffler  * here because a PHY error counter triggered.
64914779705SSam Leffler  */
65014779705SSam Leffler void
ar5416ProcessMibIntr(struct ath_hal * ah,const HAL_NODE_STATS * stats)65114779705SSam Leffler ar5416ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats)
65214779705SSam Leffler {
65314779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
65414779705SSam Leffler 	uint32_t phyCnt1, phyCnt2;
65514779705SSam Leffler 
65614779705SSam Leffler 	HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x "
65714779705SSam Leffler 	    "filtofdm 0x%x filtcck 0x%x\n",
65814779705SSam Leffler 	    __func__, OS_REG_READ(ah, AR_MIBC),
65914779705SSam Leffler 	    OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2),
66014779705SSam Leffler 	    OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK));
66114779705SSam Leffler 
66214779705SSam Leffler 	/*
66314779705SSam Leffler 	 * First order of business is to clear whatever caused
66414779705SSam Leffler 	 * the interrupt so we don't keep getting interrupted.
66514779705SSam Leffler 	 * We have the usual mib counters that are reset-on-read
66614779705SSam Leffler 	 * and the additional counters that appeared starting in
66714779705SSam Leffler 	 * Hainan.  We collect the mib counters and explicitly
66814779705SSam Leffler 	 * zero additional counters we are not using.  Anything
66914779705SSam Leffler 	 * else is reset only if it caused the interrupt.
67014779705SSam Leffler 	 */
67114779705SSam Leffler 	/* NB: these are not reset-on-read */
67214779705SSam Leffler 	phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);
67314779705SSam Leffler 	phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);
67414779705SSam Leffler 	/* not used, always reset them in case they are the cause */
67514779705SSam Leffler 	OS_REG_WRITE(ah, AR_FILTOFDM, 0);
67614779705SSam Leffler 	OS_REG_WRITE(ah, AR_FILTCCK, 0);
67714779705SSam Leffler 	if ((OS_REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING) == 0)
67814779705SSam Leffler 		OS_REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
67914779705SSam Leffler 
68014779705SSam Leffler 	/* Clear the mib counters and save them in the stats */
68114779705SSam Leffler 	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
68214779705SSam Leffler 	ahp->ah_stats.ast_nodestats = *stats;
68314779705SSam Leffler 
68414779705SSam Leffler 	/*
68514779705SSam Leffler 	 * Check for an ani stat hitting the trigger threshold.
68614779705SSam Leffler 	 * When this happens we get a MIB interrupt and the top
68714779705SSam Leffler 	 * 2 bits of the counter register will be 0b11, hence
68814779705SSam Leffler 	 * the mask check of phyCnt?.
68914779705SSam Leffler 	 */
69014779705SSam Leffler 	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
69114779705SSam Leffler 	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
69214779705SSam Leffler 		struct ar5212AniState *aniState = ahp->ah_curani;
69314779705SSam Leffler 		const struct ar5212AniParams *params = aniState->params;
69414779705SSam Leffler 		uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
69514779705SSam Leffler 
69614779705SSam Leffler 		ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
69714779705SSam Leffler 		ahp->ah_stats.ast_ani_ofdmerrs +=
69814779705SSam Leffler 			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
69914779705SSam Leffler 		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
70014779705SSam Leffler 
70114779705SSam Leffler 		cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
70214779705SSam Leffler 		ahp->ah_stats.ast_ani_cckerrs +=
70314779705SSam Leffler 			cckPhyErrCnt - aniState->cckPhyErrCount;
70414779705SSam Leffler 		aniState->cckPhyErrCount = cckPhyErrCnt;
70514779705SSam Leffler 
70614779705SSam Leffler 		/*
70714779705SSam Leffler 		 * NB: figure out which counter triggered.  If both
70814779705SSam Leffler 		 * trigger we'll only deal with one as the processing
70914779705SSam Leffler 		 * clobbers the error counter so the trigger threshold
71014779705SSam Leffler 		 * check will never be true.
71114779705SSam Leffler 		 */
71214779705SSam Leffler 		if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh)
71314779705SSam Leffler 			ar5416AniOfdmErrTrigger(ah);
71414779705SSam Leffler 		if (aniState->cckPhyErrCount > params->cckTrigHigh)
71514779705SSam Leffler 			ar5416AniCckErrTrigger(ah);
71614779705SSam Leffler 		/* NB: always restart to insure the h/w counters are reset */
71714779705SSam Leffler 		ar5416AniRestart(ah, aniState);
71814779705SSam Leffler 	}
71914779705SSam Leffler }
72014779705SSam Leffler 
72114779705SSam Leffler static void
ar5416AniLowerImmunity(struct ath_hal * ah)72214779705SSam Leffler ar5416AniLowerImmunity(struct ath_hal *ah)
72314779705SSam Leffler {
72414779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
72514779705SSam Leffler 	struct ar5212AniState *aniState;
72614779705SSam Leffler 	const struct ar5212AniParams *params;
72714779705SSam Leffler 
72814779705SSam Leffler 	HALASSERT(ANI_ENA(ah));
72914779705SSam Leffler 
73014779705SSam Leffler 	aniState = ahp->ah_curani;
73114779705SSam Leffler 	params = aniState->params;
7327f6a8ccaSAdrian Chadd 
7337f6a8ccaSAdrian Chadd 	/*
7347f6a8ccaSAdrian Chadd 	 * In the case of AP mode operation, we cannot bucketize beacons
7357f6a8ccaSAdrian Chadd 	 * according to RSSI.  Instead, lower Firstep level, down to min, and
7367f6a8ccaSAdrian Chadd 	 * simply return.
7377f6a8ccaSAdrian Chadd 	 */
7387f6a8ccaSAdrian Chadd 	if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
7397f6a8ccaSAdrian Chadd 		if (aniState->firstepLevel > 0) {
7407f6a8ccaSAdrian Chadd 			if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
7417f6a8ccaSAdrian Chadd 			    aniState->firstepLevel - 1))
7427f6a8ccaSAdrian Chadd 				return;
7437f6a8ccaSAdrian Chadd 		}
7447f6a8ccaSAdrian Chadd 	}
74514779705SSam Leffler 	if (ANI_ENA_RSSI(ah)) {
74614779705SSam Leffler 		int32_t rssi = BEACON_RSSI(ahp);
74714779705SSam Leffler 		if (rssi > params->rssiThrHigh) {
74814779705SSam Leffler 			/*
74914779705SSam Leffler 			 * Beacon signal is high, leave ofdm weak signal
75014779705SSam Leffler 			 * detection off or it may oscillate.  Let it fall
75114779705SSam Leffler 			 * through.
75214779705SSam Leffler 			 */
75314779705SSam Leffler 		} else if (rssi > params->rssiThrLow) {
75414779705SSam Leffler 			/*
75514779705SSam Leffler 			 * Beacon rssi in mid range, turn on ofdm weak signal
75614779705SSam Leffler 			 * detection or lower firstep level.
75714779705SSam Leffler 			 */
75814779705SSam Leffler 			if (aniState->ofdmWeakSigDetectOff) {
759581449cbSAdrian Chadd 				if (ar5416AniControl(ah,
76014779705SSam Leffler 				    HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
761581449cbSAdrian Chadd 				    AH_TRUE))
76214779705SSam Leffler 					return;
76314779705SSam Leffler 			}
76414779705SSam Leffler 			if (aniState->firstepLevel > 0) {
765581449cbSAdrian Chadd 				if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
766581449cbSAdrian Chadd 						 aniState->firstepLevel - 1))
76714779705SSam Leffler 					return;
76814779705SSam Leffler 			}
76914779705SSam Leffler 		} else {
77014779705SSam Leffler 			/*
77114779705SSam Leffler 			 * Beacon rssi is low, reduce firstep level.
77214779705SSam Leffler 			 */
77314779705SSam Leffler 			if (aniState->firstepLevel > 0) {
774581449cbSAdrian Chadd 				if (ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
775581449cbSAdrian Chadd 						 aniState->firstepLevel - 1))
77614779705SSam Leffler 					return;
77714779705SSam Leffler 			}
77814779705SSam Leffler 		}
77914779705SSam Leffler 	}
78014779705SSam Leffler 	/* then lower spur immunity level, down to zero */
78114779705SSam Leffler 	if (aniState->spurImmunityLevel > 0) {
782581449cbSAdrian Chadd 		if (ar5416AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
783581449cbSAdrian Chadd 				 aniState->spurImmunityLevel - 1))
78414779705SSam Leffler 			return;
78514779705SSam Leffler 	}
78614779705SSam Leffler 	/*
78714779705SSam Leffler 	 * if all else fails, lower noise immunity level down to a min value
78814779705SSam Leffler 	 * zero for now
78914779705SSam Leffler 	 */
79014779705SSam Leffler 	if (aniState->noiseImmunityLevel > 0) {
791581449cbSAdrian Chadd 		if (ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
792581449cbSAdrian Chadd 				 aniState->noiseImmunityLevel - 1))
79314779705SSam Leffler 			return;
79414779705SSam Leffler 	}
79514779705SSam Leffler }
79614779705SSam Leffler 
79714779705SSam Leffler #define CLOCK_RATE 44000	/* XXX use mac_usec or similar */
79814779705SSam Leffler /* convert HW counter values to ms using 11g clock rate, goo9d enough
79914779705SSam Leffler    for 11a and Turbo */
80014779705SSam Leffler 
80114779705SSam Leffler /*
80214779705SSam Leffler  * Return an approximation of the time spent ``listening'' by
80314779705SSam Leffler  * deducting the cycles spent tx'ing and rx'ing from the total
80414779705SSam Leffler  * cycle count since our last call.  A return value <0 indicates
80514779705SSam Leffler  * an invalid/inconsistent time.
806af5336e3SAdrian Chadd  *
807af5336e3SAdrian Chadd  * This may be called with ANI disabled; in which case simply keep
808af5336e3SAdrian Chadd  * the statistics and don't write to the aniState pointer.
809af5336e3SAdrian Chadd  *
810af5336e3SAdrian Chadd  * XXX TODO: Make this cleaner!
81114779705SSam Leffler  */
81214779705SSam Leffler static int32_t
ar5416AniGetListenTime(struct ath_hal * ah)81314779705SSam Leffler ar5416AniGetListenTime(struct ath_hal *ah)
81414779705SSam Leffler {
81514779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
816af5336e3SAdrian Chadd 	struct ar5212AniState *aniState = NULL;
817641d61c7SAdrian Chadd 	int32_t listenTime = 0;
8182e4464a4SAdrian Chadd 	int good;
819af5336e3SAdrian Chadd 	HAL_SURVEY_SAMPLE hs;
82014779705SSam Leffler 
821af5336e3SAdrian Chadd 	/*
822af5336e3SAdrian Chadd 	 * We shouldn't see ah_curchan be NULL, but just in case..
823af5336e3SAdrian Chadd 	 */
824af5336e3SAdrian Chadd 	if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) {
825af5336e3SAdrian Chadd 		ath_hal_printf(ah, "%s: ah_curchan = NULL?\n", __func__);
826af5336e3SAdrian Chadd 		return (0);
827af5336e3SAdrian Chadd 	}
8286af85006SAdrian Chadd 
829af5336e3SAdrian Chadd 	/*
830af5336e3SAdrian Chadd 	 * Fetch the current statistics, squirrel away the current
831b0602becSAdrian Chadd 	 * sample.
832af5336e3SAdrian Chadd 	 */
833af5336e3SAdrian Chadd 	OS_MEMZERO(&hs, sizeof(hs));
834af5336e3SAdrian Chadd 	good = ar5416GetMibCycleCounts(ah, &hs);
835b0602becSAdrian Chadd 	ath_hal_survey_add_sample(ah, &hs);
836af5336e3SAdrian Chadd 
837af5336e3SAdrian Chadd 	if (ANI_ENA(ah))
83814779705SSam Leffler 		aniState = ahp->ah_curani;
839af5336e3SAdrian Chadd 
840352f07f6SAdrian Chadd 	if (good == AH_FALSE) {
84114779705SSam Leffler 		/*
84214779705SSam Leffler 		 * Cycle counter wrap (or initial call); it's not possible
84314779705SSam Leffler 		 * to accurately calculate a value because the registers
84414779705SSam Leffler 		 * right shift rather than wrap--so punt and return 0.
84514779705SSam Leffler 		 */
84614779705SSam Leffler 		listenTime = 0;
84714779705SSam Leffler 		ahp->ah_stats.ast_ani_lzero++;
848af5336e3SAdrian Chadd 	} else if (ANI_ENA(ah)) {
849af5336e3SAdrian Chadd 		/*
850af5336e3SAdrian Chadd 		 * Only calculate and update the cycle count if we have
851af5336e3SAdrian Chadd 		 * an ANI state.
852af5336e3SAdrian Chadd 		 */
853af5336e3SAdrian Chadd 		int32_t ccdelta =
854af5336e3SAdrian Chadd 		    AH5416(ah)->ah_cycleCount - aniState->cycleCount;
855af5336e3SAdrian Chadd 		int32_t rfdelta =
856af5336e3SAdrian Chadd 		    AH5416(ah)->ah_rxBusy - aniState->rxFrameCount;
857af5336e3SAdrian Chadd 		int32_t tfdelta =
858af5336e3SAdrian Chadd 		    AH5416(ah)->ah_txBusy - aniState->txFrameCount;
85914779705SSam Leffler 		listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
86014779705SSam Leffler 	}
861af5336e3SAdrian Chadd 
862af5336e3SAdrian Chadd 	/*
863af5336e3SAdrian Chadd 	 * Again, only update ANI state if we have it.
864af5336e3SAdrian Chadd 	 */
865af5336e3SAdrian Chadd 	if (ANI_ENA(ah)) {
8662e4464a4SAdrian Chadd 		aniState->cycleCount = AH5416(ah)->ah_cycleCount;
86708977788SAdrian Chadd 		aniState->rxFrameCount = AH5416(ah)->ah_rxBusy;
86808977788SAdrian Chadd 		aniState->txFrameCount = AH5416(ah)->ah_txBusy;
869af5336e3SAdrian Chadd 	}
8702e4464a4SAdrian Chadd 
87114779705SSam Leffler 	return listenTime;
87214779705SSam Leffler }
87314779705SSam Leffler 
87414779705SSam Leffler /*
87514779705SSam Leffler  * Update ani stats in preparation for listen time processing.
87614779705SSam Leffler  */
87714779705SSam Leffler static void
updateMIBStats(struct ath_hal * ah,struct ar5212AniState * aniState)87814779705SSam Leffler updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState)
87914779705SSam Leffler {
88014779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
88114779705SSam Leffler 	const struct ar5212AniParams *params = aniState->params;
88214779705SSam Leffler 	uint32_t phyCnt1, phyCnt2;
88314779705SSam Leffler 	int32_t ofdmPhyErrCnt, cckPhyErrCnt;
88414779705SSam Leffler 
88514779705SSam Leffler 	/* Clear the mib counters and save them in the stats */
88614779705SSam Leffler 	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
88714779705SSam Leffler 
88814779705SSam Leffler 	/* NB: these are not reset-on-read */
88914779705SSam Leffler 	phyCnt1 = OS_REG_READ(ah, AR_PHY_ERR_1);
89014779705SSam Leffler 	phyCnt2 = OS_REG_READ(ah, AR_PHY_ERR_2);
89114779705SSam Leffler 
89214779705SSam Leffler 	/* NB: these are spec'd to never roll-over */
89314779705SSam Leffler 	ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
89414779705SSam Leffler 	if (ofdmPhyErrCnt < 0) {
89514779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n",
89614779705SSam Leffler 		    ofdmPhyErrCnt, phyCnt1);
89714779705SSam Leffler 		ofdmPhyErrCnt = AR_PHY_COUNTMAX;
89814779705SSam Leffler 	}
89914779705SSam Leffler 	ahp->ah_stats.ast_ani_ofdmerrs +=
90014779705SSam Leffler 	     ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
90114779705SSam Leffler 	aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
90214779705SSam Leffler 
90314779705SSam Leffler 	cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
90414779705SSam Leffler 	if (cckPhyErrCnt < 0) {
90514779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n",
90614779705SSam Leffler 		    cckPhyErrCnt, phyCnt2);
90714779705SSam Leffler 		cckPhyErrCnt = AR_PHY_COUNTMAX;
90814779705SSam Leffler 	}
90914779705SSam Leffler 	ahp->ah_stats.ast_ani_cckerrs +=
91014779705SSam Leffler 		cckPhyErrCnt - aniState->cckPhyErrCount;
91114779705SSam Leffler 	aniState->cckPhyErrCount = cckPhyErrCnt;
91214779705SSam Leffler }
91314779705SSam Leffler 
914a108ab63SAdrian Chadd void
ar5416RxMonitor(struct ath_hal * ah,const HAL_NODE_STATS * stats,const struct ieee80211_channel * chan)915a108ab63SAdrian Chadd ar5416RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats,
916a108ab63SAdrian Chadd 		const struct ieee80211_channel *chan)
917a108ab63SAdrian Chadd {
918a108ab63SAdrian Chadd 	struct ath_hal_5212 *ahp = AH5212(ah);
919a108ab63SAdrian Chadd 	ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi;
920a108ab63SAdrian Chadd }
921a108ab63SAdrian Chadd 
92214779705SSam Leffler /*
92314779705SSam Leffler  * Do periodic processing.  This routine is called from the
92414779705SSam Leffler  * driver's rx interrupt handler after processing frames.
92514779705SSam Leffler  */
92614779705SSam Leffler void
ar5416AniPoll(struct ath_hal * ah,const struct ieee80211_channel * chan)927a108ab63SAdrian Chadd ar5416AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
92814779705SSam Leffler {
92914779705SSam Leffler 	struct ath_hal_5212 *ahp = AH5212(ah);
93014779705SSam Leffler 	struct ar5212AniState *aniState = ahp->ah_curani;
93114779705SSam Leffler 	const struct ar5212AniParams *params;
93214779705SSam Leffler 	int32_t listenTime;
93314779705SSam Leffler 
934af5336e3SAdrian Chadd 	/* Always update from the MIB, for statistics gathering */
935af5336e3SAdrian Chadd 	listenTime = ar5416AniGetListenTime(ah);
936af5336e3SAdrian Chadd 
93714779705SSam Leffler 	/* XXX can aniState be null? */
93814779705SSam Leffler 	if (aniState == AH_NULL)
93914779705SSam Leffler 		return;
9402e4464a4SAdrian Chadd 
94114779705SSam Leffler 	if (!ANI_ENA(ah))
94214779705SSam Leffler 		return;
94314779705SSam Leffler 
94414779705SSam Leffler 	if (listenTime < 0) {
94514779705SSam Leffler 		ahp->ah_stats.ast_ani_lneg++;
94614779705SSam Leffler 		/* restart ANI period if listenTime is invalid */
9475b0c1ea0SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: invalid listenTime\n",
9485b0c1ea0SAdrian Chadd 		    __func__);
94914779705SSam Leffler 		ar5416AniRestart(ah, aniState);
9507b1c2c4eSAdrian Chadd 
9517b1c2c4eSAdrian Chadd 		/* Don't do any further processing */
9527b1c2c4eSAdrian Chadd 		return;
95314779705SSam Leffler 	}
95414779705SSam Leffler 	/* XXX beware of overflow? */
95514779705SSam Leffler 	aniState->listenTime += listenTime;
95614779705SSam Leffler 
95714779705SSam Leffler 	OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime);
95814779705SSam Leffler 
95914779705SSam Leffler 	params = aniState->params;
96014779705SSam Leffler 	if (aniState->listenTime > 5*params->period) {
96114779705SSam Leffler 		/*
96214779705SSam Leffler 		 * Check to see if need to lower immunity if
96314779705SSam Leffler 		 * 5 aniPeriods have passed
96414779705SSam Leffler 		 */
96514779705SSam Leffler 		updateMIBStats(ah, aniState);
96614779705SSam Leffler 		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
96714779705SSam Leffler 		    params->ofdmTrigLow/1000 &&
96814779705SSam Leffler 		    aniState->cckPhyErrCount <= aniState->listenTime *
96914779705SSam Leffler 		    params->cckTrigLow/1000)
97014779705SSam Leffler 			ar5416AniLowerImmunity(ah);
9715b0c1ea0SAdrian Chadd 		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower immunity\n",
9725b0c1ea0SAdrian Chadd 		    __func__);
97314779705SSam Leffler 		ar5416AniRestart(ah, aniState);
97414779705SSam Leffler 	} else if (aniState->listenTime > params->period) {
97514779705SSam Leffler 		updateMIBStats(ah, aniState);
97614779705SSam Leffler 		/* check to see if need to raise immunity */
97714779705SSam Leffler 		if (aniState->ofdmPhyErrCount > aniState->listenTime *
97814779705SSam Leffler 		    params->ofdmTrigHigh / 1000) {
9799082beb0SAdrian Chadd                         HALDEBUG(ah, HAL_DEBUG_ANI,
9809082beb0SAdrian Chadd                             "%s: OFDM err %u listenTime %u\n", __func__,
9819082beb0SAdrian Chadd                             aniState->ofdmPhyErrCount, aniState->listenTime);
98214779705SSam Leffler 			ar5416AniOfdmErrTrigger(ah);
98314779705SSam Leffler 			ar5416AniRestart(ah, aniState);
98414779705SSam Leffler 		} else if (aniState->cckPhyErrCount > aniState->listenTime *
98514779705SSam Leffler 			   params->cckTrigHigh / 1000) {
9869082beb0SAdrian Chadd                         HALDEBUG(ah, HAL_DEBUG_ANI,
9879082beb0SAdrian Chadd                             "%s: CCK err %u listenTime %u\n", __func__,
988810f2a9cSAdrian Chadd                             aniState->cckPhyErrCount, aniState->listenTime);
98914779705SSam Leffler 			ar5416AniCckErrTrigger(ah);
99014779705SSam Leffler 			ar5416AniRestart(ah, aniState);
99114779705SSam Leffler 		}
99214779705SSam Leffler 	}
99314779705SSam Leffler }
994