The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ath/ath_hal/ar5212/ar5212_ani.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
    5  * Copyright (c) 2002-2008 Atheros Communications, Inc.
    6  *
    7  * Permission to use, copy, modify, and/or distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  *
   19  * $FreeBSD$
   20  */
   21 #include "opt_ah.h"
   22 
   23 #include "ah.h"
   24 #include "ah_internal.h"
   25 #include "ah_desc.h"
   26 
   27 #include "ar5212/ar5212.h"
   28 #include "ar5212/ar5212reg.h"
   29 #include "ar5212/ar5212phy.h"
   30 
   31 /*
   32  * Anti noise immunity support.  We track phy errors and react
   33  * to excessive errors by adjusting the noise immunity parameters.
   34  */
   35 
   36 #define HAL_EP_RND(x, mul) \
   37         ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
   38 #define BEACON_RSSI(ahp) \
   39         HAL_EP_RND(ahp->ah_stats.ast_nodestats.ns_avgbrssi, \
   40                 HAL_RSSI_EP_MULTIPLIER)
   41 
   42 /*
   43  * ANI processing tunes radio parameters according to PHY errors
   44  * and related information.  This is done for noise and spur
   45  * immunity in all operating modes if the device indicates it's
   46  * capable at attach time.  In addition, when there is a reference
   47  * rssi value (e.g. beacon frames from an ap in station mode)
   48  * further tuning is done.
   49  *
   50  * ANI_ENA indicates whether any ANI processing should be done;
   51  * this is specified at attach time.
   52  *
   53  * ANI_ENA_RSSI indicates whether rssi-based processing should
   54  * done, this is enabled based on operating mode and is meaningful
   55  * only if ANI_ENA is true.
   56  *
   57  * ANI parameters are typically controlled only by the hal.  The
   58  * AniControl interface however permits manual tuning through the
   59  * diagnostic api.
   60  */
   61 #define ANI_ENA(ah) \
   62         (AH5212(ah)->ah_procPhyErr & HAL_ANI_ENA)
   63 #define ANI_ENA_RSSI(ah) \
   64         (AH5212(ah)->ah_procPhyErr & HAL_RSSI_ANI_ENA)
   65 
   66 #define ah_mibStats     ah_stats.ast_mibstats
   67 
   68 static void
   69 enableAniMIBCounters(struct ath_hal *ah, const struct ar5212AniParams *params)
   70 {
   71         struct ath_hal_5212 *ahp = AH5212(ah);
   72 
   73         HALDEBUG(ah, HAL_DEBUG_ANI, "%s: Enable mib counters: "
   74             "OfdmPhyErrBase 0x%x cckPhyErrBase 0x%x\n",
   75             __func__, params->ofdmPhyErrBase, params->cckPhyErrBase);
   76 
   77         OS_REG_WRITE(ah, AR_FILTOFDM, 0);
   78         OS_REG_WRITE(ah, AR_FILTCCK, 0);
   79 
   80         OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase);
   81         OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase);
   82         OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);
   83         OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);
   84 
   85         ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save+clear counters*/
   86         ar5212EnableMibCounters(ah);                    /* enable everything */
   87 }
   88 
   89 static void 
   90 disableAniMIBCounters(struct ath_hal *ah)
   91 {
   92         struct ath_hal_5212 *ahp = AH5212(ah);
   93 
   94         HALDEBUG(ah, HAL_DEBUG_ANI, "Disable MIB counters\n");
   95 
   96         ar5212UpdateMibCounters(ah, &ahp->ah_mibStats); /* save stats */
   97         ar5212DisableMibCounters(ah);                   /* disable everything */
   98 
   99         OS_REG_WRITE(ah, AR_PHYCNTMASK1, 0);
  100         OS_REG_WRITE(ah, AR_PHYCNTMASK2, 0);
  101 }
  102 
  103 /*
  104  * Return the current ANI state of the channel we're on
  105  */
  106 struct ar5212AniState *
  107 ar5212AniGetCurrentState(struct ath_hal *ah)
  108 {
  109         return AH5212(ah)->ah_curani;
  110 }
  111 
  112 /*
  113  * Return the current statistics.
  114  */
  115 HAL_ANI_STATS *
  116 ar5212AniGetCurrentStats(struct ath_hal *ah)
  117 {
  118         struct ath_hal_5212 *ahp = AH5212(ah);
  119 
  120         /* update mib stats so we return current data */
  121         /* XXX? side-effects to doing this here? */
  122         ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
  123         return &ahp->ah_stats;
  124 }
  125 
  126 static void
  127 setPhyErrBase(struct ath_hal *ah, struct ar5212AniParams *params)
  128 {
  129         if (params->ofdmTrigHigh >= AR_PHY_COUNTMAX) {
  130                 HALDEBUG(ah, HAL_DEBUG_ANY,
  131                     "OFDM Trigger %d is too high for hw counters, using max\n",
  132                     params->ofdmTrigHigh);
  133                 params->ofdmPhyErrBase = 0;
  134         } else
  135                 params->ofdmPhyErrBase = AR_PHY_COUNTMAX - params->ofdmTrigHigh;
  136         if (params->cckTrigHigh >= AR_PHY_COUNTMAX) {
  137                 HALDEBUG(ah, HAL_DEBUG_ANY,
  138                     "CCK Trigger %d is too high for hw counters, using max\n",
  139                     params->cckTrigHigh);
  140                 params->cckPhyErrBase = 0;
  141         } else
  142                 params->cckPhyErrBase = AR_PHY_COUNTMAX - params->cckTrigHigh;
  143 }
  144 
  145 /*
  146  * Setup ANI handling.  Sets all thresholds and reset the
  147  * channel statistics.  Note that ar5212AniReset should be
  148  * called by ar5212Reset before anything else happens and
  149  * that's where we force initial settings.
  150  */
  151 void
  152 ar5212AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24,
  153         const struct ar5212AniParams *params5, HAL_BOOL enable)
  154 {
  155         struct ath_hal_5212 *ahp = AH5212(ah);
  156 
  157         ahp->ah_hasHwPhyCounters =
  158                 AH_PRIVATE(ah)->ah_caps.halHwPhyCounterSupport;
  159 
  160         if (params24 != AH_NULL) {
  161                 OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));
  162                 setPhyErrBase(ah, &ahp->ah_aniParams24);
  163         }
  164         if (params5 != AH_NULL) {
  165                 OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));
  166                 setPhyErrBase(ah, &ahp->ah_aniParams5);
  167         }
  168 
  169         OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));
  170         if (ahp->ah_hasHwPhyCounters) {
  171                 /* Enable MIB Counters */
  172                 enableAniMIBCounters(ah, &ahp->ah_aniParams24 /*XXX*/);
  173         }
  174         if (enable) {           /* Enable ani now */
  175                 HALASSERT(params24 != AH_NULL && params5 != AH_NULL);
  176                 ahp->ah_procPhyErr |= HAL_ANI_ENA;
  177         } else {
  178                 ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
  179         }
  180 }
  181 
  182 HAL_BOOL
  183 ar5212AniSetParams(struct ath_hal *ah, const struct ar5212AniParams *params24,
  184         const struct ar5212AniParams *params5)
  185 {
  186         struct ath_hal_5212 *ahp = AH5212(ah);
  187         HAL_BOOL ena = (ahp->ah_procPhyErr & HAL_ANI_ENA) != 0;
  188 
  189         ar5212AniControl(ah, HAL_ANI_MODE, AH_FALSE);
  190 
  191         OS_MEMCPY(&ahp->ah_aniParams24, params24, sizeof(*params24));
  192         setPhyErrBase(ah, &ahp->ah_aniParams24);
  193         OS_MEMCPY(&ahp->ah_aniParams5, params5, sizeof(*params5));
  194         setPhyErrBase(ah, &ahp->ah_aniParams5);
  195 
  196         OS_MEMZERO(ahp->ah_ani, sizeof(ahp->ah_ani));
  197         ar5212AniReset(ah, AH_PRIVATE(ah)->ah_curchan,
  198             AH_PRIVATE(ah)->ah_opmode, AH_FALSE);
  199 
  200         ar5212AniControl(ah, HAL_ANI_MODE, ena);
  201 
  202         return AH_TRUE;
  203 }
  204 
  205 /*
  206  * Cleanup any ANI state setup.
  207  */
  208 void
  209 ar5212AniDetach(struct ath_hal *ah)
  210 {
  211         struct ath_hal_5212 *ahp = AH5212(ah);
  212 
  213         HALDEBUG(ah, HAL_DEBUG_ANI, "Detaching Ani\n");
  214         if (ahp->ah_hasHwPhyCounters)
  215                 disableAniMIBCounters(ah);
  216 }
  217 
  218 /*
  219  * Control Adaptive Noise Immunity Parameters
  220  */
  221 HAL_BOOL
  222 ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
  223 {
  224         typedef int TABLE[];
  225         struct ath_hal_5212 *ahp = AH5212(ah);
  226         struct ar5212AniState *aniState = ahp->ah_curani;
  227         const struct ar5212AniParams *params = AH_NULL;
  228 
  229         /*
  230          * This function may be called before there's a current
  231          * channel (eg to disable ANI.)
  232          */
  233         if (aniState != AH_NULL)
  234                 params = aniState->params;
  235 
  236         OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);
  237 
  238         switch (cmd) {
  239         case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
  240                 u_int level = param;
  241 
  242                 if (level > params->maxNoiseImmunityLevel) {
  243                         HALDEBUG(ah, HAL_DEBUG_ANY,
  244                             "%s: level out of range (%u > %u)\n",
  245                             __func__, level, params->maxNoiseImmunityLevel);
  246                         return AH_FALSE;
  247                 }
  248 
  249                 OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
  250                     AR_PHY_DESIRED_SZ_TOT_DES, params->totalSizeDesired[level]);
  251                 OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
  252                     AR_PHY_AGC_CTL1_COARSE_LOW, params->coarseLow[level]);
  253                 OS_REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
  254                     AR_PHY_AGC_CTL1_COARSE_HIGH, params->coarseHigh[level]);
  255                 OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
  256                     AR_PHY_FIND_SIG_FIRPWR, params->firpwr[level]);
  257 
  258                 if (level > aniState->noiseImmunityLevel)
  259                         ahp->ah_stats.ast_ani_niup++;
  260                 else if (level < aniState->noiseImmunityLevel)
  261                         ahp->ah_stats.ast_ani_nidown++;
  262                 aniState->noiseImmunityLevel = level;
  263                 break;
  264         }
  265         case HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
  266                 static const TABLE m1ThreshLow   = { 127,   50 };
  267                 static const TABLE m2ThreshLow   = { 127,   40 };
  268                 static const TABLE m1Thresh      = { 127, 0x4d };
  269                 static const TABLE m2Thresh      = { 127, 0x40 };
  270                 static const TABLE m2CountThr    = {  31,   16 };
  271                 static const TABLE m2CountThrLow = {  63,   48 };
  272                 u_int on = param ? 1 : 0;
  273 
  274                 OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
  275                         AR_PHY_SFCORR_LOW_M1_THRESH_LOW, m1ThreshLow[on]);
  276                 OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
  277                         AR_PHY_SFCORR_LOW_M2_THRESH_LOW, m2ThreshLow[on]);
  278                 OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
  279                         AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]);
  280                 OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
  281                         AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]);
  282                 OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR,
  283                         AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]);
  284                 OS_REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
  285                         AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, m2CountThrLow[on]);
  286 
  287                 if (on) {
  288                         OS_REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
  289                                 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
  290                         ahp->ah_stats.ast_ani_ofdmon++;
  291                 } else {
  292                         OS_REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
  293                                 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
  294                         ahp->ah_stats.ast_ani_ofdmoff++;
  295                 }
  296                 aniState->ofdmWeakSigDetectOff = !on;
  297                 break;
  298         }
  299         case HAL_ANI_CCK_WEAK_SIGNAL_THR: {
  300                 static const TABLE weakSigThrCck = { 8, 6 };
  301                 u_int high = param ? 1 : 0;
  302 
  303                 OS_REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
  304                     AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, weakSigThrCck[high]);
  305                 if (high)
  306                         ahp->ah_stats.ast_ani_cckhigh++;
  307                 else
  308                         ahp->ah_stats.ast_ani_ccklow++;
  309                 aniState->cckWeakSigThreshold = high;
  310                 break;
  311         }
  312         case HAL_ANI_FIRSTEP_LEVEL: {
  313                 u_int level = param;
  314 
  315                 if (level > params->maxFirstepLevel) {
  316                         HALDEBUG(ah, HAL_DEBUG_ANY,
  317                             "%s: level out of range (%u > %u)\n",
  318                             __func__, level, params->maxFirstepLevel);
  319                         return AH_FALSE;
  320                 }
  321                 OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
  322                     AR_PHY_FIND_SIG_FIRSTEP, params->firstep[level]);
  323                 if (level > aniState->firstepLevel)
  324                         ahp->ah_stats.ast_ani_stepup++;
  325                 else if (level < aniState->firstepLevel)
  326                         ahp->ah_stats.ast_ani_stepdown++;
  327                 aniState->firstepLevel = level;
  328                 break;
  329         }
  330         case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
  331                 u_int level = param;
  332 
  333                 if (level > params->maxSpurImmunityLevel) {
  334                         HALDEBUG(ah, HAL_DEBUG_ANY,
  335                             "%s: level out of range (%u > %u)\n",
  336                             __func__, level, params->maxSpurImmunityLevel);
  337                         return AH_FALSE;
  338                 }
  339                 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5,
  340                     AR_PHY_TIMING5_CYCPWR_THR1, params->cycPwrThr1[level]);
  341                 if (level > aniState->spurImmunityLevel)
  342                         ahp->ah_stats.ast_ani_spurup++;
  343                 else if (level < aniState->spurImmunityLevel)
  344                         ahp->ah_stats.ast_ani_spurdown++;
  345                 aniState->spurImmunityLevel = level;
  346                 break;
  347         }
  348         case HAL_ANI_PRESENT:
  349                 break;
  350         case HAL_ANI_MODE:
  351                 if (param == 0) {
  352                         ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
  353                         /* Turn off HW counters if we have them */
  354                         ar5212AniDetach(ah);
  355                         ah->ah_setRxFilter(ah,
  356                             ah->ah_getRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
  357                 } else {                        /* normal/auto mode */
  358                         /* don't mess with state if already enabled */
  359                         if (ahp->ah_procPhyErr & HAL_ANI_ENA)
  360                                 break;
  361                         if (ahp->ah_hasHwPhyCounters) {
  362                                 ar5212SetRxFilter(ah,
  363                                         ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
  364                                 /* Enable MIB Counters */
  365                                 enableAniMIBCounters(ah,
  366                                     ahp->ah_curani != AH_NULL ?
  367                                         ahp->ah_curani->params:
  368                                         &ahp->ah_aniParams24 /*XXX*/);
  369                         } else {
  370                                 ah->ah_setRxFilter(ah,
  371                                     ah->ah_getRxFilter(ah) | HAL_RX_FILTER_PHYERR);
  372                         }
  373                         ahp->ah_procPhyErr |= HAL_ANI_ENA;
  374                 }
  375                 break;
  376 #ifdef AH_PRIVATE_DIAG
  377         case HAL_ANI_PHYERR_RESET:
  378                 ahp->ah_stats.ast_ani_ofdmerrs = 0;
  379                 ahp->ah_stats.ast_ani_cckerrs = 0;
  380                 break;
  381 #endif /* AH_PRIVATE_DIAG */
  382         default:
  383                 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid cmd %u\n",
  384                     __func__, cmd);
  385                 return AH_FALSE;
  386         }
  387         return AH_TRUE;
  388 }
  389 
  390 static void
  391 ar5212AniOfdmErrTrigger(struct ath_hal *ah)
  392 {
  393         struct ath_hal_5212 *ahp = AH5212(ah);
  394         const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
  395         struct ar5212AniState *aniState;
  396         const struct ar5212AniParams *params;
  397 
  398         HALASSERT(chan != AH_NULL);
  399 
  400         if (!ANI_ENA(ah))
  401                 return;
  402 
  403         aniState = ahp->ah_curani;
  404         params = aniState->params;
  405         /* First, raise noise immunity level, up to max */
  406         if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) {
  407                 HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
  408                     aniState->noiseImmunityLevel + 1);
  409                 ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 
  410                                  aniState->noiseImmunityLevel + 1);
  411                 return;
  412         }
  413         /* then, raise spur immunity level, up to max */
  414         if (aniState->spurImmunityLevel+1 <= params->maxSpurImmunityLevel) {
  415                 HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise SI to %u\n", __func__,
  416                     aniState->spurImmunityLevel + 1);
  417                 ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
  418                                  aniState->spurImmunityLevel + 1);
  419                 return;
  420         }
  421 
  422         if (ANI_ENA_RSSI(ah)) {
  423                 int32_t rssi = BEACON_RSSI(ahp);
  424                 if (rssi > params->rssiThrHigh) {
  425                         /*
  426                          * Beacon rssi is high, can turn off ofdm
  427                          * weak sig detect.
  428                          */
  429                         if (!aniState->ofdmWeakSigDetectOff) {
  430                                 HALDEBUG(ah, HAL_DEBUG_ANI,
  431                                     "%s: rssi %d OWSD off\n", __func__, rssi);
  432                                 ar5212AniControl(ah,
  433                                     HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  434                                     AH_FALSE);
  435                                 ar5212AniControl(ah,
  436                                     HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
  437                                 return;
  438                         }
  439                         /* 
  440                          * If weak sig detect is already off, as last resort,
  441                          * raise firstep level 
  442                          */
  443                         if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
  444                                 HALDEBUG(ah, HAL_DEBUG_ANI,
  445                                     "%s: rssi %d raise ST %u\n", __func__, rssi,
  446                                     aniState->firstepLevel+1);
  447                                 ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
  448                                                  aniState->firstepLevel + 1);
  449                                 return;
  450                         }
  451                 } else if (rssi > params->rssiThrLow) {
  452                         /* 
  453                          * Beacon rssi in mid range, need ofdm weak signal
  454                          * detect, but we can raise firststepLevel.
  455                          */
  456                         if (aniState->ofdmWeakSigDetectOff) {
  457                                 HALDEBUG(ah, HAL_DEBUG_ANI,
  458                                     "%s: rssi %d OWSD on\n", __func__, rssi);
  459                                 ar5212AniControl(ah,
  460                                     HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  461                                     AH_TRUE);
  462                         }
  463                         if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
  464                                 HALDEBUG(ah, HAL_DEBUG_ANI,
  465                                     "%s: rssi %d raise ST %u\n", __func__, rssi,
  466                                     aniState->firstepLevel+1);
  467                                 ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
  468                                      aniState->firstepLevel + 1);
  469                         }
  470                         return;
  471                 } else {
  472                         /* 
  473                          * Beacon rssi is low, if in 11b/g mode, turn off ofdm
  474                          * weak signal detection and zero firstepLevel to
  475                          * maximize CCK sensitivity 
  476                          */
  477                         if (IEEE80211_IS_CHAN_CCK(chan)) {
  478                                 if (!aniState->ofdmWeakSigDetectOff) {
  479                                         HALDEBUG(ah, HAL_DEBUG_ANI,
  480                                             "%s: rssi %d OWSD off\n",
  481                                             __func__, rssi);
  482                                         ar5212AniControl(ah,
  483                                             HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  484                                             AH_FALSE);
  485                                 }
  486                                 if (aniState->firstepLevel > 0) {
  487                                         HALDEBUG(ah, HAL_DEBUG_ANI,
  488                                             "%s: rssi %d zero ST (was %u)\n",
  489                                             __func__, rssi,
  490                                             aniState->firstepLevel);
  491                                         ar5212AniControl(ah,
  492                                              HAL_ANI_FIRSTEP_LEVEL, 0);
  493                                 }
  494                                 return;
  495                         }
  496                 }
  497         }
  498 }
  499 
  500 static void
  501 ar5212AniCckErrTrigger(struct ath_hal *ah)
  502 {
  503         struct ath_hal_5212 *ahp = AH5212(ah);
  504         const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan;
  505         struct ar5212AniState *aniState;
  506         const struct ar5212AniParams *params;
  507 
  508         HALASSERT(chan != AH_NULL);
  509 
  510         if (!ANI_ENA(ah))
  511                 return;
  512 
  513         /* first, raise noise immunity level, up to max */
  514         aniState = ahp->ah_curani;
  515         params = aniState->params;
  516         if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) {
  517                 HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
  518                     aniState->noiseImmunityLevel + 1);
  519                 ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
  520                                  aniState->noiseImmunityLevel + 1);
  521                 return;
  522         }
  523 
  524         if (ANI_ENA_RSSI(ah)) {
  525                 int32_t rssi = BEACON_RSSI(ahp);
  526                 if (rssi >  params->rssiThrLow) {
  527                         /*
  528                          * Beacon signal in mid and high range,
  529                          * raise firstep level.
  530                          */
  531                         if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
  532                                 HALDEBUG(ah, HAL_DEBUG_ANI,
  533                                     "%s: rssi %d raise ST %u\n", __func__, rssi,
  534                                     aniState->firstepLevel+1);
  535                                 ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
  536                                                  aniState->firstepLevel + 1);
  537                         }
  538                 } else {
  539                         /*
  540                          * Beacon rssi is low, zero firstep level to maximize
  541                          * CCK sensitivity in 11b/g mode.
  542                          */
  543                         /* XXX can optimize */
  544                         if (IEEE80211_IS_CHAN_B(chan) ||
  545                             IEEE80211_IS_CHAN_G(chan)) {
  546                                 if (aniState->firstepLevel > 0) {
  547                                         HALDEBUG(ah, HAL_DEBUG_ANI,
  548                                             "%s: rssi %d zero ST (was %u)\n",
  549                                             __func__, rssi,
  550                                             aniState->firstepLevel);
  551                                         ar5212AniControl(ah,
  552                                             HAL_ANI_FIRSTEP_LEVEL, 0);
  553                                 }
  554                         }
  555                 }
  556         }
  557 }
  558 
  559 static void
  560 ar5212AniRestart(struct ath_hal *ah, struct ar5212AniState *aniState)
  561 {
  562         struct ath_hal_5212 *ahp = AH5212(ah);
  563 
  564         aniState->listenTime = 0;
  565         if (ahp->ah_hasHwPhyCounters) {
  566                 const struct ar5212AniParams *params = aniState->params;
  567                 /*
  568                  * NB: these are written on reset based on the
  569                  *     ini so we must re-write them!
  570                  */
  571                 OS_REG_WRITE(ah, AR_PHYCNT1, params->ofdmPhyErrBase);
  572                 OS_REG_WRITE(ah, AR_PHYCNT2, params->cckPhyErrBase);
  573                 OS_REG_WRITE(ah, AR_PHYCNTMASK1, AR_PHY_ERR_OFDM_TIMING);
  574                 OS_REG_WRITE(ah, AR_PHYCNTMASK2, AR_PHY_ERR_CCK_TIMING);
  575 
  576                 /* Clear the mib counters and save them in the stats */
  577                 ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
  578         }
  579         aniState->ofdmPhyErrCount = 0;
  580         aniState->cckPhyErrCount = 0;
  581 }
  582 
  583 /*
  584  * Restore/reset the ANI parameters and reset the statistics.
  585  * This routine must be called for every channel change.
  586  */
  587 void
  588 ar5212AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan,
  589         HAL_OPMODE opmode, int restore)
  590 {
  591         struct ath_hal_5212 *ahp = AH5212(ah);
  592         HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
  593         /* XXX bounds check ic_devdata */
  594         struct ar5212AniState *aniState = &ahp->ah_ani[chan->ic_devdata];
  595         uint32_t rxfilter;
  596 
  597         if ((ichan->privFlags & CHANNEL_ANI_INIT) == 0) {
  598                 OS_MEMZERO(aniState, sizeof(*aniState));
  599                 if (IEEE80211_IS_CHAN_2GHZ(chan))
  600                         aniState->params = &ahp->ah_aniParams24;
  601                 else
  602                         aniState->params = &ahp->ah_aniParams5;
  603                 ichan->privFlags |= CHANNEL_ANI_INIT;
  604                 HALASSERT((ichan->privFlags & CHANNEL_ANI_SETUP) == 0);
  605         }
  606         ahp->ah_curani = aniState;
  607 #if 0
  608         ath_hal_printf(ah,"%s: chan %u/0x%x restore %d opmode %u%s\n",
  609             __func__, chan->ic_freq, chan->ic_flags, restore, opmode,
  610             ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : "");
  611 #else
  612         HALDEBUG(ah, HAL_DEBUG_ANI, "%s: chan %u/0x%x restore %d opmode %u%s\n",
  613             __func__, chan->ic_freq, chan->ic_flags, restore, opmode,
  614             ichan->privFlags & CHANNEL_ANI_SETUP ? " setup" : "");
  615 #endif
  616         OS_MARK(ah, AH_MARK_ANI_RESET, opmode);
  617 
  618         /*
  619          * Turn off PHY error frame delivery while we futz with settings.
  620          */
  621         rxfilter = ah->ah_getRxFilter(ah);
  622         ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
  623 
  624         /*
  625          * If ANI is disabled at this point, don't set the default
  626          * ANI parameter settings - leave the HAL settings there.
  627          * This is (currently) needed for reliable radar detection.
  628          */
  629         if (! ANI_ENA(ah)) {
  630                 HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n",
  631                     __func__);
  632                 goto finish;
  633         }
  634 
  635         /*
  636          * Automatic processing is done only in station mode right now.
  637          */
  638         if (opmode == HAL_M_STA)
  639                 ahp->ah_procPhyErr |= HAL_RSSI_ANI_ENA;
  640         else
  641                 ahp->ah_procPhyErr &= ~HAL_RSSI_ANI_ENA;
  642         /*
  643          * Set all ani parameters.  We either set them to initial
  644          * values or restore the previous ones for the channel.
  645          * XXX if ANI follows hardware, we don't care what mode we're
  646          * XXX in, we should keep the ani parameters
  647          */
  648         if (restore && (ichan->privFlags & CHANNEL_ANI_SETUP)) {
  649                 ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
  650                                  aniState->noiseImmunityLevel);
  651                 ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
  652                                  aniState->spurImmunityLevel);
  653                 ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  654                                  !aniState->ofdmWeakSigDetectOff);
  655                 ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR,
  656                                  aniState->cckWeakSigThreshold);
  657                 ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
  658                                  aniState->firstepLevel);
  659         } else {
  660                 ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL, 0);
  661                 ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
  662                 ar5212AniControl(ah, HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  663                         AH_TRUE);
  664                 ar5212AniControl(ah, HAL_ANI_CCK_WEAK_SIGNAL_THR, AH_FALSE);
  665                 ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
  666                 ichan->privFlags |= CHANNEL_ANI_SETUP;
  667         }
  668         /*
  669          * In case the counters haven't yet been setup; set them up.
  670          */
  671         enableAniMIBCounters(ah, ahp->ah_curani->params);
  672         ar5212AniRestart(ah, aniState);
  673 
  674 finish:
  675         /* restore RX filter mask */
  676         ah->ah_setRxFilter(ah, rxfilter);
  677 }
  678 
  679 /*
  680  * Process a MIB interrupt.  We may potentially be invoked because
  681  * any of the MIB counters overflow/trigger so don't assume we're
  682  * here because a PHY error counter triggered.
  683  */
  684 void
  685 ar5212ProcessMibIntr(struct ath_hal *ah, const HAL_NODE_STATS *stats)
  686 {
  687         struct ath_hal_5212 *ahp = AH5212(ah);
  688         uint32_t phyCnt1, phyCnt2;
  689 
  690         HALDEBUG(ah, HAL_DEBUG_ANI, "%s: mibc 0x%x phyCnt1 0x%x phyCnt2 0x%x "
  691             "filtofdm 0x%x filtcck 0x%x\n",
  692             __func__, OS_REG_READ(ah, AR_MIBC),
  693             OS_REG_READ(ah, AR_PHYCNT1), OS_REG_READ(ah, AR_PHYCNT2),
  694             OS_REG_READ(ah, AR_FILTOFDM), OS_REG_READ(ah, AR_FILTCCK));
  695 
  696         /*
  697          * First order of business is to clear whatever caused
  698          * the interrupt so we don't keep getting interrupted.
  699          * We have the usual mib counters that are reset-on-read
  700          * and the additional counters that appeared starting in
  701          * Hainan.  We collect the mib counters and explicitly
  702          * zero additional counters we are not using.  Anything
  703          * else is reset only if it caused the interrupt.
  704          */
  705         /* NB: these are not reset-on-read */
  706         phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1);
  707         phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2);
  708         /* not used, always reset them in case they are the cause */
  709         OS_REG_WRITE(ah, AR_FILTOFDM, 0);
  710         OS_REG_WRITE(ah, AR_FILTCCK, 0);
  711 
  712         /* Clear the mib counters and save them in the stats */
  713         ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
  714         ahp->ah_stats.ast_nodestats = *stats;
  715 
  716         /*
  717          * Check for an ani stat hitting the trigger threshold.
  718          * When this happens we get a MIB interrupt and the top
  719          * 2 bits of the counter register will be 0b11, hence
  720          * the mask check of phyCnt?.
  721          */
  722         if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || 
  723             ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
  724                 struct ar5212AniState *aniState = ahp->ah_curani;
  725                 const struct ar5212AniParams *params = aniState->params;
  726                 uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
  727 
  728                 ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
  729                 ahp->ah_stats.ast_ani_ofdmerrs +=
  730                         ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
  731                 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
  732 
  733                 cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
  734                 ahp->ah_stats.ast_ani_cckerrs +=
  735                         cckPhyErrCnt - aniState->cckPhyErrCount;
  736                 aniState->cckPhyErrCount = cckPhyErrCnt;
  737 
  738                 /*
  739                  * NB: figure out which counter triggered.  If both
  740                  * trigger we'll only deal with one as the processing
  741                  * clobbers the error counter so the trigger threshold
  742                  * check will never be true.
  743                  */
  744                 if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh)
  745                         ar5212AniOfdmErrTrigger(ah);
  746                 if (aniState->cckPhyErrCount > params->cckTrigHigh)
  747                         ar5212AniCckErrTrigger(ah);
  748                 /* NB: always restart to insure the h/w counters are reset */
  749                 ar5212AniRestart(ah, aniState);
  750         }
  751 }
  752 
  753 void 
  754 ar5212AniPhyErrReport(struct ath_hal *ah, const struct ath_rx_status *rs)
  755 {
  756         struct ath_hal_5212 *ahp = AH5212(ah);
  757         struct ar5212AniState *aniState;
  758         const struct ar5212AniParams *params;
  759 
  760         HALASSERT(!ahp->ah_hasHwPhyCounters && rs != AH_NULL);
  761 
  762         aniState = ahp->ah_curani;
  763         params = aniState->params;
  764         if (rs->rs_phyerr == HAL_PHYERR_OFDM_TIMING) {
  765                 aniState->ofdmPhyErrCount++;
  766                 ahp->ah_stats.ast_ani_ofdmerrs++;
  767                 if (aniState->ofdmPhyErrCount > params->ofdmTrigHigh) {
  768                         ar5212AniOfdmErrTrigger(ah);
  769                         ar5212AniRestart(ah, aniState);
  770                 }
  771         } else if (rs->rs_phyerr == HAL_PHYERR_CCK_TIMING) {
  772                 aniState->cckPhyErrCount++;
  773                 ahp->ah_stats.ast_ani_cckerrs++;
  774                 if (aniState->cckPhyErrCount > params->cckTrigHigh) {
  775                         ar5212AniCckErrTrigger(ah);
  776                         ar5212AniRestart(ah, aniState);
  777                 }
  778         }
  779 }
  780 
  781 static void
  782 ar5212AniLowerImmunity(struct ath_hal *ah)
  783 {
  784         struct ath_hal_5212 *ahp = AH5212(ah);
  785         struct ar5212AniState *aniState;
  786         const struct ar5212AniParams *params;
  787 
  788         HALASSERT(ANI_ENA(ah));
  789 
  790         aniState = ahp->ah_curani;
  791         params = aniState->params;
  792         if (ANI_ENA_RSSI(ah)) {
  793                 int32_t rssi = BEACON_RSSI(ahp);
  794                 if (rssi > params->rssiThrHigh) {
  795                         /* 
  796                          * Beacon signal is high, leave ofdm weak signal
  797                          * detection off or it may oscillate.  Let it fall
  798                          * through.
  799                          */
  800                 } else if (rssi > params->rssiThrLow) {
  801                         /*
  802                          * Beacon rssi in mid range, turn on ofdm weak signal
  803                          * detection or lower firstep level.
  804                          */
  805                         if (aniState->ofdmWeakSigDetectOff) {
  806                                 HALDEBUG(ah, HAL_DEBUG_ANI,
  807                                     "%s: rssi %d OWSD on\n", __func__, rssi);
  808                                 ar5212AniControl(ah,
  809                                     HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
  810                                     AH_TRUE);
  811                                 return;
  812                         }
  813                         if (aniState->firstepLevel > 0) {
  814                                 HALDEBUG(ah, HAL_DEBUG_ANI,
  815                                     "%s: rssi %d lower ST %u\n", __func__, rssi,
  816                                     aniState->firstepLevel-1);
  817                                 ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
  818                                                  aniState->firstepLevel - 1);
  819                                 return;
  820                         }
  821                 } else {
  822                         /*
  823                          * Beacon rssi is low, reduce firstep level.
  824                          */
  825                         if (aniState->firstepLevel > 0) {
  826                                 HALDEBUG(ah, HAL_DEBUG_ANI,
  827                                     "%s: rssi %d lower ST %u\n", __func__, rssi,
  828                                     aniState->firstepLevel-1);
  829                                 ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
  830                                                  aniState->firstepLevel - 1);
  831                                 return;
  832                         }
  833                 }
  834         }
  835         /* then lower spur immunity level, down to zero */
  836         if (aniState->spurImmunityLevel > 0) {
  837                 HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower SI %u\n",
  838                     __func__, aniState->spurImmunityLevel-1);
  839                 ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
  840                                  aniState->spurImmunityLevel - 1);
  841                 return;
  842         }
  843         /* 
  844          * if all else fails, lower noise immunity level down to a min value
  845          * zero for now
  846          */
  847         if (aniState->noiseImmunityLevel > 0) {
  848                 HALDEBUG(ah, HAL_DEBUG_ANI, "%s: lower NI %u\n",
  849                     __func__, aniState->noiseImmunityLevel-1);
  850                 ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
  851                                  aniState->noiseImmunityLevel - 1);
  852                 return;
  853         }
  854 }
  855 
  856 #define CLOCK_RATE 44000        /* XXX use mac_usec or similar */
  857 /* convert HW counter values to ms using 11g clock rate, goo9d enough
  858    for 11a and Turbo */
  859 
  860 /* 
  861  * Return an approximation of the time spent ``listening'' by
  862  * deducting the cycles spent tx'ing and rx'ing from the total
  863  * cycle count since our last call.  A return value <0 indicates
  864  * an invalid/inconsistent time.
  865  */
  866 static int32_t
  867 ar5212AniGetListenTime(struct ath_hal *ah)
  868 {
  869         struct ath_hal_5212 *ahp = AH5212(ah);
  870         struct ar5212AniState *aniState = NULL;
  871         int32_t listenTime = 0;
  872         int good;
  873         HAL_SURVEY_SAMPLE hs;
  874 
  875         /*
  876          * We shouldn't see ah_curchan be NULL, but just in case..
  877          */
  878         if (AH_PRIVATE(ah)->ah_curchan == AH_NULL) {
  879                 ath_hal_printf(ah, "%s: ah_curchan = NULL?\n", __func__);
  880                 return (0);
  881         }
  882 
  883         /*
  884          * Fetch the current statistics, squirrel away the current
  885          * sample, bump the sequence/sample counter.
  886          */
  887         OS_MEMZERO(&hs, sizeof(hs));
  888         good = ar5212GetMibCycleCounts(ah, &hs);
  889         ath_hal_survey_add_sample(ah, &hs);
  890 
  891         if (ANI_ENA(ah))
  892                 aniState = ahp->ah_curani;
  893 
  894         if (good == AH_FALSE) {
  895                 /*
  896                  * Cycle counter wrap (or initial call); it's not possible
  897                  * to accurately calculate a value because the registers
  898                  * right shift rather than wrap--so punt and return 0.
  899                  */
  900                 listenTime = 0;
  901                 ahp->ah_stats.ast_ani_lzero++;
  902         } else if (ANI_ENA(ah)) {
  903                 /*
  904                  * Only calculate and update the cycle count if we have
  905                  * an ANI state.
  906                  */
  907                 int32_t ccdelta =
  908                     AH5212(ah)->ah_cycleCount - aniState->cycleCount;
  909                 int32_t rfdelta =
  910                     AH5212(ah)->ah_rxBusy - aniState->rxFrameCount;
  911                 int32_t tfdelta =
  912                     AH5212(ah)->ah_txBusy - aniState->txFrameCount;
  913                 listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
  914         }
  915 
  916         /*
  917          * Again, only update ANI state if we have it.
  918          */
  919         if (ANI_ENA(ah)) {
  920                 aniState->cycleCount = AH5212(ah)->ah_cycleCount;
  921                 aniState->rxFrameCount = AH5212(ah)->ah_rxBusy;
  922                 aniState->txFrameCount = AH5212(ah)->ah_txBusy;
  923         }
  924 
  925         return listenTime;
  926 }
  927 
  928 /*
  929  * Update ani stats in preparation for listen time processing.
  930  */
  931 static void
  932 updateMIBStats(struct ath_hal *ah, struct ar5212AniState *aniState)
  933 {
  934         struct ath_hal_5212 *ahp = AH5212(ah);
  935         const struct ar5212AniParams *params = aniState->params;
  936         uint32_t phyCnt1, phyCnt2;
  937         int32_t ofdmPhyErrCnt, cckPhyErrCnt;
  938 
  939         HALASSERT(ahp->ah_hasHwPhyCounters);
  940 
  941         /* Clear the mib counters and save them in the stats */
  942         ar5212UpdateMibCounters(ah, &ahp->ah_mibStats);
  943 
  944         /* NB: these are not reset-on-read */
  945         phyCnt1 = OS_REG_READ(ah, AR_PHYCNT1);
  946         phyCnt2 = OS_REG_READ(ah, AR_PHYCNT2);
  947 
  948         /* NB: these are spec'd to never roll-over */
  949         ofdmPhyErrCnt = phyCnt1 - params->ofdmPhyErrBase;
  950         if (ofdmPhyErrCnt < 0) {
  951                 HALDEBUG(ah, HAL_DEBUG_ANI, "OFDM phyErrCnt %d phyCnt1 0x%x\n",
  952                     ofdmPhyErrCnt, phyCnt1);
  953                 ofdmPhyErrCnt = AR_PHY_COUNTMAX;
  954         }
  955         ahp->ah_stats.ast_ani_ofdmerrs +=
  956              ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
  957         aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
  958 
  959         cckPhyErrCnt = phyCnt2 - params->cckPhyErrBase;
  960         if (cckPhyErrCnt < 0) {
  961                 HALDEBUG(ah, HAL_DEBUG_ANI, "CCK phyErrCnt %d phyCnt2 0x%x\n",
  962                     cckPhyErrCnt, phyCnt2);
  963                 cckPhyErrCnt = AR_PHY_COUNTMAX;
  964         }
  965         ahp->ah_stats.ast_ani_cckerrs +=
  966                 cckPhyErrCnt - aniState->cckPhyErrCount;
  967         aniState->cckPhyErrCount = cckPhyErrCnt;
  968 }
  969 
  970 void
  971 ar5212RxMonitor(struct ath_hal *ah, const HAL_NODE_STATS *stats,
  972                 const struct ieee80211_channel *chan)
  973 {
  974         struct ath_hal_5212 *ahp = AH5212(ah);
  975         ahp->ah_stats.ast_nodestats.ns_avgbrssi = stats->ns_avgbrssi;
  976 }
  977 
  978 /*
  979  * Do periodic processing.  This routine is called from the
  980  * driver's rx interrupt handler after processing frames.
  981  */
  982 void
  983 ar5212AniPoll(struct ath_hal *ah, const struct ieee80211_channel *chan)
  984 {
  985         struct ath_hal_5212 *ahp = AH5212(ah);
  986         struct ar5212AniState *aniState = ahp->ah_curani;
  987         const struct ar5212AniParams *params;
  988         int32_t listenTime;
  989 
  990         /* Always update from the MIB, for statistics gathering */
  991         listenTime = ar5212AniGetListenTime(ah);
  992 
  993         /* XXX can aniState be null? */
  994         if (aniState == AH_NULL)
  995                 return;
  996         if (!ANI_ENA(ah))
  997                 return;
  998 
  999         if (listenTime < 0) {
 1000                 ahp->ah_stats.ast_ani_lneg++;
 1001                 /* restart ANI period if listenTime is invalid */
 1002                 ar5212AniRestart(ah, aniState);
 1003 
 1004                 /* Don't do any further ANI processing here */
 1005                 return;
 1006         }
 1007         /* XXX beware of overflow? */
 1008         aniState->listenTime += listenTime;
 1009 
 1010         OS_MARK(ah, AH_MARK_ANI_POLL, aniState->listenTime);
 1011 
 1012         params = aniState->params;
 1013         if (aniState->listenTime > 5*params->period) {
 1014                 /* 
 1015                  * Check to see if need to lower immunity if
 1016                  * 5 aniPeriods have passed
 1017                  */
 1018                 if (ahp->ah_hasHwPhyCounters)
 1019                         updateMIBStats(ah, aniState);
 1020                 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
 1021                     params->ofdmTrigLow/1000 &&
 1022                     aniState->cckPhyErrCount <= aniState->listenTime *
 1023                     params->cckTrigLow/1000)
 1024                         ar5212AniLowerImmunity(ah);
 1025                 ar5212AniRestart(ah, aniState);
 1026         } else if (aniState->listenTime > params->period) {
 1027                 if (ahp->ah_hasHwPhyCounters)
 1028                         updateMIBStats(ah, aniState);
 1029                 /* check to see if need to raise immunity */
 1030                 if (aniState->ofdmPhyErrCount > aniState->listenTime *
 1031                     params->ofdmTrigHigh / 1000) {
 1032                         HALDEBUG(ah, HAL_DEBUG_ANI,
 1033                             "%s: OFDM err %u listenTime %u\n", __func__,
 1034                             aniState->ofdmPhyErrCount, aniState->listenTime);
 1035                         ar5212AniOfdmErrTrigger(ah);
 1036                         ar5212AniRestart(ah, aniState);
 1037                 } else if (aniState->cckPhyErrCount > aniState->listenTime *
 1038                            params->cckTrigHigh / 1000) {
 1039                         HALDEBUG(ah, HAL_DEBUG_ANI,
 1040                             "%s: CCK err %u listenTime %u\n", __func__,
 1041                             aniState->cckPhyErrCount, aniState->listenTime);
 1042                         ar5212AniCckErrTrigger(ah);
 1043                         ar5212AniRestart(ah, aniState);
 1044                 }
 1045         }
 1046 }

Cache object: 266559c21145376c75eb965a69f23c5d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.