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 (!scan)
 159                aniState->ofdmNoiseImmunityLevel = immunityLevel;
 160
 161        entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
 162        entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
 163
 164        if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
 165                ath9k_hw_ani_control(ah,
 166                                     ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
 167                                     entry_ofdm->spur_immunity_level);
 168
 169        if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
 170            entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
 171                ath9k_hw_ani_control(ah,
 172                                     ATH9K_ANI_FIRSTEP_LEVEL,
 173                                     entry_ofdm->fir_step_level);
 174
 175        weak_sig = entry_ofdm->ofdm_weak_signal_on;
 176        if (ah->opmode == NL80211_IFTYPE_STATION &&
 177            BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH)
 178                weak_sig = true;
 179
 180        /*
 181         * OFDM Weak signal detection is always enabled for AP mode.
 182         */
 183        if (ah->opmode != NL80211_IFTYPE_AP &&
 184            aniState->ofdmWeakSigDetect != weak_sig) {
 185                ath9k_hw_ani_control(ah,
 186                                     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
 187                                     entry_ofdm->ofdm_weak_signal_on);
 188        }
 189
 190        if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
 191                ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
 192                ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI;
 193        } else {
 194                ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI;
 195                ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
 196        }
 197}
 198
 199static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
 200{
 201        struct ar5416AniState *aniState;
 202
 203        if (!ah->curchan)
 204                return;
 205
 206        aniState = &ah->ani;
 207
 208        if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
 209                ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false);
 210}
 211
 212/*
 213 * Set the ANI settings to match an CCK level.
 214 */
 215static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
 216                                 bool scan)
 217{
 218        struct ar5416AniState *aniState = &ah->ani;
 219        struct ath_common *common = ath9k_hw_common(ah);
 220        const struct ani_ofdm_level_entry *entry_ofdm;
 221        const struct ani_cck_level_entry *entry_cck;
 222
 223        ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
 224                aniState->cckNoiseImmunityLevel, immunityLevel,
 225                BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
 226                ATH9K_ANI_RSSI_THR_HIGH);
 227
 228        if (ah->opmode == NL80211_IFTYPE_STATION &&
 229            BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
 230            immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
 231                immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
 232
 233        if (!scan)
 234                aniState->cckNoiseImmunityLevel = immunityLevel;
 235
 236        entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
 237        entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
 238
 239        if (aniState->firstepLevel != entry_cck->fir_step_level &&
 240            entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
 241                ath9k_hw_ani_control(ah,
 242                                     ATH9K_ANI_FIRSTEP_LEVEL,
 243                                     entry_cck->fir_step_level);
 244
 245        /* Skip MRC CCK for pre AR9003 families */
 246        if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah))
 247                return;
 248
 249        if (aniState->mrcCCK != entry_cck->mrc_cck_on)
 250                ath9k_hw_ani_control(ah,
 251                                     ATH9K_ANI_MRC_CCK,
 252                                     entry_cck->mrc_cck_on);
 253}
 254
 255static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
 256{
 257        struct ar5416AniState *aniState;
 258
 259        if (!ah->curchan)
 260                return;
 261
 262        aniState = &ah->ani;
 263
 264        if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
 265                ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1,
 266                                     false);
 267}
 268
 269/*
 270 * only lower either OFDM or CCK errors per turn
 271 * we lower the other one next time
 272 */
 273static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
 274{
 275        struct ar5416AniState *aniState;
 276
 277        aniState = &ah->ani;
 278
 279        /* lower OFDM noise immunity */
 280        if (aniState->ofdmNoiseImmunityLevel > 0 &&
 281            (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
 282                ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1,
 283                                      false);
 284                return;
 285        }
 286
 287        /* lower CCK noise immunity */
 288        if (aniState->cckNoiseImmunityLevel > 0)
 289                ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1,
 290                                     false);
 291}
 292
 293/*
 294 * Restore the ANI parameters in the HAL and reset the statistics.
 295 * This routine should be called for every hardware reset and for
 296 * every channel change.
 297 */
 298void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
 299{
 300        struct ar5416AniState *aniState = &ah->ani;
 301        struct ath9k_channel *chan = ah->curchan;
 302        struct ath_common *common = ath9k_hw_common(ah);
 303        int ofdm_nil, cck_nil;
 304
 305        if (!ah->curchan)
 306                return;
 307
 308        BUG_ON(aniState == NULL);
 309        ah->stats.ast_ani_reset++;
 310
 311        /* only allow a subset of functions in AP mode */
 312        if (ah->opmode == NL80211_IFTYPE_AP) {
 313                if (IS_CHAN_2GHZ(chan)) {
 314                        ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
 315                                            ATH9K_ANI_FIRSTEP_LEVEL);
 316                        if (AR_SREV_9300_20_OR_LATER(ah))
 317                                ah->ani_function |= ATH9K_ANI_MRC_CCK;
 318                } else
 319                        ah->ani_function = 0;
 320        }
 321
 322        ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
 323                         aniState->ofdmNoiseImmunityLevel);
 324        cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
 325                         aniState->cckNoiseImmunityLevel);
 326
 327        if (is_scanning ||
 328            (ah->opmode != NL80211_IFTYPE_STATION &&
 329             ah->opmode != NL80211_IFTYPE_ADHOC)) {
 330                /*
 331                 * If we're scanning or in AP mode, the defaults (ini)
 332                 * should be in place. For an AP we assume the historical
 333                 * levels for this channel are probably outdated so start
 334                 * from defaults instead.
 335                 */
 336                if (aniState->ofdmNoiseImmunityLevel !=
 337                    ATH9K_ANI_OFDM_DEF_LEVEL ||
 338                    aniState->cckNoiseImmunityLevel !=
 339                    ATH9K_ANI_CCK_DEF_LEVEL) {
 340                        ath_dbg(common, ANI,
 341                                "Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
 342                                ah->opmode,
 343                                chan->channel,
 344                                chan->channelFlags,
 345                                is_scanning,
 346                                aniState->ofdmNoiseImmunityLevel,
 347                                aniState->cckNoiseImmunityLevel);
 348
 349                        ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
 350                        cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
 351                }
 352        } else {
 353                /*
 354                 * restore historical levels for this channel
 355                 */
 356                ath_dbg(common, ANI,
 357                        "Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
 358                        ah->opmode,
 359                        chan->channel,
 360                        chan->channelFlags,
 361                        is_scanning,
 362                        aniState->ofdmNoiseImmunityLevel,
 363                        aniState->cckNoiseImmunityLevel);
 364        }
 365        ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning);
 366        ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning);
 367
 368        ath9k_ani_restart(ah);
 369}
 370
 371static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
 372{
 373        struct ath_common *common = ath9k_hw_common(ah);
 374        struct ar5416AniState *aniState = &ah->ani;
 375        u32 phyCnt1, phyCnt2;
 376        int32_t listenTime;
 377
 378        ath_hw_cycle_counters_update(common);
 379        listenTime = ath_hw_get_listen_time(common);
 380
 381        if (listenTime <= 0) {
 382                ah->stats.ast_ani_lneg_or_lzero++;
 383                ath9k_ani_restart(ah);
 384                return false;
 385        }
 386
 387        aniState->listenTime += listenTime;
 388
 389        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 390
 391        phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
 392        phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
 393
 394        ah->stats.ast_ani_ofdmerrs += phyCnt1 - aniState->ofdmPhyErrCount;
 395        aniState->ofdmPhyErrCount = phyCnt1;
 396
 397        ah->stats.ast_ani_cckerrs += phyCnt2 - aniState->cckPhyErrCount;
 398        aniState->cckPhyErrCount = phyCnt2;
 399
 400        return true;
 401}
 402
 403void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
 404{
 405        struct ar5416AniState *aniState;
 406        struct ath_common *common = ath9k_hw_common(ah);
 407        u32 ofdmPhyErrRate, cckPhyErrRate;
 408
 409        if (!ah->curchan)
 410                return;
 411
 412        aniState = &ah->ani;
 413        if (!ath9k_hw_ani_read_counters(ah))
 414                return;
 415
 416        ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
 417                         aniState->listenTime;
 418        cckPhyErrRate =  aniState->cckPhyErrCount * 1000 /
 419                         aniState->listenTime;
 420
 421        ath_dbg(common, ANI,
 422                "listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
 423                aniState->listenTime,
 424                aniState->ofdmNoiseImmunityLevel,
 425                ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
 426                cckPhyErrRate, aniState->ofdmsTurn);
 427
 428        if (aniState->listenTime > ah->aniperiod) {
 429                if (cckPhyErrRate < ah->config.cck_trig_low &&
 430                    ofdmPhyErrRate < ah->config.ofdm_trig_low) {
 431                        ath9k_hw_ani_lower_immunity(ah);
 432                        aniState->ofdmsTurn = !aniState->ofdmsTurn;
 433                } else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
 434                        ath9k_hw_ani_ofdm_err_trigger(ah);
 435                        aniState->ofdmsTurn = false;
 436                } else if (cckPhyErrRate > ah->config.cck_trig_high) {
 437                        ath9k_hw_ani_cck_err_trigger(ah);
 438                        aniState->ofdmsTurn = true;
 439                }
 440                ath9k_ani_restart(ah);
 441        }
 442}
 443EXPORT_SYMBOL(ath9k_hw_ani_monitor);
 444
 445void ath9k_enable_mib_counters(struct ath_hw *ah)
 446{
 447        struct ath_common *common = ath9k_hw_common(ah);
 448
 449        ath_dbg(common, ANI, "Enable MIB counters\n");
 450
 451        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 452
 453        ENABLE_REGWRITE_BUFFER(ah);
 454
 455        REG_WRITE(ah, AR_FILT_OFDM, 0);
 456        REG_WRITE(ah, AR_FILT_CCK, 0);
 457        REG_WRITE(ah, AR_MIBC,
 458                  ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
 459                  & 0x0f);
 460        REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
 461        REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
 462
 463        REGWRITE_BUFFER_FLUSH(ah);
 464}
 465
 466/* Freeze the MIB counters, get the stats and then clear them */
 467void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
 468{
 469        struct ath_common *common = ath9k_hw_common(ah);
 470
 471        ath_dbg(common, ANI, "Disable MIB counters\n");
 472
 473        REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
 474        ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
 475        REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
 476        REG_WRITE(ah, AR_FILT_OFDM, 0);
 477        REG_WRITE(ah, AR_FILT_CCK, 0);
 478}
 479EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
 480
 481void ath9k_hw_ani_init(struct ath_hw *ah)
 482{
 483        struct ath_common *common = ath9k_hw_common(ah);
 484        struct ar5416AniState *ani = &ah->ani;
 485
 486        ath_dbg(common, ANI, "Initialize ANI\n");
 487
 488        ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
 489        ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
 490        ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
 491        ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
 492
 493        ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
 494        ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
 495        ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false;
 496        ani->ofdmsTurn = true;
 497        ani->ofdmWeakSigDetect = true;
 498        ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
 499        ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
 500
 501        /*
 502         * since we expect some ongoing maintenance on the tables, let's sanity
 503         * check here default level should not modify INI setting.
 504         */
 505        ah->aniperiod = ATH9K_ANI_PERIOD;
 506        ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL;
 507
 508        ath9k_ani_restart(ah);
 509        ath9k_enable_mib_counters(ah);
 510}
 511