Example #1
0
void 
ar5212AniPhyErrReport(struct ath_hal *ah, const struct ath_rx_status *rs)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState;
	const struct ar5212AniParams *params;

	HALASSERT(!ahp->ah_hasHwPhyCounters && rs != AH_NULL);

	aniState = ahp->ah_curani;
	params = aniState->params;
	if (rs->rs_phyerr == HAL_PHYERR_OFDM_TIMING) {
		aniState->ofdmPhyErrCount++;
		ahp->ah_stats.ast_ani_ofdmerrs++;
		if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) {
			ar5212AniOfdmErrTrigger(ah);
			ar5212AniRestart(ah, aniState);
		}
	} else if (rs->rs_phyerr == HAL_PHYERR_CCK_TIMING) {
		aniState->cckPhyErrCount++;
		ahp->ah_stats.ast_ani_cckerrs++;
		if (aniState->cckPhyErrCount > params->cckTrigHigh) {
			ar5212AniCckErrTrigger(ah);
			ar5212AniRestart(ah, aniState);
		}
	}
}
Example #2
0
/*
 * Do periodic processing.  This routine is called from the
 * driver's rx interrupt handler after processing frames.
 */
void
ar5212AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState = ahp->ah_curani;
	const struct ar5212AniParams *params;
	int32_t listenTime;

	/* XXX can aniState be null? */
	if (aniState == AH_NULL)
		return;
	if (!ANI_ENA(ah))
		return;

	listenTime = ar5212AniGetListenTime(ah);
	if (listenTime < 0) {
		ahp->ah_stats.ast_ani_lneg++;
		/* restart ANI period if listenTime is invalid */
		ar5212AniRestart(ah, aniState);
	}
	/* XXX beware of overflow? */
	aniState->listenTime += listenTime;

	OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime);

	params = aniState->params;
	if (aniState->listenTime > 5*params->period) {
		/* 
		 * Check to see if need to lower immunity if
		 * 5 aniPeriods have passed
		 */
		if (ahp->ah_hasHwPhyCounters)
			updateMIBStats(ah, aniState);
		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
		    params->ofdmTrigLow/1000 &&
		    aniState->cckPhyErrCount <= aniState->listenTime *
		    params->cckTrigLow/1000)
			ar5212AniLowerImmunity(ah);
		ar5212AniRestart(ah, aniState);
	} else if (aniState->listenTime > params->period) {
		if (ahp->ah_hasHwPhyCounters)
			updateMIBStats(ah, aniState);
		/* check to see if need to raise immunity */
		if (aniState->ofdmPhyErrCount > aniState->listenTime *
		    params->ofdmTrigHigh / 1000) {
			HALDEBUG(ah, HAL_DEBUG_ANI,
			    "%s: OFDM err %u listenTime %u\n", __func__,
			    aniState->ofdmPhyErrCount, aniState->listenTime);
			ar5212AniOfdmErrTrigger(ah);
			ar5212AniRestart(ah, aniState);
		} else if (aniState->cckPhyErrCount > aniState->listenTime *
			   params->cckTrigHigh / 1000) {
			HALDEBUG(ah, HAL_DEBUG_ANI,
			    "%s: CCK err %u listenTime %u\n", __func__,
			    aniState->cckPhyErrCount, aniState->listenTime);
			ar5212AniCckErrTrigger(ah);
			ar5212AniRestart(ah, aniState);
		}
	}
}
Example #3
0
/*
 * Process a MIB interrupt.  We may potentially be invoked because
 * any of the MIB counters overflow/trigger so don't assume we're
 * here because a PHY error counter triggered.
 */
void
ar5212ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	u_int32_t phyCnt1, phyCnt2;

	HALDEBUG(ah, "Processing Mib Intr\n");
	/* Reset these counters regardless */
	OS_REG_WRITE(ah, AR_FILTOFDM, 0);
	OS_REG_WRITE(ah, AR_FILTCCK, 0);

	/* Clear the mib counters and save them in the stats */
	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
	ahp->ah_stats.ast_nodestats = *stats;

	/* NB: these are not reset-on-read */
	phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1);
	phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2);
	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || 
	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
		struct ar5212AniState *aniState = ahp->ah_curani;
		u_int32_t ofdmPhyErrCnt, cckPhyErrCnt;

		/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
		ahp->ah_stats.ast_ani_ofdmerrs +=
			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;

		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
		ahp->ah_stats.ast_ani_cckerrs +=
			cckPhyErrCnt - aniState->cckPhyErrCount;
		aniState->cckPhyErrCount = cckPhyErrCnt;

		/*
		 * NB: figure out which counter triggered.  If both
		 * trigger we'll only deal with one as the processing
		 * clobbers the error counter so the trigger threshold
		 * check will never be true.
		 */
		if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
			ar5212AniOfdmErrTrigger(ah);
		if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
			ar5212AniCckErrTrigger(ah);
		/* NB: always restart to insure the h/w counters are reset */
		ar5212AniRestart(ah);
	}
}
Example #4
0
/*
 * Process a MIB interrupt.  We may potentially be invoked because
 * any of the MIB counters overflow/trigger so don't assume we're
 * here because a PHY error counter triggered.
 */
void
ar5212ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	uint32_t phyCnt1, phyCnt2;

	HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x "
	    "filtofdm 0x%x filtcck 0x%x\n",
	    __func__, OS_REG_READ(ah, AR_MIBC),
	    OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2),
	    OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK));

	/*
	 * First order of business is to clear whatever caused
	 * the interrupt so we don't keep getting interrupted.
	 * We have the usual mib counters that are reset-on-read
	 * and the additional counters that appeared starting in
	 * Hainan.  We collect the mib counters and explicitly
	 * zero additional counters we are not using.  Anything
	 * else is reset only if it caused the interrupt.
	 */
	/* NB: these are not reset-on-read */
	phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1);
	phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2);
	/* not used, always reset them in case they are the cause */
	OS_REG_WRITE(ah, AR_FILTOFDM, 0);
	OS_REG_WRITE(ah, AR_FILTCCK, 0);

	/* Clear the mib counters and save them in the stats */
	ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
	ahp->ah_stats.ast_nodestats = *stats;

	/*
	 * Check for an ani stat hitting the trigger threshold.
	 * When this happens we get a MIB interrupt and the top
	 * 2 bits of the counter register will be 0b11, hence
	 * the mask check of phyCnt?.
	 */
	if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || 
	    ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
		struct ar5212AniState *aniState = ahp->ah_curani;
		const struct ar5212AniParams *params = aniState->params;
		uint32_t ofdmPhyErrCnt, cckPhyErrCnt;

		ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
		ahp->ah_stats.ast_ani_ofdmerrs +=
			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;

		cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
		ahp->ah_stats.ast_ani_cckerrs +=
			cckPhyErrCnt - aniState->cckPhyErrCount;
		aniState->cckPhyErrCount = cckPhyErrCnt;

		/*
		 * NB: figure out which counter triggered.  If both
		 * trigger we'll only deal with one as the processing
		 * clobbers the error counter so the trigger threshold
		 * check will never be true.
		 */
		if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh)
			ar5212AniOfdmErrTrigger(ah);
		if (aniState->cckPhyErrCount > params->cckTrigHigh)
			ar5212AniCckErrTrigger(ah);
		/* NB: always restart to insure the h/w counters are reset */
		ar5212AniRestart(ah, aniState);
	}
}
Example #5
0
/*
 * Restore/reset the ANI parameters and reset the statistics.
 * This routine must be called for every channel change.
 */
void
ar5212AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan,
	HAL_OPMODE opmode, int restore)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
	/* XXX bounds check ic_devdata */
	struct ar5212AniState *aniState = &ahp->ah_ani[chan->ic_devdata];
	uint32_t rxfilter;

	if ((ichan->privFlags & CHANNEL_ANI_INIT) == 0) {
		OS_MEMZERO(aniState, sizeof(*aniState));
		if (IEEE80211_IS_CHAN_2GHZ(chan))
			aniState->params = &ahp->ah_aniParams24;
		else
			aniState->params = &ahp->ah_aniParams5;
		ichan->privFlags |= CHANNEL_ANI_INIT;
		HALASSERT((ichan->privFlags & CHANNEL_ANI_SETUP) == 0);
	}
	ahp->ah_curani = aniState;
#if 0
	ath_hal_printf(ah,"%s: chan %u/0x%x restore %d opmode %u%s\n",
	    __func__, chan->ic_freq, chan->ic_flags, restore, opmode,
	    ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : "");
#else
	HALDEBUG(ah, HAL_DEBUG_ANI, "%s: chan %u/0x%x restore %d opmode %u%s\n",
	    __func__, chan->ic_freq, chan->ic_flags, restore, opmode,
	    ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : "");
#endif
	OS_MARK(ah, AH_MARK_ANI_RESET, opmode);

	/*
	 * Turn off PHY error frame delivery while we futz with settings.
	 */
	rxfilter = ah->ah_getRxFilter(ah);
	ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);

	/*
	 * If ANI is disabled at this point, don't set the default
	 * ANI parameter settings - leave the HAL settings there.
	 * This is (currently) needed for reliable radar detection.
	 */
	if (! ANI_ENA(ah)) {
		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n",
		    __func__);
		goto finish;
	}

	/*
	 * Automatic processing is done only in station mode right now.
	 */
	if (opmode == HAL_M_STA)
		ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA;
	else
		ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA;
	/*
	 * Set all ani parameters.  We either set them to initial
	 * values or restore the previous ones for the channel.
	 * XXX if ANI follows hardware, we don't care what mode we're
	 * XXX in, we should keep the ani parameters
	 */
	if (restore && (ichan->privFlags & CHANNEL_ANI_SETUP)) {
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
				 aniState->noiseImmunityLevel);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
				 aniState->spurImmunityLevel);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				 !aniState->ofdmWeakSigDetectOff);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
				 aniState->cckWeakSigThreshold);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
				 aniState->firstepLevel);
	} else {
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
			AH_TRUE);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
		ichan->privFlags |= CHANNEL_ANI_SETUP;
	}
	/*
	 * In case the counters haven't yet been setup; set them up.
	 */
	enableAniMIBCounters(ah, ahp->ah_curani->params);
	ar5212AniRestart(ah, aniState);

finish:
	/* restore RX filter mask */
	ah->ah_setRxFilter(ah, rxfilter);
}
Example #6
0
/*
 * Do periodic processing.  This routine is called from the
 * driver's rx interrupt handler after processing frames.
 */
void
ar5212AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState;
	int32_t listenTime;

	aniState = ahp->ah_curani;
	ahp->ah_stats.ast_nodestats = *stats;		/* XXX optimize? */

	listenTime = ar5212AniGetListenTime(ah);
	if (listenTime < 0) {
		ahp->ah_stats.ast_ani_lneg++;
		/* restart ANI period if listenTime is invalid */
		ar5212AniRestart(ah);
		return;
	}
	/* XXX beware of overflow? */
	aniState->listenTime += listenTime;

	if (ahp->ah_hasHwPhyCounters) {
		u_int32_t phyCnt1, phyCnt2;
		u_int32_t ofdmPhyErrCnt, cckPhyErrCnt;

		/* Clear the mib counters and save them in the stats */
		ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
		/* NB: these are not reset-on-read */
		phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1);
		phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2);
		/* XXX sometimes zero, why? */
		if (phyCnt1 < aniState->ofdmPhyErrBase ||
		    phyCnt2 < aniState->cckPhyErrBase) {
			if (phyCnt1 < aniState->ofdmPhyErrBase) {
				ath_hal_printf(ah, "%s: phyCnt1 0x%x, resetting "
					"counter value to 0x%x\n", __func__,
					phyCnt1, aniState->ofdmPhyErrBase);
				OS_REG_WRITE(ah, AR_PHYCNT1, aniState->ofdmPhyErrBase);
				OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);
			}
			if (phyCnt2 < aniState->cckPhyErrBase) {
				ath_hal_printf(ah, "%s: phyCnt2 0x%x, resetting "
					"counter value to 0x%x\n", __func__,
					phyCnt2, aniState->cckPhyErrBase);
				OS_REG_WRITE(ah, AR_PHYCNT2, aniState->cckPhyErrBase);
				OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);
			}
			return;		/* XXX */
		}
		/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
		ahp->ah_stats.ast_ani_ofdmerrs +=
			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;

		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
		ahp->ah_stats.ast_ani_cckerrs +=
			cckPhyErrCnt - aniState->cckPhyErrCount;
		aniState->cckPhyErrCount = cckPhyErrCnt;
	}
	/*
	 * If ani is not enabled, return after we've collected
	 * statistics
	 */
	if (!(DO_ANI(ah) && AH_PRIVATE(ah)->ah_opmode == HAL_M_STA))
		return;
	if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
		/* 
		 * Check to see if need to lower immunity if
		 * 5 aniPeriods have passed
		 */
		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
		     aniState->ofdmTrigLow/1000 &&
		    aniState->cckPhyErrCount <= aniState->listenTime *
		     aniState->cckTrigLow/1000)
			ar5212AniLowerImmunity(ah);
		ar5212AniRestart(ah);
	} else if (aniState->listenTime > ahp->ah_aniPeriod) {
		/* check to see if need to raise immunity */
		if (aniState->ofdmPhyErrCount > aniState->listenTime *
		    aniState->ofdmTrigHigh / 1000) {
			ar5212AniOfdmErrTrigger(ah);
			ar5212AniRestart(ah);
		} else if (aniState->cckPhyErrCount > aniState->listenTime *
			   aniState->cckTrigHigh / 1000) {
			ar5212AniCckErrTrigger(ah);
			ar5212AniRestart(ah);
		}
	}
}
Example #7
0
/*
 * Restore the ANI parameters in the HAL and reset the statistics.
 * This routine should be called for every hardware reset and for
 * every channel change.  NOTE: This must be called for every channel
 * change for ah_curani to be set correctly.
 */
void
ar5212AniReset(struct ath_hal *ah)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState;
	HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
	int index;

	HALASSERT(chan != AH_NULL);

	index = ar5212GetAniChannelIndex(ah, chan);
	aniState = &ahp->ah_ani[index];
	ahp->ah_curani = aniState;

	/*
	 * ANI is enabled but we're not operating in station
	 * mode.  Reset all parameters.  This can happen, for
	 * example, when starting up AP operation.
	 */
	if (DO_ANI(ah) && AH_PRIVATE(ah)->ah_opmode != HAL_M_STA) {
		HALDEBUG(ah,"%s: Reset ANI state opmode %u\n",
			__func__, AH_PRIVATE(ah)->ah_opmode);
		ahp->ah_stats.ast_ani_reset++;
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
			!HAL_ANI_USE_OFDM_WEAK_SIG);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
			HAL_ANI_CCK_WEAK_SIG_THR);
		/* NB: enable phy frames so the driver gets stats */
		ar5212SetRxFilter(ah,
			ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR);
		ar5212AniRestart(ah);
		return;
	}

	if (aniState->noiseImmunityLevel != 0)
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
				 aniState->noiseImmunityLevel);
	if (aniState->spurImmunityLevel != 0)
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
				 aniState->spurImmunityLevel);
	if (aniState->ofdmWeakSigDetectOff)
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				 !aniState->ofdmWeakSigDetectOff);
	if (aniState->cckWeakSigThreshold)
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
				 aniState->cckWeakSigThreshold);
	if (aniState->firstepLevel != 0)
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel);
	if (ahp->ah_hasHwPhyCounters) {
		ar5212SetRxFilter(ah,
			  ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
		ar5212AniRestart(ah);
		OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);
		OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);

	} else {
		ar5212AniRestart(ah);
		ar5212SetRxFilter(ah, ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR);
	}
}
Example #8
0
/*
 * Do periodic processing.  This routine is called from the
 * driver's rx interrupt handler after processing frames.
 */
void
ar5212AniArPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats,
		HAL_CHANNEL *chan, HAL_ANISTATS *ani_stats)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState;
	int32_t listenTime;

    /*
	 * If ani is not enabled, return after we've collected
	 * statistics
	 */
	if (!(DO_ANI(ah)))
    {
		HDPRINTF(ah, HAL_DBG_ANI, "<=No ANI\n");
        return;
    }

 	/* sanity check for uninitialized state */
 	if (ahp->ah_curani == AH_NULL)
 		return;

	/* 
 	 * Since we're called from end of rx tasklet, we also check for
 	 * AR processing now
 	 */
	aniState = ahp->ah_curani;

    aniState->rssi = stats->ns_avgbrssi;

	if (ahp->ah_hasHwPhyCounters) {
		u_int32_t phyCnt1, phyCnt2;
		u_int32_t ofdmPhyErrCnt, cckPhyErrCnt;

		/* Clear the mib counters and save them in the stats */
		ar5212UpdateMibMacStats(ah);
		/* NB: these are not reset-on-read */
		phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1);
		phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2);
		/* XXX sometimes zero, why? */
		if (phyCnt1 < aniState->ofdmPhyErrBase ||
		    phyCnt2 < aniState->cckPhyErrBase) {
			if (phyCnt1 < aniState->ofdmPhyErrBase) {
				HDPRINTF(ah, HAL_DBG_ANI, "%s: phyCnt1 0x%x, resetting "
					"counter value to 0x%x\n", __func__,
					phyCnt1, aniState->ofdmPhyErrBase);
				OS_REG_WRITE(ah, AR_PHYCNT1, aniState->ofdmPhyErrBase);
				OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);
			}
			if (phyCnt2 < aniState->cckPhyErrBase) {
				HDPRINTF(ah, HAL_DBG_ANI, "%s: phyCnt2 0x%x, resetting "
					"counter value to 0x%x\n", __func__,
					phyCnt2, aniState->cckPhyErrBase);
				OS_REG_WRITE(ah, AR_PHYCNT2, aniState->cckPhyErrBase);
				OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);
			}
			return;		/* XXX */
		}
		/* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
		ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
		ahp->ah_stats.ast_ani_ofdmerrs +=
			ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
		aniState->ofdmPhyErrCount = ofdmPhyErrCnt;

		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
		ahp->ah_stats.ast_ani_cckerrs +=
			cckPhyErrCnt - aniState->cckPhyErrCount;
		aniState->cckPhyErrCount = cckPhyErrCnt;
	}

	listenTime = ar5212AniGetListenTime(ah);
	if (listenTime < 0) {
		ahp->ah_stats.ast_ani_lneg++;
		/* restart ANI period if listenTime is invalid */
		ar5212AniRestart(ah);
		return;
	}
	/* XXX beware of overflow? */
	aniState->listenTime += listenTime;

	if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
		/* 
		 * Check to see if need to lower immunity if
		 * 5 aniPeriods have passed
		 */
		if (aniState->ofdmPhyErrCount <= aniState->listenTime *
		     aniState->ofdmTrigLow/1000 &&
		    aniState->cckPhyErrCount <= aniState->listenTime *
		     aniState->cckTrigLow/1000)
			ar5212AniLowerImmunity(ah);
		ar5212AniRestart(ah);
	} else if (aniState->listenTime > ahp->ah_aniPeriod) {
		/* check to see if need to raise immunity */
		if (aniState->ofdmPhyErrCount > aniState->listenTime *
		    aniState->ofdmTrigHigh / 1000) {
			ar5212AniOfdmErrTrigger(ah);
			ar5212AniRestart(ah);
		} else if (aniState->cckPhyErrCount > aniState->listenTime *
			   aniState->cckTrigHigh / 1000) {
			ar5212AniCckErrTrigger(ah);
			ar5212AniRestart(ah);
		}
	}
}
Example #9
0
/*
 * Restore the ANI parameters in the HAL and reset the statistics.
 * This routine should be called for every hardware reset and for
 * every channel change.  NOTE: This must be called for every channel
 * change for ah_curani to be set correctly.
 */
void
ar5212AniReset(struct ath_hal *ah, int isRestore)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState;
	HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
	int index;

	HALASSERT(chan != AH_NULL);

	if (!(DO_ANI(ah))) {
		return;
	}

	index = ar5212GetAniChannelIndex(ah, chan);
	aniState = &ahp->ah_ani[index];
	ahp->ah_curani = aniState;

	/* If ANI follows hardware, we don't care what mode we're
	   in, we should keep the ani parameters */
	/*
	 * ANI is enabled but we're not operating in station
	 * mode.  Reset all parameters.  This can happen, for
	 * example, when starting up AP operation.
	 */
	if (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA &&
	    AH_PRIVATE(ah)->ah_opmode != HAL_M_IBSS) {
		HDPRINTF(ah, HAL_DBG_ANI, "%s: Reset ANI state opmode %u\n",
			     __func__, AH_PRIVATE(ah)->ah_opmode);
		ahp->ah_stats.ast_ani_reset++;
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
#ifdef notyet
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
			!HAL_ANI_USE_OFDM_WEAK_SIG);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
			HAL_ANI_CCK_WEAK_SIG_THR);
#endif
		ar5212AniRestart(ah);
		return;
	}

	if (isRestore) {
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
				 aniState->noiseImmunityLevel);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
				 aniState->spurImmunityLevel);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				 !aniState->ofdmWeakSigDetectOff);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
				 aniState->cckWeakSigThreshold);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel);
	}
	else {
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 4);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 7);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,1);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,1);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 2);
	}

	if (ahp->ah_hasHwPhyCounters) {
		ar5212SetRxFilter(ah,
			  ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
		ar5212AniRestart(ah);
		OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);
		OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);

	} else {
		ar5212AniRestart(ah);
		ar5212SetRxFilter(ah, ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR);
	}
}
/*
 * Restore/reset the ANI parameters and reset the statistics.
 * This routine must be called for every channel change.
 *
 * NOTE: This is where ah_curani is set; other ani code assumes
 *       it is setup to reflect the current channel.
 */
void
ar5212AniReset(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan,
	HAL_OPMODE opmode, int restore)
{
	struct ath_hal_5212 *ahp = AH5212(ah);
	struct ar5212AniState *aniState;
	uint32_t rxfilter;
	int index;

	index = ar5212GetAniChannelIndex(ah, chan);
	aniState = &ahp->ah_ani[index];
	ahp->ah_curani = aniState;
#if 0
	ath_hal_printf(ah,"%s: chan %u/0x%x restore %d setup %d opmode %u\n",
	    __func__, chan->channel, chan->channelFlags, restore,
	    aniState->isSetup, opmode);
#else
	HALDEBUG(ah, HAL_DEBUG_ANI,
	    "%s: chan %u/0x%x restore %d setup %d opmode %u\n",
	    __func__, chan->channel, chan->channelFlags, restore,
	    aniState->isSetup, opmode);
#endif
	OS_MARK(ah, AH_MARK_ANI_RESET, opmode);

	/*
	 * Turn off PHY error frame delivery while we futz with settings.
	 */
	rxfilter = ar5212GetRxFilter(ah);
	ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
	/*
	 * Automatic processing is done only in station mode right now.
	 */
	if (opmode == HAL_M_STA)
		ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA;
	else
		ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA;
	/*
	 * Set all ani parameters.  We either set them to initial
	 * values or restore the previous ones for the channel.
	 * XXX if ANI follows hardware, we don't care what mode we're
	 * XXX in, we should keep the ani parameters
	 */
	if (restore && aniState->isSetup) {
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
				 aniState->noiseImmunityLevel);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
				 aniState->spurImmunityLevel);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				 !aniState->ofdmWeakSigDetectOff);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
				 aniState->cckWeakSigThreshold);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
				 aniState->firstepLevel);
	} else {
		ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
		ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
			AH_TRUE);
		ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);
		ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
		aniState->isSetup = AH_TRUE;
	}
	ar5212AniRestart(ah, aniState);

	/* restore RX filter mask */
	ar5212SetRxFilter(ah, rxfilter);
}