📄 ar5212_ani.c
字号:
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); if (IS_CHAN_5GHZ((HAL_CHANNEL *)chan)) { ar5212SetRxFilter(ah, ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR); } else { ar5212SetRxFilter(ah, ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR); } }}/* * 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. */voidar5212ProcessMibIntr(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); }}void ar5212AniPhyErrReport(struct ath_hal *ah, const struct ath_rx_status *rs){ struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState; HALASSERT(!ahp->ah_hasHwPhyCounters && rs != AH_NULL); aniState = ahp->ah_curani; if (rs->rs_phyerr == HAL_PHYERR_OFDM_TIMING) { aniState->ofdmPhyErrCount++; ahp->ah_stats.ast_ani_ofdmerrs++; if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) { ar5212AniOfdmErrTrigger(ah); ar5212AniRestart(ah); } } else if (rs->rs_phyerr == HAL_PHYERR_CCK_TIMING) { aniState->cckPhyErrCount++; ahp->ah_stats.ast_ani_cckerrs++; if (aniState->cckPhyErrCount > aniState->cckTrigHigh) { ar5212AniCckErrTrigger(ah); ar5212AniRestart(ah); } }}static voidar5212AniLowerImmunity(struct ath_hal *ah){ struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState; int32_t rssi, data_rssi; aniState = ahp->ah_curani; rssi = BEACON_RSSI(ahp); if (rssi > aniState->rssiThrHigh) { /* * Beacon signal is high, leave ofdm weak signal detection off * or it may oscillate. Let it fall through. */ } else if (rssi > aniState->rssiThrLow) { /* * Beacon rssi in mid range, turn on ofdm weak signal * detection or lower first step level. */ if (aniState->ofdmWeakSigDetectOff) { ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, AH_TRUE); return; } if (aniState->firstepLevel > 0) { ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1); return; } } else { /* * Beacon rssi is low, reduce first step level. */ if (aniState->firstepLevel > 0) { ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1); return; } } /* then lower spur immunity level, down to zero */ if (aniState->spurImmunityLevel > 0) { ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel - 1); return; } /* * if all else fails, lower noise immunity level down to a min value * zero for now */ if (aniState->noiseImmunityLevel > 0) {// if (aniState->noiseImmunityLevel == 4 && (BEACON_RSSI(ahp) > STRONG_RSSI || DATA_RSSI(ahp) > STRONG_RSSI))// return; if ((aniState->noiseImmunityLevel == HAL_NOISE_IMMUNE_MAX )){ rssi = BEACON_RSSI(ahp); data_rssi = DATA_RSSI(ahp); if (MAX(rssi, data_rssi) < aniState->attenOffThreshold) { /* Enable DPDT switch */ ar5212AniControl(ah, HAL_ANT_SW_OPT, 0x0); ar5212SetRxFilter(ah, ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR); } else { return; } } ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel - 1); return; }}#define CLOCK_RATE 44000 /* XXX use mac_usec or similar *//* convert HW counter values to ms using 11g clock rate, goo9d enough for 11a and Turbo *//* * Return an approximation of the time spent ``listening'' by * deducting the cycles spent tx'ing and rx'ing from the total * cycle count since our last call. A return value <0 indicates * an invalid/inconsistent time. */static int32_tar5212AniGetListenTime(struct ath_hal *ah){ struct ath_hal_5212 *ahp = AH5212(ah); struct ar5212AniState *aniState; u_int32_t txFrameCount, rxFrameCount, cycleCount; int32_t listenTime; txFrameCount = OS_REG_READ(ah, AR_TFCNT); rxFrameCount = OS_REG_READ(ah, AR_RFCNT); cycleCount = OS_REG_READ(ah, AR_CCCNT); aniState = ahp->ah_curani; if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { /* * Cycle counter wrap (or initial call); it's not possible * to accurately calculate a value because the registers * right shift rather than wrap--so punt and return 0. */ listenTime = 0; ahp->ah_stats.ast_ani_lzero++; } else { int32_t ccdelta = cycleCount - aniState->cycleCount; int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; int32_t tfdelta = txFrameCount - aniState->txFrameCount; listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE; } aniState->cycleCount = cycleCount; aniState->txFrameCount = txFrameCount; aniState->rxFrameCount = rxFrameCount; return listenTime;}/* * Do periodic processing. This routine is called from the * driver's rx interrupt handler after processing frames. */voidar5212AniArPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, HAL_CHANNEL *chan){ 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) { HALDEBUG(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) { HALDEBUG(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))) { return; } if (IS_CHAN_2GHZ(chan)) { if (BEACON_RSSI(ahp) > aniState->rssiThrMaxNoiseImmunity && aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, HAL_NOISE_IMMUNE_MAX); } else if (BEACON_RSSI(ahp) < aniState->rssiThrDefNoiseImmunity && aniState->noiseImmunityLevel > 0) { ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0); } 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); } }}#endif /* AH_SUPPORT_AR5212 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -