2 * Copyright (c) 2008-2011 Atheros Communications Inc.
4 * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
5 * Original from Linux kernel 3.0.1
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.
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.
23 struct ani_ofdm_level_entry {
24 int spur_immunity_level;
26 int ofdm_weak_signal_on;
29 /* values here are relative to the INI */
36 * WS: OFDM / CCK Weak Signal detection
37 * MRC-CCK: Maximal Ratio Combining for CCK
40 static const struct ani_ofdm_level_entry ofdm_level_table[] = {
42 { 0, 0, 1 }, /* lvl 0 */
43 { 1, 1, 1 }, /* lvl 1 */
44 { 2, 2, 1 }, /* lvl 2 */
45 { 3, 2, 1 }, /* lvl 3 (default) */
46 { 4, 3, 1 }, /* lvl 4 */
47 { 5, 4, 1 }, /* lvl 5 */
48 { 6, 5, 1 }, /* lvl 6 */
49 { 7, 6, 1 }, /* lvl 7 */
50 { 7, 7, 1 }, /* lvl 8 */
51 { 7, 8, 0 } /* lvl 9 */
53 #define ATH9K_ANI_OFDM_NUM_LEVEL \
54 ARRAY_SIZE(ofdm_level_table)
55 #define ATH9K_ANI_OFDM_MAX_LEVEL \
56 (ATH9K_ANI_OFDM_NUM_LEVEL-1)
57 #define ATH9K_ANI_OFDM_DEF_LEVEL \
58 3 /* default level - matches the INI settings */
61 * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
62 * With OFDM for single stream you just add up all antenna inputs, you're
63 * only interested in what you get after FFT. Signal aligment is also not
64 * required for OFDM because any phase difference adds up in the frequency
67 * MRC requires extra work for use with CCK. You need to align the antenna
68 * signals from the different antenna before you can add the signals together.
69 * You need aligment of signals as CCK is in time domain, so addition can cancel
70 * your signal completely if phase is 180 degrees (think of adding sine waves).
71 * You also need to remove noise before the addition and this is where ANI
72 * MRC CCK comes into play. One of the antenna inputs may be stronger but
73 * lower SNR, so just adding after alignment can be dangerous.
75 * Regardless of alignment in time, the antenna signals add constructively after
76 * FFT and improve your reception. For more information:
78 * http://en.wikipedia.org/wiki/Maximal-ratio_combining
81 struct ani_cck_level_entry {
86 static const struct ani_cck_level_entry cck_level_table[] = {
90 { 2, 1 }, /* lvl 2 (default) */
95 { 7, 0 }, /* lvl 7 (only for high rssi) */
96 { 8, 0 } /* lvl 8 (only for high rssi) */
99 #define ATH9K_ANI_CCK_NUM_LEVEL \
100 ARRAY_SIZE(cck_level_table)
101 #define ATH9K_ANI_CCK_MAX_LEVEL \
102 (ATH9K_ANI_CCK_NUM_LEVEL-1)
103 #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
104 (ATH9K_ANI_CCK_NUM_LEVEL-3)
105 #define ATH9K_ANI_CCK_DEF_LEVEL \
106 2 /* default level - matches the INI settings */
108 static int use_new_ani(struct ath_hw *ah)
110 return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
113 static void ath9k_hw_update_mibstats(struct ath_hw *ah,
114 struct ath9k_mib_stats *stats)
116 stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
117 stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
118 stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
119 stats->rts_good += REG_READ(ah, AR_RTS_OK);
120 stats->beacons += REG_READ(ah, AR_BEACON_CNT);
123 static void ath9k_ani_restart(struct ath_hw *ah)
125 struct ar5416AniState *aniState;
126 u32 ofdm_base = 0, cck_base = 0;
131 aniState = &ah->curchan->ani;
132 aniState->listenTime = 0;
134 if (!use_new_ani(ah)) {
135 ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
136 cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
140 "Writing ofdmbase=%d cckbase=%d\n", ofdm_base, cck_base);
142 ENABLE_REGWRITE_BUFFER(ah);
144 REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
145 REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
146 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
147 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
149 REGWRITE_BUFFER_FLUSH(ah);
151 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
153 aniState->ofdmPhyErrCount = 0;
154 aniState->cckPhyErrCount = 0;
157 static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
159 struct ar5416AniState *aniState;
162 aniState = &ah->curchan->ani;
164 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
165 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
166 aniState->noiseImmunityLevel + 1)) {
171 if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
172 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
173 aniState->spurImmunityLevel + 1)) {
178 rssi = BEACON_RSSI(ah);
179 if (rssi > aniState->rssiThrHigh) {
180 if (aniState->ofdmWeakSigDetect) {
181 if (ath9k_hw_ani_control(ah,
182 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
184 ath9k_hw_ani_control(ah,
185 ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
189 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
190 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
191 aniState->firstepLevel + 1);
194 } else if (rssi > aniState->rssiThrLow) {
195 if (!aniState->ofdmWeakSigDetect)
196 ath9k_hw_ani_control(ah,
197 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
199 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
200 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
201 aniState->firstepLevel + 1);
204 if ((ah->dev->channels + ah->dev->channel)->band == NET80211_BAND_2GHZ) {
205 if (aniState->ofdmWeakSigDetect)
206 ath9k_hw_ani_control(ah,
207 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
209 if (aniState->firstepLevel > 0)
210 ath9k_hw_ani_control(ah,
211 ATH9K_ANI_FIRSTEP_LEVEL, 0);
217 static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
219 struct ar5416AniState *aniState;
222 aniState = &ah->curchan->ani;
223 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
224 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
225 aniState->noiseImmunityLevel + 1)) {
229 rssi = BEACON_RSSI(ah);
230 if (rssi > aniState->rssiThrLow) {
231 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
232 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
233 aniState->firstepLevel + 1);
235 if ((ah->dev->channels + ah->dev->channel)->band == NET80211_BAND_2GHZ) {
236 if (aniState->firstepLevel > 0)
237 ath9k_hw_ani_control(ah,
238 ATH9K_ANI_FIRSTEP_LEVEL, 0);
243 /* Adjust the OFDM Noise Immunity Level */
244 static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
246 struct ar5416AniState *aniState = &ah->curchan->ani;
247 const struct ani_ofdm_level_entry *entry_ofdm;
248 const struct ani_cck_level_entry *entry_cck;
250 aniState->noiseFloor = BEACON_RSSI(ah);
253 "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
254 aniState->ofdmNoiseImmunityLevel,
255 immunityLevel, aniState->noiseFloor,
256 aniState->rssiThrLow, aniState->rssiThrHigh);
258 aniState->ofdmNoiseImmunityLevel = immunityLevel;
260 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
261 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
263 if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
264 ath9k_hw_ani_control(ah,
265 ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
266 entry_ofdm->spur_immunity_level);
268 if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
269 entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
270 ath9k_hw_ani_control(ah,
271 ATH9K_ANI_FIRSTEP_LEVEL,
272 entry_ofdm->fir_step_level);
275 static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
277 struct ar5416AniState *aniState;
282 if (!use_new_ani(ah)) {
283 ath9k_hw_ani_ofdm_err_trigger_old(ah);
287 aniState = &ah->curchan->ani;
289 if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
290 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
294 * Set the ANI settings to match an CCK level.
296 static void ath9k_hw_set_cck_nil(struct ath_hw *ah, uint8_t immunityLevel)
298 struct ar5416AniState *aniState = &ah->curchan->ani;
299 const struct ani_ofdm_level_entry *entry_ofdm;
300 const struct ani_cck_level_entry *entry_cck;
302 aniState->noiseFloor = BEACON_RSSI(ah);
304 "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
305 aniState->cckNoiseImmunityLevel, immunityLevel,
306 aniState->noiseFloor, aniState->rssiThrLow,
307 aniState->rssiThrHigh);
309 if (aniState->noiseFloor <= (unsigned int)aniState->rssiThrLow &&
310 immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
311 immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
313 aniState->cckNoiseImmunityLevel = immunityLevel;
315 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
316 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
318 if (aniState->firstepLevel != entry_cck->fir_step_level &&
319 entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
320 ath9k_hw_ani_control(ah,
321 ATH9K_ANI_FIRSTEP_LEVEL,
322 entry_cck->fir_step_level);
324 /* Skip MRC CCK for pre AR9003 families */
325 if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
328 if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
329 ath9k_hw_ani_control(ah,
331 entry_cck->mrc_cck_on);
334 static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
336 struct ar5416AniState *aniState;
341 if (!use_new_ani(ah)) {
342 ath9k_hw_ani_cck_err_trigger_old(ah);
346 aniState = &ah->curchan->ani;
348 if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
349 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
352 static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
354 struct ar5416AniState *aniState;
357 aniState = &ah->curchan->ani;
359 rssi = BEACON_RSSI(ah);
360 if (rssi > aniState->rssiThrHigh) {
362 } else if (rssi > aniState->rssiThrLow) {
363 if (!aniState->ofdmWeakSigDetect) {
364 if (ath9k_hw_ani_control(ah,
365 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
369 if (aniState->firstepLevel > 0) {
370 if (ath9k_hw_ani_control(ah,
371 ATH9K_ANI_FIRSTEP_LEVEL,
372 aniState->firstepLevel - 1) == 1)
376 if (aniState->firstepLevel > 0) {
377 if (ath9k_hw_ani_control(ah,
378 ATH9K_ANI_FIRSTEP_LEVEL,
379 aniState->firstepLevel - 1) == 1)
384 if (aniState->spurImmunityLevel > 0) {
385 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
386 aniState->spurImmunityLevel - 1))
390 if (aniState->noiseImmunityLevel > 0) {
391 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
392 aniState->noiseImmunityLevel - 1);
398 * only lower either OFDM or CCK errors per turn
399 * we lower the other one next time
401 static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
403 struct ar5416AniState *aniState;
405 aniState = &ah->curchan->ani;
407 if (!use_new_ani(ah)) {
408 ath9k_hw_ani_lower_immunity_old(ah);
412 /* lower OFDM noise immunity */
413 if (aniState->ofdmNoiseImmunityLevel > 0 &&
414 (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
415 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
419 /* lower CCK noise immunity */
420 if (aniState->cckNoiseImmunityLevel > 0)
421 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
424 static void ath9k_ani_reset_old(struct ath_hw *ah)
426 struct ar5416AniState *aniState;
431 aniState = &ah->curchan->ani;
433 if (aniState->noiseImmunityLevel != 0)
434 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
435 aniState->noiseImmunityLevel);
436 if (aniState->spurImmunityLevel != 0)
437 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
438 aniState->spurImmunityLevel);
439 if (!aniState->ofdmWeakSigDetect)
440 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
441 aniState->ofdmWeakSigDetect);
442 if (aniState->cckWeakSigThreshold)
443 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
444 aniState->cckWeakSigThreshold);
445 if (aniState->firstepLevel != 0)
446 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
447 aniState->firstepLevel);
449 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
450 ~ATH9K_RX_FILTER_PHYERR);
451 ath9k_ani_restart(ah);
453 ENABLE_REGWRITE_BUFFER(ah);
455 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
456 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
458 REGWRITE_BUFFER_FLUSH(ah);
462 * Restore the ANI parameters in the HAL and reset the statistics.
463 * This routine should be called for every hardware reset and for
464 * every channel change.
466 void ath9k_ani_reset(struct ath_hw *ah, int is_scanning)
468 struct ar5416AniState *aniState = &ah->curchan->ani;
469 struct ath9k_channel *chan = ah->curchan;
474 if (!use_new_ani(ah))
475 return ath9k_ani_reset_old(ah);
477 ah->stats.ast_ani_reset++;
479 /* always allow mode (on/off) to be controlled */
480 ah->ani_function |= ATH9K_ANI_MODE;
484 * If we're scanning or in AP mode, the defaults (ini)
485 * should be in place. For an AP we assume the historical
486 * levels for this channel are probably outdated so start
487 * from defaults instead.
489 if (aniState->ofdmNoiseImmunityLevel !=
490 ATH9K_ANI_OFDM_DEF_LEVEL ||
491 aniState->cckNoiseImmunityLevel !=
492 ATH9K_ANI_CCK_DEF_LEVEL) {
494 "Restore defaults: chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
498 aniState->ofdmNoiseImmunityLevel,
499 aniState->cckNoiseImmunityLevel);
501 ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
502 ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
506 * restore historical levels for this channel
509 "Restore history: chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
513 aniState->ofdmNoiseImmunityLevel,
514 aniState->cckNoiseImmunityLevel);
516 ath9k_hw_set_ofdm_nil(ah,
517 aniState->ofdmNoiseImmunityLevel);
518 ath9k_hw_set_cck_nil(ah,
519 aniState->cckNoiseImmunityLevel);
523 * enable phy counters if hw supports or if not, enable phy
524 * interrupts (so we can count each one)
526 ath9k_ani_restart(ah);
528 ENABLE_REGWRITE_BUFFER(ah);
530 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
531 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
533 REGWRITE_BUFFER_FLUSH(ah);
536 static int ath9k_hw_ani_read_counters(struct ath_hw *ah)
538 struct ath_common *common = ath9k_hw_common(ah);
539 struct ar5416AniState *aniState = &ah->curchan->ani;
542 u32 ofdmPhyErrCnt, cckPhyErrCnt;
543 u32 phyCnt1, phyCnt2;
546 ath_hw_cycle_counters_update(common);
547 listenTime = ath_hw_get_listen_time(common);
549 if (listenTime <= 0) {
550 ah->stats.ast_ani_lneg++;
551 ath9k_ani_restart(ah);
555 if (!use_new_ani(ah)) {
556 ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
557 cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
560 aniState->listenTime += listenTime;
562 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
563 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
565 if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
566 if (phyCnt1 < ofdm_base) {
568 "phyCnt1 0x%x, resetting counter value to 0x%x\n",
570 REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
571 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
572 AR_PHY_ERR_OFDM_TIMING);
574 if (phyCnt2 < cck_base) {
576 "phyCnt2 0x%x, resetting counter value to 0x%x\n",
578 REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
579 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
580 AR_PHY_ERR_CCK_TIMING);
585 ofdmPhyErrCnt = phyCnt1 - ofdm_base;
586 ah->stats.ast_ani_ofdmerrs +=
587 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
588 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
590 cckPhyErrCnt = phyCnt2 - cck_base;
591 ah->stats.ast_ani_cckerrs +=
592 cckPhyErrCnt - aniState->cckPhyErrCount;
593 aniState->cckPhyErrCount = cckPhyErrCnt;
597 void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan __unused)
599 struct ar5416AniState *aniState;
600 u32 ofdmPhyErrRate, cckPhyErrRate;
605 aniState = &ah->curchan->ani;
609 if (!ath9k_hw_ani_read_counters(ah))
612 ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
613 aniState->listenTime;
614 cckPhyErrRate = aniState->cckPhyErrCount * 1000 /
615 aniState->listenTime;
618 "listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
619 aniState->listenTime,
620 aniState->ofdmNoiseImmunityLevel,
621 ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
622 cckPhyErrRate, aniState->ofdmsTurn);
624 if (aniState->listenTime > 5 * ah->aniperiod) {
625 if (ofdmPhyErrRate <= ah->config.ofdm_trig_low &&
626 cckPhyErrRate <= ah->config.cck_trig_low) {
627 ath9k_hw_ani_lower_immunity(ah);
628 aniState->ofdmsTurn = !aniState->ofdmsTurn;
630 ath9k_ani_restart(ah);
631 } else if (aniState->listenTime > ah->aniperiod) {
632 /* check to see if need to raise immunity */
633 if (ofdmPhyErrRate > ah->config.ofdm_trig_high &&
634 (cckPhyErrRate <= ah->config.cck_trig_high ||
635 aniState->ofdmsTurn)) {
636 ath9k_hw_ani_ofdm_err_trigger(ah);
637 ath9k_ani_restart(ah);
638 aniState->ofdmsTurn = 0;
639 } else if (cckPhyErrRate > ah->config.cck_trig_high) {
640 ath9k_hw_ani_cck_err_trigger(ah);
641 ath9k_ani_restart(ah);
642 aniState->ofdmsTurn = 1;
647 void ath9k_hw_ani_setup(struct ath_hw *ah)
651 static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
652 static const int coarseHigh[] = { -14, -14, -14, -14, -12 };
653 static const int coarseLow[] = { -64, -64, -64, -64, -70 };
654 static const int firpwr[] = { -78, -78, -78, -78, -80 };
656 for (i = 0; i < 5; i++) {
657 ah->totalSizeDesired[i] = totalSizeDesired[i];
658 ah->coarse_high[i] = coarseHigh[i];
659 ah->coarse_low[i] = coarseLow[i];
660 ah->firpwr[i] = firpwr[i];
664 void ath9k_hw_ani_init(struct ath_hw *ah)
668 DBG2("ath9k: Initialize ANI\n");
670 if (use_new_ani(ah)) {
671 ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
672 ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
674 ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
675 ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
677 ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
678 ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
680 ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
681 ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
684 for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
685 struct ath9k_channel *chan = &ah->channels[i];
686 struct ar5416AniState *ani = &chan->ani;
688 if (use_new_ani(ah)) {
689 ani->spurImmunityLevel =
690 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
692 ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
694 if (AR_SREV_9300_20_OR_LATER(ah))
696 !ATH9K_ANI_ENABLE_MRC_CCK;
702 ani->spurImmunityLevel =
703 ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
704 ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
706 ani->cckWeakSigThreshold =
707 ATH9K_ANI_CCK_WEAK_SIG_THR;
710 ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
711 ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
712 ani->ofdmWeakSigDetect =
713 ATH9K_ANI_USE_OFDM_WEAK_SIG;
714 ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
718 * since we expect some ongoing maintenance on the tables, let's sanity
719 * check here default level should not modify INI setting.
721 if (use_new_ani(ah)) {
722 ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
723 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
725 ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
726 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
729 if (ah->config.enable_ani)
730 ah->proc_phyerr |= HAL_PROCESS_ANI;
732 ath9k_ani_restart(ah);