linux/drivers/net/wireless/ath/ath9k/ani.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2008-2011 Atheros Communications Inc.
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/export.h>
  19#include "hw.h"
  20#include "hw-ops.h"
  21
  22struct ani_ofdm_level_entry {
  23        int spur_immunity_level;
  24        int fir_step_level;
  25        int ofdm_weak_signal_on;
  26};
  27
  28/* values here are relative to the INI */
  29
  30/*
  31 * Legend:
  32 *
  33 * SI: Spur immunity
  34 * FS: FIR Step
  35 * WS: OFDM / CCK Weak Signal detection
  36 * MRC-CCK: Maximal Ratio Combining for CCK
  37 */
  38
  39static const struct ani_ofdm_level_entry ofdm_level_table[] = {
  40        /* SI  FS  WS */
  41        {  0,  0,  1  }, /* lvl 0 */
  42        {  1,  1,  1  }, /* lvl 1 */
  43        {  2,  2,  1  }, /* lvl 2 */
  44        {  3,  2,  1  }, /* lvl 3  (default) */
  45        {  4,  3,  1  }, /* lvl 4 */
  46        {  5,  4,  1  }, /* lvl 5 */
  47        {  6,  5,  1  }, /* lvl 6 */
  48        {  7,  6,  1  }, /* lvl 7 */
  49        {  7,  7,  1  }, /* lvl 8 */
  50        {  7,  8,  0  }  /* lvl 9 */
  51};
  52#define ATH9K_ANI_OFDM_NUM_LEVEL \
  53        ARRAY_SIZE(ofdm_level_table)
  54#define ATH9K_ANI_OFDM_MAX_LEVEL \
  55        (ATH9K_ANI_OFDM_NUM_LEVEL-1)
  56#define ATH9K_ANI_OFDM_DEF_LEVEL \
  57        3 /* default level - matches the INI settings */
  58
  59/*
  60 * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
  61 * With OFDM for single stream you just add up all antenna inputs, you're
  62 * only interested in what you get after FFT. Signal aligment is also not
  63 * required for OFDM because any phase difference adds up in the frequency
  64 * domain.
  65 *
  66 * MRC requires extra work for use with CCK. You need to align the antenna
  67 * signals from the different antenna before you can add the signals together.
  68 * You need aligment of signals as CCK is in time domain, so addition can cancel
  69 * your signal completely if phase is 180 degrees (think of adding sine waves).
  70 * You also need to remove noise before the addition and this is where ANI
  71 * MRC CCK comes into play. One of the antenna inputs may be stronger but
  72 * lower SNR, so just adding after alignment can be dangerous.
  73 *
  74 * Regardless of alignment in time, the antenna signals add constructively after
  75 * FFT and improve your reception. For more information:
  76 *
  77 * http://en.wikipedia.org/wiki/Maximal-ratio_combining
  78 */
  79
  80struct ani_cck_level_entry {
  81        int fir_step_level;
  82        int mrc_cck_on;
  83};
  84
  85static const struct ani_cck_level_entry cck_level_table[] = {
  86        /* FS  MRC-CCK  */
  87        {  0,  1  }, /* lvl 0 */
  88        {  1,  1  }, /* lvl 1 */
  89        {  2,  1  }, /* lvl 2  (default) */
  90        {  3,  1  }, /* lvl 3 */
  91        {  4,  0  }, /* lvl 4 */
  92        {  5,  0  }, /* lvl 5 */
  93        {  6,  0  }, /* lvl 6 */
  94        {  7,  0  }, /* lvl 7 (only for high rssi) */
  95        {  8,  0  }  /* lvl 8 (only for high rssi) */
  96};
  97
  98#define ATH9K_ANI_CCK_NUM_LEVEL \
  99        ARRAY_SIZE(cck_level_table)
 100#define ATH9K_ANI_CCK_MAX_LEVEL \
 101        (ATH9K_ANI_CCK_NUM_LEVEL-1)
 102#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
 103        (ATH9K_ANI_CCK_NUM_LEVEL-3)
 104#define ATH9K_ANI_CCK_DEF_LEVEL \
 105        2 /* default level - matches the INI settings */
 106
 107static void ath9k_hw_update_mibstats(struct ath_hw *ah,
 108                                     struct ath9k_mib_stats *stats)
 109{
 110        stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
 111        stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
 112        stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
 113        stats->rts_good += REG_READ(ah, AR_RTS_OK);
 114        stats->beacons += REG_READ(ah, AR_BEACON_CNT);
 115}
 116
 117static void ath9k_ani_restart(struct ath_hw *ah)
 118{
 119        struct ar5416AniState *aniState;
 120
 121        if (!ah->curchan)
 122                return;
 123
 124        aniState = &ah->ani;
 125        aniState->listenTime = 0;
 126
 127        ENABLE_REGWRITE_BUFFER(ah);
 128
 129        REG_WRITE(ah, AR_PHY_ERR_1, 0);
 130        REG_WRITE(ah, AR_PHY_ERR_2, 0);
 131        REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
 132        REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
 133
 134        REGWRITE_BUFFER_FLUSH(ah);
 135
 136        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 137
 138        aniState->ofdmPhyErrCount = 0;
 139        aniState->cckPhyErrCount = 0;
 140}
 141
 142/* Adjust the OFDM Noise Immunity Level */
 143static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
 144                                  bool scan)
 145{
 146        struct ar5416AniState *aniState = &ah->ani;
 147        struct ath_common *common = ath9k_hw_common(ah);
 148        const struct ani_ofdm_level_entry *entry_ofdm;
 149        const struct ani_cck_level_entry *entry_cck;
 150        bool weak_sig;
 151
 152        ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
 153                aniState->ofdmNoiseImmunityLevel,
 154                immunityLevel, BEACON_RSSI(ah),
 155                ATH9K_ANI_RSSI_THR_LOW,
 156                ATH9K_ANI_RSSI_THR_HIGH);
 157
 158        if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL)
 159                immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
 160
 161        if (!scan)
 162                aniState->ofdmNoiseImmunityLevel = immunityLevel;
 163
 164        entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
 165        entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
 166
 167        if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
 168                ath9k_hw_ani_control(ah,
 169                                     ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
 170                                     entry_ofdm->spur_immunity_level);
 171
 172        if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
 173            entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
 174                ath9k_hw_ani_control(ah,
 175                                     ATH9K_ANI_FIRSTEP_LEVEL,
 176                                     entry_ofdm->fir_step_level);
 177
 178        weak_sig = entry_ofdm->ofdm_weak_signal_on;
 179        if (ah->opmode == NL80211_IFTYPE_STATION &&
 180            BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH)
 181                weak_sig = true;
 182        /*
 183         * Newer chipsets are better at dealing with high PHY error counts -
 184         * keep weak signal detection enabled when no RSSI threshold is
 185         * available to determine if it is needed (mode != STA)
 186         */
 187        else if (AR_SREV_9300_20_OR_LATER(ah) &&
 188                 ah->opmode != NL80211_IFTYPE_STATION)
 189                weak_sig = true;
 190
 191        /* Older chipsets are more sensitive to high PHY error counts */
 192        else if (!AR_SREV_9300_20_OR_LATER(ah) &&
 193                 aniState->ofdmNoiseImmunityLevel >= 8)
 194                weak_sig = false;
 195
 196        if (aniState->ofdmWeakSigDetect != weak_sig)
 197                ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
 198                                     weak_sig);
 199
 200        if (!AR_SREV_9300_20_OR_LATER(ah))
 201                return;
 202
 203        if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
 204                ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
 205                ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI;
 206        } else {
 207                ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI;
 208                ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
 209        }
 210}
 211
 212static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
 213{
 214        struct ar5416AniState *aniState;
 215
 216        if (!ah->curchan)
 217                return;
 218
 219        aniState = &ah->ani;
 220
 221        if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
 222                ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false);
 223}
 224
 225/*
 226 * Set the ANI settings to match an CCK level.
 227 */
 228static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
 229                                 bool scan)
 230{
 231        struct ar5416AniState *aniState = &ah->ani;
 232        struct ath_common *common = ath9k_hw_common(ah);
 233        const struct ani_ofdm_level_entry *entry_ofdm;
 234        const struct ani_cck_level_entry *entry_cck;
 235
 236        ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
 237                aniState->cckNoiseImmunityLevel, immunityLevel,
 238                BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
 239                ATH9K_ANI_RSSI_THR_HIGH);
 240
 241        if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL)
 242                immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
 243
 244        if (ah->opmode == NL80211_IFTYPE_STATION &&
 245            BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
 246            immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
 247                immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
 248
 249        if (!scan)
 250                aniState->cckNoiseImmunityLevel = immunityLevel;
 251
 252        entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
 253        entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
 254
 255        if (aniState->firstepLevel != entry_cck->fir_step_level &&
 256            entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
 257                ath9k_hw_ani_control(ah,
 258                                     ATH9K_ANI_FIRSTEP_LEVEL,
 259                                     entry_cck->fir_step_level);
 260
 261        /* Skip MRC CCK for pre AR9003 families */
 262        if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) ||
 263            AR_SREV_9565(ah) || AR_SREV_9561(ah))
 264                return;
 265
 266        if (aniState->mrcCCK != entry_cck->mrc_cck_on)
 267                ath9k_hw_ani_control(ah,
 268                                     ATH9K_ANI_MRC_CCK,
 269                                     entry_cck->mrc_cck_on);
 270}
 271
 272static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
 273{
 274        struct ar5416AniState *aniState;
 275
 276        if (!ah->curchan)
 277                return;
 278
 279        aniState = &ah->ani;
 280
 281        if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
 282                ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1,
 283                                     false);
 284}
 285
 286/*
 287 * only lower either OFDM or CCK errors per turn
 288 * we lower the other one next time
 289 */
 290static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
 291{
 292        struct ar5416AniState *aniState;
 293
 294        aniState = &ah->ani;
 295
 296        /* lower OFDM noise immunity */
 297        if (aniState->ofdmNoiseImmunityLevel > 0 &&
 298            (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
 299                ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1,
 300                                      false);
 301                return;
 302        }
 303
 304        /* lower CCK noise immunity */
 305        if (aniState->cckNoiseImmunityLevel > 0)
 306                ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1,
 307                                     false);
 308}
 309
 310/*
 311 * Restore the ANI parameters in the HAL and reset the statistics.
 312 * This routine should be called for every hardware reset and for
 313 * every channel change.
 314 */
 315void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
 316{
 317        struct ar5416AniState *aniState = &ah->ani;
 318        struct ath9k_channel *chan = ah->curchan;
 319        struct ath_common *common = ath9k_hw_common(ah);
 320        int ofdm_nil, cck_nil;
 321
 322        if (!ah->curchan)
 323                return;
 324
 325        BUG_ON(aniState == NULL);
 326        ah->stats.ast_ani_reset++;
 327
 328        ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
 329                         aniState->ofdmNoiseImmunityLevel);
 330        cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
 331                         aniState->cckNoiseImmunityLevel);
 332
 333        if (is_scanning ||
 334            (ah->opmode != NL80211_IFTYPE_STATION &&
 335             ah->opmode != NL80211_IFTYPE_ADHOC)) {
 336                /*
 337                 * If we're scanning or in AP mode, the defaults (ini)
 338                 * should be in place. For an AP we assume the historical
 339                 * levels for this channel are probably outdated so start
 340                 * from defaults instead.
 341                 */
 342                if (aniState->ofdmNoiseImmunityLevel !=
 343                    ATH9K_ANI_OFDM_DEF_LEVEL ||
 344                    aniState->cckNoiseImmunityLevel !=
 345                    ATH9K_ANI_CCK_DEF_LEVEL) {
 346                        ath_dbg(common, ANI,
 347                                "Restore defaults: opmode %u chan %d Mhz is_scanning=%d ofdm:%d cck:%d\n",
 348                                ah->opmode,
 349                                chan->channel,
 350                                is_scanning,
 351                                aniState->ofdmNoiseImmunityLevel,
 352                                aniState->cckNoiseImmunityLevel);
 353
 354                        ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
 355                        cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
 356                }
 357        } else {
 358                /*
 359                 * restore historical levels for this channel
 360                 */
 361                ath_dbg(common, ANI,
 362                        "Restore history: opmode %u chan %d Mhz is_scanning=%d ofdm:%d cck:%d\n",
 363                        ah->opmode,
 364                        chan->channel,
 365                        is_scanning,
 366                        aniState->ofdmNoiseImmunityLevel,
 367                        aniState->cckNoiseImmunityLevel);
 368        }
 369        ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning);
 370        ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning);
 371
 372        ath9k_ani_restart(ah);
 373}
 374
 375static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
 376{
 377        struct ath_common *common = ath9k_hw_common(ah);
 378        struct ar5416AniState *aniState = &ah->ani;
 379        u32 phyCnt1, phyCnt2;
 380        int32_t listenTime;
 381
 382        ath_hw_cycle_counters_update(common);
 383        listenTime = ath_hw_get_listen_time(common);
 384
 385        if (listenTime <= 0) {
 386                ah->stats.ast_ani_lneg_or_lzero++;
 387                ath9k_ani_restart(ah);
 388                return false;
 389        }
 390
 391        aniState->listenTime += listenTime;
 392
 393        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 394
 395        phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
 396        phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
 397
 398        ah->stats.ast_ani_ofdmerrs += phyCnt1 - aniState->ofdmPhyErrCount;
 399        aniState->ofdmPhyErrCount = phyCnt1;
 400
 401        ah->stats.ast_ani_cckerrs += phyCnt2 - aniState->cckPhyErrCount;
 402        aniState->cckPhyErrCount = phyCnt2;
 403
 404        return true;
 405}
 406
 407void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
 408{
 409        struct ar5416AniState *aniState;
 410        struct ath_common *common = ath9k_hw_common(ah);
 411        u32 ofdmPhyErrRate, cckPhyErrRate;
 412
 413        if (!ah->curchan)
 414                return;
 415
 416        aniState = &ah->ani;
 417        if (!ath9k_hw_ani_read_counters(ah))
 418                return;
 419
 420        ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
 421                         aniState->listenTime;
 422        cckPhyErrRate =  aniState->cckPhyErrCount * 1000 /
 423                         aniState->listenTime;
 424
 425        ath_dbg(common, ANI,
 426                "listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
 427                aniState->listenTime,
 428                aniState->ofdmNoiseImmunityLevel,
 429                ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
 430                cckPhyErrRate, aniState->ofdmsTurn);
 431
 432        if (aniState->listenTime > ah->aniperiod) {
 433                if (cckPhyErrRate < ah->config.cck_trig_low &&
 434                    ofdmPhyErrRate < ah->config.ofdm_trig_low) {
 435                        ath9k_hw_ani_lower_immunity(ah);
 436                        aniState->ofdmsTurn = !aniState->ofdmsTurn;
 437                } else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
 438                        ath9k_hw_ani_ofdm_err_trigger(ah);
 439                        aniState->ofdmsTurn = false;
 440                } else if (cckPhyErrRate > ah->config.cck_trig_high) {
 441                        ath9k_hw_ani_cck_err_trigger(ah);
 442                        aniState->ofdmsTurn = true;
 443                }
 444                ath9k_ani_restart(ah);
 445        }
 446}
 447EXPORT_SYMBOL(ath9k_hw_ani_monitor);
 448
 449void ath9k_enable_mib_counters(struct ath_hw *ah)
 450{
 451        struct ath_common *common = ath9k_hw_common(ah);
 452
 453        ath_dbg(common, ANI, "Enable MIB counters\n");
 454
 455        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 456
 457        ENABLE_REGWRITE_BUFFER(ah);
 458
 459        REG_WRITE(ah, AR_FILT_OFDM, 0);
 460        REG_WRITE(ah, AR_FILT_CCK, 0);
 461        REG_WRITE(ah, AR_MIBC,
 462                  ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
 463                  & 0x0f);
 464        REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
 465        REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
 466
 467        REGWRITE_BUFFER_FLUSH(ah);
 468}
 469
 470/* Freeze the MIB counters, get the stats and then clear them */
 471void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
 472{
 473        struct ath_common *common = ath9k_hw_common(ah);
 474
 475        ath_dbg(common, ANI, "Disable MIB counters\n");
 476
 477        REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
 478        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 479        REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
 480        REG_WRITE(ah, AR_FILT_OFDM, 0);
 481        REG_WRITE(ah, AR_FILT_CCK, 0);
 482}
 483EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
 484
 485void ath9k_hw_ani_init(struct ath_hw *ah)
 486{
 487        struct ath_common *common = ath9k_hw_common(ah);
 488        struct ar5416AniState *ani = &ah->ani;
 489
 490        ath_dbg(common, ANI, "Initialize ANI\n");
 491
 492        if (AR_SREV_9300_20_OR_LATER(ah)) {
 493                ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
 494                ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
 495                ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
 496                ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
 497        } else {
 498                ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
 499                ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
 500                ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
 501                ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
 502        }
 503
 504        ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
 505        ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
 506        ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false;
 507        ani->ofdmsTurn = true;
 508        ani->ofdmWeakSigDetect = true;
 509        ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
 510        ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
 511
 512        /*
 513         * since we expect some ongoing maintenance on the tables, let's sanity
 514         * check here default level should not modify INI setting.
 515         */
 516        ah->aniperiod = ATH9K_ANI_PERIOD;
 517        ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL;
 518
 519        ath9k_ani_restart(ah);
 520        ath9k_enable_mib_counters(ah);
 521}
 522