2 * Copyright (c) 2008-2010 Atheros Communications Inc.
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.
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.
17 #include <linux/kernel.h>
21 struct ani_ofdm_level_entry {
22 int spur_immunity_level;
24 int ofdm_weak_signal_on;
27 /* values here are relative to the INI */
34 * WS: OFDM / CCK Weak Signal detection
35 * MRC-CCK: Maximal Ratio Combining for CCK
38 static const struct ani_ofdm_level_entry ofdm_level_table[] = {
40 { 0, 0, 1 }, /* lvl 0 */
41 { 1, 1, 1 }, /* lvl 1 */
42 { 2, 2, 1 }, /* lvl 2 */
43 { 3, 2, 1 }, /* lvl 3 (default) */
44 { 4, 3, 1 }, /* lvl 4 */
45 { 5, 4, 1 }, /* lvl 5 */
46 { 6, 5, 1 }, /* lvl 6 */
47 { 7, 6, 1 }, /* lvl 7 */
48 { 7, 7, 1 }, /* lvl 8 */
49 { 7, 8, 0 } /* lvl 9 */
51 #define ATH9K_ANI_OFDM_NUM_LEVEL \
52 ARRAY_SIZE(ofdm_level_table)
53 #define ATH9K_ANI_OFDM_MAX_LEVEL \
54 (ATH9K_ANI_OFDM_NUM_LEVEL-1)
55 #define ATH9K_ANI_OFDM_DEF_LEVEL \
56 3 /* default level - matches the INI settings */
59 * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
60 * With OFDM for single stream you just add up all antenna inputs, you're
61 * only interested in what you get after FFT. Signal aligment is also not
62 * required for OFDM because any phase difference adds up in the frequency
65 * MRC requires extra work for use with CCK. You need to align the antenna
66 * signals from the different antenna before you can add the signals together.
67 * You need aligment of signals as CCK is in time domain, so addition can cancel
68 * your signal completely if phase is 180 degrees (think of adding sine waves).
69 * You also need to remove noise before the addition and this is where ANI
70 * MRC CCK comes into play. One of the antenna inputs may be stronger but
71 * lower SNR, so just adding after alignment can be dangerous.
73 * Regardless of alignment in time, the antenna signals add constructively after
74 * FFT and improve your reception. For more information:
76 * http://en.wikipedia.org/wiki/Maximal-ratio_combining
79 struct ani_cck_level_entry {
84 static const struct ani_cck_level_entry cck_level_table[] = {
88 { 2, 1 }, /* lvl 2 (default) */
93 { 7, 0 }, /* lvl 7 (only for high rssi) */
94 { 8, 0 } /* lvl 8 (only for high rssi) */
97 #define ATH9K_ANI_CCK_NUM_LEVEL \
98 ARRAY_SIZE(cck_level_table)
99 #define ATH9K_ANI_CCK_MAX_LEVEL \
100 (ATH9K_ANI_CCK_NUM_LEVEL-1)
101 #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
102 (ATH9K_ANI_CCK_NUM_LEVEL-3)
103 #define ATH9K_ANI_CCK_DEF_LEVEL \
104 2 /* default level - matches the INI settings */
106 /* Private to ani.c */
107 static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
109 ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
112 int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
113 struct ath9k_channel *chan)
117 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
119 ah->ani[i].c->channel == chan->channel)
121 if (ah->ani[i].c == NULL) {
127 ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
128 "No more channel states left. Using channel 0\n");
133 static void ath9k_hw_update_mibstats(struct ath_hw *ah,
134 struct ath9k_mib_stats *stats)
136 stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
137 stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
138 stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
139 stats->rts_good += REG_READ(ah, AR_RTS_OK);
140 stats->beacons += REG_READ(ah, AR_BEACON_CNT);
143 static void ath9k_ani_restart_old(struct ath_hw *ah)
145 struct ar5416AniState *aniState;
146 struct ath_common *common = ath9k_hw_common(ah);
151 aniState = ah->curani;
152 aniState->listenTime = 0;
154 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
155 aniState->ofdmPhyErrBase = 0;
156 ath_print(common, ATH_DBG_ANI,
157 "OFDM Trigger is too high for hw counters\n");
159 aniState->ofdmPhyErrBase =
160 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
162 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
163 aniState->cckPhyErrBase = 0;
164 ath_print(common, ATH_DBG_ANI,
165 "CCK Trigger is too high for hw counters\n");
167 aniState->cckPhyErrBase =
168 AR_PHY_COUNTMAX - aniState->cckTrigHigh;
170 ath_print(common, ATH_DBG_ANI,
171 "Writing ofdmbase=%u cckbase=%u\n",
172 aniState->ofdmPhyErrBase,
173 aniState->cckPhyErrBase);
175 ENABLE_REGWRITE_BUFFER(ah);
177 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
178 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
179 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
180 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
182 REGWRITE_BUFFER_FLUSH(ah);
184 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
186 aniState->ofdmPhyErrCount = 0;
187 aniState->cckPhyErrCount = 0;
190 static void ath9k_ani_restart_new(struct ath_hw *ah)
192 struct ar5416AniState *aniState;
193 struct ath_common *common = ath9k_hw_common(ah);
198 aniState = ah->curani;
199 aniState->listenTime = 0;
201 aniState->ofdmPhyErrBase = 0;
202 aniState->cckPhyErrBase = 0;
204 ath_print(common, ATH_DBG_ANI,
205 "Writing ofdmbase=%08x cckbase=%08x\n",
206 aniState->ofdmPhyErrBase,
207 aniState->cckPhyErrBase);
209 ENABLE_REGWRITE_BUFFER(ah);
211 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
212 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
213 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
214 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
216 REGWRITE_BUFFER_FLUSH(ah);
218 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
220 aniState->ofdmPhyErrCount = 0;
221 aniState->cckPhyErrCount = 0;
224 static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
226 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
227 struct ar5416AniState *aniState;
233 aniState = ah->curani;
235 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
236 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
237 aniState->noiseImmunityLevel + 1)) {
242 if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
243 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
244 aniState->spurImmunityLevel + 1)) {
249 if (ah->opmode == NL80211_IFTYPE_AP) {
250 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
251 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
252 aniState->firstepLevel + 1);
256 rssi = BEACON_RSSI(ah);
257 if (rssi > aniState->rssiThrHigh) {
258 if (!aniState->ofdmWeakSigDetectOff) {
259 if (ath9k_hw_ani_control(ah,
260 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
262 ath9k_hw_ani_control(ah,
263 ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
267 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
268 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
269 aniState->firstepLevel + 1);
272 } else if (rssi > aniState->rssiThrLow) {
273 if (aniState->ofdmWeakSigDetectOff)
274 ath9k_hw_ani_control(ah,
275 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
277 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
278 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
279 aniState->firstepLevel + 1);
282 if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
284 if (!aniState->ofdmWeakSigDetectOff)
285 ath9k_hw_ani_control(ah,
286 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
288 if (aniState->firstepLevel > 0)
289 ath9k_hw_ani_control(ah,
290 ATH9K_ANI_FIRSTEP_LEVEL, 0);
296 static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
298 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
299 struct ar5416AniState *aniState;
305 aniState = ah->curani;
306 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
307 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
308 aniState->noiseImmunityLevel + 1)) {
312 if (ah->opmode == NL80211_IFTYPE_AP) {
313 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
314 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
315 aniState->firstepLevel + 1);
319 rssi = BEACON_RSSI(ah);
320 if (rssi > aniState->rssiThrLow) {
321 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
322 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
323 aniState->firstepLevel + 1);
325 if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
327 if (aniState->firstepLevel > 0)
328 ath9k_hw_ani_control(ah,
329 ATH9K_ANI_FIRSTEP_LEVEL, 0);
334 /* Adjust the OFDM Noise Immunity Level */
335 static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
337 struct ar5416AniState *aniState = ah->curani;
338 struct ath_common *common = ath9k_hw_common(ah);
339 const struct ani_ofdm_level_entry *entry_ofdm;
340 const struct ani_cck_level_entry *entry_cck;
342 aniState->noiseFloor = BEACON_RSSI(ah);
344 ath_print(common, ATH_DBG_ANI,
345 "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
346 aniState->ofdmNoiseImmunityLevel,
347 immunityLevel, aniState->noiseFloor,
348 aniState->rssiThrLow, aniState->rssiThrHigh);
350 aniState->ofdmNoiseImmunityLevel = immunityLevel;
352 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
353 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
355 if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
356 ath9k_hw_ani_control(ah,
357 ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
358 entry_ofdm->spur_immunity_level);
360 if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
361 entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
362 ath9k_hw_ani_control(ah,
363 ATH9K_ANI_FIRSTEP_LEVEL,
364 entry_ofdm->fir_step_level);
366 if ((ah->opmode != NL80211_IFTYPE_STATION &&
367 ah->opmode != NL80211_IFTYPE_ADHOC) ||
368 aniState->noiseFloor <= aniState->rssiThrHigh) {
369 if (aniState->ofdmWeakSigDetectOff)
370 /* force on ofdm weak sig detect */
371 ath9k_hw_ani_control(ah,
372 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
374 else if (aniState->ofdmWeakSigDetectOff ==
375 entry_ofdm->ofdm_weak_signal_on)
376 ath9k_hw_ani_control(ah,
377 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
378 entry_ofdm->ofdm_weak_signal_on);
382 static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
384 struct ar5416AniState *aniState;
389 aniState = ah->curani;
391 if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
392 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
396 * Set the ANI settings to match an CCK level.
398 static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
400 struct ar5416AniState *aniState = ah->curani;
401 struct ath_common *common = ath9k_hw_common(ah);
402 const struct ani_ofdm_level_entry *entry_ofdm;
403 const struct ani_cck_level_entry *entry_cck;
405 aniState->noiseFloor = BEACON_RSSI(ah);
406 ath_print(common, ATH_DBG_ANI,
407 "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
408 aniState->cckNoiseImmunityLevel, immunityLevel,
409 aniState->noiseFloor, aniState->rssiThrLow,
410 aniState->rssiThrHigh);
412 if ((ah->opmode == NL80211_IFTYPE_STATION ||
413 ah->opmode == NL80211_IFTYPE_ADHOC) &&
414 aniState->noiseFloor <= aniState->rssiThrLow &&
415 immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
416 immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
418 aniState->cckNoiseImmunityLevel = immunityLevel;
420 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
421 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
423 if (aniState->firstepLevel != entry_cck->fir_step_level &&
424 entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
425 ath9k_hw_ani_control(ah,
426 ATH9K_ANI_FIRSTEP_LEVEL,
427 entry_cck->fir_step_level);
429 /* Skip MRC CCK for pre AR9003 families */
430 if (!AR_SREV_9300_20_OR_LATER(ah))
433 if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
434 ath9k_hw_ani_control(ah,
436 entry_cck->mrc_cck_on);
439 static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
441 struct ar5416AniState *aniState;
446 aniState = ah->curani;
448 if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
449 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
452 static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
454 struct ar5416AniState *aniState;
457 aniState = ah->curani;
459 if (ah->opmode == NL80211_IFTYPE_AP) {
460 if (aniState->firstepLevel > 0) {
461 if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
462 aniState->firstepLevel - 1))
466 rssi = BEACON_RSSI(ah);
467 if (rssi > aniState->rssiThrHigh) {
469 } else if (rssi > aniState->rssiThrLow) {
470 if (aniState->ofdmWeakSigDetectOff) {
471 if (ath9k_hw_ani_control(ah,
472 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
476 if (aniState->firstepLevel > 0) {
477 if (ath9k_hw_ani_control(ah,
478 ATH9K_ANI_FIRSTEP_LEVEL,
479 aniState->firstepLevel - 1) == true)
483 if (aniState->firstepLevel > 0) {
484 if (ath9k_hw_ani_control(ah,
485 ATH9K_ANI_FIRSTEP_LEVEL,
486 aniState->firstepLevel - 1) == true)
492 if (aniState->spurImmunityLevel > 0) {
493 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
494 aniState->spurImmunityLevel - 1))
498 if (aniState->noiseImmunityLevel > 0) {
499 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
500 aniState->noiseImmunityLevel - 1);
506 * only lower either OFDM or CCK errors per turn
507 * we lower the other one next time
509 static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
511 struct ar5416AniState *aniState;
513 aniState = ah->curani;
515 /* lower OFDM noise immunity */
516 if (aniState->ofdmNoiseImmunityLevel > 0 &&
517 (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
518 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
522 /* lower CCK noise immunity */
523 if (aniState->cckNoiseImmunityLevel > 0)
524 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
527 static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
529 struct ath9k_channel *chan = ah->curchan;
530 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
531 u8 clockrate; /* in MHz */
533 if (!ah->curchan) /* should really check for CCK instead */
534 clockrate = ATH9K_CLOCK_RATE_CCK;
535 else if (conf->channel->band == IEEE80211_BAND_2GHZ)
536 clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
537 else if (IS_CHAN_A_FAST_CLOCK(ah, chan))
538 clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
540 clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
542 if (conf_is_ht40(conf))
543 return clockrate * 2;
548 static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
553 ath9k_hw_update_cycle_counters(ah);
554 clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;
555 listen_time = ah->listen_time / clock_rate;
561 static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
563 struct ar5416AniState *aniState;
564 struct ath9k_channel *chan = ah->curchan;
565 struct ath_common *common = ath9k_hw_common(ah);
571 index = ath9k_hw_get_ani_channel_idx(ah, chan);
572 aniState = &ah->ani[index];
573 ah->curani = aniState;
575 if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
576 && ah->opmode != NL80211_IFTYPE_ADHOC) {
577 ath_print(common, ATH_DBG_ANI,
578 "Reset ANI state opmode %u\n", ah->opmode);
579 ah->stats.ast_ani_reset++;
581 if (ah->opmode == NL80211_IFTYPE_AP) {
583 * ath9k_hw_ani_control() will only process items set on
586 if (IS_CHAN_2GHZ(chan))
587 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
588 ATH9K_ANI_FIRSTEP_LEVEL);
590 ah->ani_function = 0;
593 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
594 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
595 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
596 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
597 !ATH9K_ANI_USE_OFDM_WEAK_SIG);
598 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
599 ATH9K_ANI_CCK_WEAK_SIG_THR);
601 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
602 ATH9K_RX_FILTER_PHYERR);
604 if (ah->opmode == NL80211_IFTYPE_AP) {
605 ah->curani->ofdmTrigHigh =
606 ah->config.ofdm_trig_high;
607 ah->curani->ofdmTrigLow =
608 ah->config.ofdm_trig_low;
609 ah->curani->cckTrigHigh =
610 ah->config.cck_trig_high;
611 ah->curani->cckTrigLow =
612 ah->config.cck_trig_low;
614 ath9k_ani_restart_old(ah);
618 if (aniState->noiseImmunityLevel != 0)
619 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
620 aniState->noiseImmunityLevel);
621 if (aniState->spurImmunityLevel != 0)
622 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
623 aniState->spurImmunityLevel);
624 if (aniState->ofdmWeakSigDetectOff)
625 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
626 !aniState->ofdmWeakSigDetectOff);
627 if (aniState->cckWeakSigThreshold)
628 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
629 aniState->cckWeakSigThreshold);
630 if (aniState->firstepLevel != 0)
631 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
632 aniState->firstepLevel);
634 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
635 ~ATH9K_RX_FILTER_PHYERR);
636 ath9k_ani_restart_old(ah);
638 ENABLE_REGWRITE_BUFFER(ah);
640 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
641 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
643 REGWRITE_BUFFER_FLUSH(ah);
647 * Restore the ANI parameters in the HAL and reset the statistics.
648 * This routine should be called for every hardware reset and for
649 * every channel change.
651 static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
653 struct ar5416AniState *aniState = ah->curani;
654 struct ath9k_channel *chan = ah->curchan;
655 struct ath_common *common = ath9k_hw_common(ah);
660 BUG_ON(aniState == NULL);
661 ah->stats.ast_ani_reset++;
663 /* only allow a subset of functions in AP mode */
664 if (ah->opmode == NL80211_IFTYPE_AP) {
665 if (IS_CHAN_2GHZ(chan)) {
666 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
667 ATH9K_ANI_FIRSTEP_LEVEL);
668 if (AR_SREV_9300_20_OR_LATER(ah))
669 ah->ani_function |= ATH9K_ANI_MRC_CCK;
671 ah->ani_function = 0;
674 /* always allow mode (on/off) to be controlled */
675 ah->ani_function |= ATH9K_ANI_MODE;
678 (ah->opmode != NL80211_IFTYPE_STATION &&
679 ah->opmode != NL80211_IFTYPE_ADHOC)) {
681 * If we're scanning or in AP mode, the defaults (ini)
682 * should be in place. For an AP we assume the historical
683 * levels for this channel are probably outdated so start
684 * from defaults instead.
686 if (aniState->ofdmNoiseImmunityLevel !=
687 ATH9K_ANI_OFDM_DEF_LEVEL ||
688 aniState->cckNoiseImmunityLevel !=
689 ATH9K_ANI_CCK_DEF_LEVEL) {
690 ath_print(common, ATH_DBG_ANI,
691 "Restore defaults: opmode %u "
692 "chan %d Mhz/0x%x is_scanning=%d "
698 aniState->ofdmNoiseImmunityLevel,
699 aniState->cckNoiseImmunityLevel);
701 ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
702 ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
706 * restore historical levels for this channel
708 ath_print(common, ATH_DBG_ANI,
709 "Restore history: opmode %u "
710 "chan %d Mhz/0x%x is_scanning=%d "
716 aniState->ofdmNoiseImmunityLevel,
717 aniState->cckNoiseImmunityLevel);
719 ath9k_hw_set_ofdm_nil(ah,
720 aniState->ofdmNoiseImmunityLevel);
721 ath9k_hw_set_cck_nil(ah,
722 aniState->cckNoiseImmunityLevel);
726 * enable phy counters if hw supports or if not, enable phy
727 * interrupts (so we can count each one)
729 ath9k_ani_restart_new(ah);
731 ENABLE_REGWRITE_BUFFER(ah);
733 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
734 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
736 REGWRITE_BUFFER_FLUSH(ah);
739 static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
740 struct ath9k_channel *chan)
742 struct ar5416AniState *aniState;
743 struct ath_common *common = ath9k_hw_common(ah);
745 u32 phyCnt1, phyCnt2;
746 u32 ofdmPhyErrCnt, cckPhyErrCnt;
751 aniState = ah->curani;
753 listenTime = ath9k_hw_ani_get_listen_time(ah);
754 if (listenTime < 0) {
755 ah->stats.ast_ani_lneg++;
756 ath9k_ani_restart_old(ah);
760 aniState->listenTime += listenTime;
762 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
764 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
765 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
767 if (phyCnt1 < aniState->ofdmPhyErrBase ||
768 phyCnt2 < aniState->cckPhyErrBase) {
769 if (phyCnt1 < aniState->ofdmPhyErrBase) {
770 ath_print(common, ATH_DBG_ANI,
771 "phyCnt1 0x%x, resetting "
772 "counter value to 0x%x\n",
774 aniState->ofdmPhyErrBase);
775 REG_WRITE(ah, AR_PHY_ERR_1,
776 aniState->ofdmPhyErrBase);
777 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
778 AR_PHY_ERR_OFDM_TIMING);
780 if (phyCnt2 < aniState->cckPhyErrBase) {
781 ath_print(common, ATH_DBG_ANI,
782 "phyCnt2 0x%x, resetting "
783 "counter value to 0x%x\n",
785 aniState->cckPhyErrBase);
786 REG_WRITE(ah, AR_PHY_ERR_2,
787 aniState->cckPhyErrBase);
788 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
789 AR_PHY_ERR_CCK_TIMING);
794 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
795 ah->stats.ast_ani_ofdmerrs +=
796 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
797 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
799 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
800 ah->stats.ast_ani_cckerrs +=
801 cckPhyErrCnt - aniState->cckPhyErrCount;
802 aniState->cckPhyErrCount = cckPhyErrCnt;
804 if (aniState->listenTime > 5 * ah->aniperiod) {
805 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
806 aniState->ofdmTrigLow / 1000 &&
807 aniState->cckPhyErrCount <= aniState->listenTime *
808 aniState->cckTrigLow / 1000)
809 ath9k_hw_ani_lower_immunity(ah);
810 ath9k_ani_restart_old(ah);
811 } else if (aniState->listenTime > ah->aniperiod) {
812 if (aniState->ofdmPhyErrCount > aniState->listenTime *
813 aniState->ofdmTrigHigh / 1000) {
814 ath9k_hw_ani_ofdm_err_trigger_old(ah);
815 ath9k_ani_restart_old(ah);
816 } else if (aniState->cckPhyErrCount >
817 aniState->listenTime * aniState->cckTrigHigh /
819 ath9k_hw_ani_cck_err_trigger_old(ah);
820 ath9k_ani_restart_old(ah);
825 static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
826 struct ath9k_channel *chan)
828 struct ar5416AniState *aniState;
829 struct ath_common *common = ath9k_hw_common(ah);
831 u32 phyCnt1, phyCnt2;
832 u32 ofdmPhyErrCnt, cckPhyErrCnt;
833 u32 ofdmPhyErrRate, cckPhyErrRate;
838 aniState = ah->curani;
839 if (WARN_ON(!aniState))
842 listenTime = ath9k_hw_ani_get_listen_time(ah);
843 if (listenTime <= 0) {
844 ah->stats.ast_ani_lneg++;
845 /* restart ANI period if listenTime is invalid */
846 ath_print(common, ATH_DBG_ANI,
847 "listenTime=%d - on new ani monitor\n",
849 ath9k_ani_restart_new(ah);
853 aniState->listenTime += listenTime;
855 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
857 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
858 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
860 if (phyCnt1 < aniState->ofdmPhyErrBase ||
861 phyCnt2 < aniState->cckPhyErrBase) {
862 if (phyCnt1 < aniState->ofdmPhyErrBase) {
863 ath_print(common, ATH_DBG_ANI,
864 "phyCnt1 0x%x, resetting "
865 "counter value to 0x%x\n",
867 aniState->ofdmPhyErrBase);
868 REG_WRITE(ah, AR_PHY_ERR_1,
869 aniState->ofdmPhyErrBase);
870 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
871 AR_PHY_ERR_OFDM_TIMING);
873 if (phyCnt2 < aniState->cckPhyErrBase) {
874 ath_print(common, ATH_DBG_ANI,
875 "phyCnt2 0x%x, resetting "
876 "counter value to 0x%x\n",
878 aniState->cckPhyErrBase);
879 REG_WRITE(ah, AR_PHY_ERR_2,
880 aniState->cckPhyErrBase);
881 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
882 AR_PHY_ERR_CCK_TIMING);
887 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
888 ah->stats.ast_ani_ofdmerrs +=
889 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
890 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
892 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
893 ah->stats.ast_ani_cckerrs +=
894 cckPhyErrCnt - aniState->cckPhyErrCount;
895 aniState->cckPhyErrCount = cckPhyErrCnt;
897 ath_print(common, ATH_DBG_ANI,
898 "Errors: OFDM=0x%08x-0x%08x=%d "
899 "CCK=0x%08x-0x%08x=%d\n",
901 aniState->ofdmPhyErrBase,
904 aniState->cckPhyErrBase,
907 ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
908 aniState->listenTime;
909 cckPhyErrRate = aniState->cckPhyErrCount * 1000 /
910 aniState->listenTime;
912 ath_print(common, ATH_DBG_ANI,
913 "listenTime=%d OFDM:%d errs=%d/s CCK:%d "
914 "errs=%d/s ofdm_turn=%d\n",
915 listenTime, aniState->ofdmNoiseImmunityLevel,
916 ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
917 cckPhyErrRate, aniState->ofdmsTurn);
919 if (aniState->listenTime > 5 * ah->aniperiod) {
920 if (ofdmPhyErrRate <= aniState->ofdmTrigLow &&
921 cckPhyErrRate <= aniState->cckTrigLow) {
922 ath_print(common, ATH_DBG_ANI,
923 "1. listenTime=%d OFDM:%d errs=%d/s(<%d) "
924 "CCK:%d errs=%d/s(<%d) -> "
925 "ath9k_hw_ani_lower_immunity()\n",
926 aniState->listenTime,
927 aniState->ofdmNoiseImmunityLevel,
929 aniState->ofdmTrigLow,
930 aniState->cckNoiseImmunityLevel,
932 aniState->cckTrigLow);
933 ath9k_hw_ani_lower_immunity(ah);
934 aniState->ofdmsTurn = !aniState->ofdmsTurn;
936 ath_print(common, ATH_DBG_ANI,
937 "1 listenTime=%d ofdm=%d/s cck=%d/s - "
938 "calling ath9k_ani_restart_new()\n",
939 aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate);
940 ath9k_ani_restart_new(ah);
941 } else if (aniState->listenTime > ah->aniperiod) {
942 /* check to see if need to raise immunity */
943 if (ofdmPhyErrRate > aniState->ofdmTrigHigh &&
944 (cckPhyErrRate <= aniState->cckTrigHigh ||
945 aniState->ofdmsTurn)) {
946 ath_print(common, ATH_DBG_ANI,
947 "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> "
948 "ath9k_hw_ani_ofdm_err_trigger_new()\n",
949 aniState->listenTime,
950 aniState->ofdmNoiseImmunityLevel,
952 aniState->ofdmTrigHigh);
953 ath9k_hw_ani_ofdm_err_trigger_new(ah);
954 ath9k_ani_restart_new(ah);
955 aniState->ofdmsTurn = false;
956 } else if (cckPhyErrRate > aniState->cckTrigHigh) {
957 ath_print(common, ATH_DBG_ANI,
958 "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> "
959 "ath9k_hw_ani_cck_err_trigger_new()\n",
960 aniState->listenTime,
961 aniState->cckNoiseImmunityLevel,
963 aniState->cckTrigHigh);
964 ath9k_hw_ani_cck_err_trigger_new(ah);
965 ath9k_ani_restart_new(ah);
966 aniState->ofdmsTurn = true;
971 void ath9k_enable_mib_counters(struct ath_hw *ah)
973 struct ath_common *common = ath9k_hw_common(ah);
975 ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
977 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
979 ENABLE_REGWRITE_BUFFER(ah);
981 REG_WRITE(ah, AR_FILT_OFDM, 0);
982 REG_WRITE(ah, AR_FILT_CCK, 0);
983 REG_WRITE(ah, AR_MIBC,
984 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
986 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
987 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
989 REGWRITE_BUFFER_FLUSH(ah);
992 /* Freeze the MIB counters, get the stats and then clear them */
993 void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
995 struct ath_common *common = ath9k_hw_common(ah);
997 ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
999 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
1000 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1001 REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
1002 REG_WRITE(ah, AR_FILT_OFDM, 0);
1003 REG_WRITE(ah, AR_FILT_CCK, 0);
1005 EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
1007 void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
1009 struct ath_cycle_counters cc;
1012 memcpy(&cc, &ah->cc, sizeof(cc));
1014 /* freeze counters */
1015 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
1017 ah->cc.cycles = REG_READ(ah, AR_CCCNT);
1018 if (ah->cc.cycles < cc.cycles) {
1023 ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
1024 ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
1025 ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
1027 /* prevent wraparound */
1028 if (ah->cc.cycles & BIT(31))
1031 #define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
1032 CC_DELTA(cycles, AR_CCCNT);
1033 CC_DELTA(rx_frame, AR_RFCNT);
1034 CC_DELTA(rx_clear, AR_RCCNT);
1035 CC_DELTA(tx_frame, AR_TFCNT);
1038 ah->listen_time += (ah->cc.cycles - cc.cycles) -
1039 ((ah->cc.rx_frame - cc.rx_frame) +
1040 (ah->cc.tx_frame - cc.tx_frame));
1044 REG_WRITE(ah, AR_CCCNT, 0);
1045 REG_WRITE(ah, AR_RFCNT, 0);
1046 REG_WRITE(ah, AR_RCCNT, 0);
1047 REG_WRITE(ah, AR_TFCNT, 0);
1048 memset(&ah->cc, 0, sizeof(ah->cc));
1051 /* unfreeze counters */
1052 REG_WRITE(ah, AR_MIBC, 0);
1056 * Process a MIB interrupt. We may potentially be invoked because
1057 * any of the MIB counters overflow/trigger so don't assume we're
1058 * here because a PHY error counter triggered.
1060 static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
1062 u32 phyCnt1, phyCnt2;
1064 /* Reset these counters regardless */
1065 REG_WRITE(ah, AR_FILT_OFDM, 0);
1066 REG_WRITE(ah, AR_FILT_CCK, 0);
1067 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
1068 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
1070 /* Clear the mib counters and save them in the stats */
1071 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1075 * We must always clear the interrupt cause by
1076 * resetting the phy error regs.
1078 REG_WRITE(ah, AR_PHY_ERR_1, 0);
1079 REG_WRITE(ah, AR_PHY_ERR_2, 0);
1083 /* NB: these are not reset-on-read */
1084 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
1085 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
1086 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
1087 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
1088 struct ar5416AniState *aniState = ah->curani;
1089 u32 ofdmPhyErrCnt, cckPhyErrCnt;
1091 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
1092 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
1093 ah->stats.ast_ani_ofdmerrs +=
1094 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
1095 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
1097 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
1098 ah->stats.ast_ani_cckerrs +=
1099 cckPhyErrCnt - aniState->cckPhyErrCount;
1100 aniState->cckPhyErrCount = cckPhyErrCnt;
1103 * NB: figure out which counter triggered. If both
1104 * trigger we'll only deal with one as the processing
1105 * clobbers the error counter so the trigger threshold
1106 * check will never be true.
1108 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
1109 ath9k_hw_ani_ofdm_err_trigger_new(ah);
1110 if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
1111 ath9k_hw_ani_cck_err_trigger_old(ah);
1112 /* NB: always restart to insure the h/w counters are reset */
1113 ath9k_ani_restart_old(ah);
1118 * Process a MIB interrupt. We may potentially be invoked because
1119 * any of the MIB counters overflow/trigger so don't assume we're
1120 * here because a PHY error counter triggered.
1122 static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
1124 u32 phyCnt1, phyCnt2;
1126 /* Reset these counters regardless */
1127 REG_WRITE(ah, AR_FILT_OFDM, 0);
1128 REG_WRITE(ah, AR_FILT_CCK, 0);
1129 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
1130 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
1132 /* Clear the mib counters and save them in the stats */
1133 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1137 * We must always clear the interrupt cause by
1138 * resetting the phy error regs.
1140 REG_WRITE(ah, AR_PHY_ERR_1, 0);
1141 REG_WRITE(ah, AR_PHY_ERR_2, 0);
1145 /* NB: these are not reset-on-read */
1146 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
1147 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
1149 /* NB: always restart to insure the h/w counters are reset */
1150 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
1151 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK))
1152 ath9k_ani_restart_new(ah);
1155 void ath9k_hw_ani_setup(struct ath_hw *ah)
1159 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
1160 const int coarseHigh[] = { -14, -14, -14, -14, -12 };
1161 const int coarseLow[] = { -64, -64, -64, -64, -70 };
1162 const int firpwr[] = { -78, -78, -78, -78, -80 };
1164 for (i = 0; i < 5; i++) {
1165 ah->totalSizeDesired[i] = totalSizeDesired[i];
1166 ah->coarse_high[i] = coarseHigh[i];
1167 ah->coarse_low[i] = coarseLow[i];
1168 ah->firpwr[i] = firpwr[i];
1172 void ath9k_hw_ani_init(struct ath_hw *ah)
1174 struct ath_common *common = ath9k_hw_common(ah);
1177 ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
1179 memset(ah->ani, 0, sizeof(ah->ani));
1180 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
1181 if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
1182 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
1183 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
1185 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
1186 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW;
1188 ah->ani[i].spurImmunityLevel =
1189 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
1191 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
1193 ah->ani[i].ofdmPhyErrBase = 0;
1194 ah->ani[i].cckPhyErrBase = 0;
1196 if (AR_SREV_9300_20_OR_LATER(ah))
1197 ah->ani[i].mrcCCKOff =
1198 !ATH9K_ANI_ENABLE_MRC_CCK;
1200 ah->ani[i].mrcCCKOff = true;
1202 ah->ani[i].ofdmsTurn = true;
1204 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1205 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
1207 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1208 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD;
1210 ah->ani[i].spurImmunityLevel =
1211 ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
1212 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
1214 ah->ani[i].ofdmPhyErrBase =
1215 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1216 ah->ani[i].cckPhyErrBase =
1217 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1218 ah->ani[i].cckWeakSigThreshold =
1219 ATH9K_ANI_CCK_WEAK_SIG_THR;
1222 ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
1223 ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
1224 ah->ani[i].ofdmWeakSigDetectOff =
1225 !ATH9K_ANI_USE_OFDM_WEAK_SIG;
1226 ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
1230 * since we expect some ongoing maintenance on the tables, let's sanity
1231 * check here default level should not modify INI setting.
1233 if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
1234 const struct ani_ofdm_level_entry *entry_ofdm;
1235 const struct ani_cck_level_entry *entry_cck;
1237 entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL];
1238 entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL];
1240 ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
1241 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
1243 ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
1244 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
1247 ath_print(common, ATH_DBG_ANI,
1248 "Setting OfdmErrBase = 0x%08x\n",
1249 ah->ani[0].ofdmPhyErrBase);
1250 ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
1251 ah->ani[0].cckPhyErrBase);
1253 ENABLE_REGWRITE_BUFFER(ah);
1255 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
1256 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
1258 REGWRITE_BUFFER_FLUSH(ah);
1260 ath9k_enable_mib_counters(ah);
1262 if (ah->config.enable_ani)
1263 ah->proc_phyerr |= HAL_PROCESS_ANI;
1266 void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
1268 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1269 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1271 priv_ops->ani_reset = ath9k_ani_reset_old;
1272 priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old;
1274 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
1275 ops->ani_monitor = ath9k_hw_ani_monitor_old;
1277 ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
1280 void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
1282 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1283 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1285 priv_ops->ani_reset = ath9k_ani_reset_new;
1286 priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
1288 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
1289 ops->ani_monitor = ath9k_hw_ani_monitor_new;
1291 ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");