aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2010-06-12 00:33:45 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-14 15:39:29 -0400
commite36b27aff1b10c81c53990b28da4ab6ab0ed0761 (patch)
treefa2642ea274398ccaac4b9e03efecc766030409b
parent40346b66799b7d382e61bbb68a6b6bbdd20f320e (diff)
ath9k: add new ANI implementation for AR9003
This adds support for ANI for AR9003. The implementation for ANI for AR9003 is slightly different than the one used for the older chipset families. It can technically be used for the older families as well but this is not yet fully tested so we only enable the new ANI for the AR5008, AR9001 and AR9002 families with a module parameter, force_new_ani. The old ANI implementation is left intact. Details of the new ANI implemention: * ANI adjustment logic is now table driven so that each ANI level setting is parameterized. This makes adjustments much more deterministic than the old procedure based logic and allows adjustments to be made incrementally to several parameters per level. * ANI register settings are now relative to INI values; so ANI param zero level == INI value. Appropriate floor and ceiling values are obeyed when adjustments are combined with INI values. * ANI processing is done once per second rather that every 100ms. The poll interval is now a set upon hardware initialization and can be picked up by the core driver. * OFDM error and CCK error processing are made in a round robin fashion rather than allowing all OFDM adjustments to be made before CCK adjustments. * ANI adjusts MRC CCK off in the presence of high CCK errors * When adjusting spur immunity (SI) and OFDM weak signal detection, ANI now sets register values for the extension channel too * When adjusting FIR step (ST), ANI now sets register for FIR step low too * FIR step adjustments now allow for an extra level of immunity for extremely noisy environments * The old Noise immunity setting (NI), which changes coarse low, size desired, etc have been removed. Changing these settings could affect up RIFS RX as well. * CCK weak signal adjustment is no longer used * ANI no longer enables phy error interrupts; in all cases phy hw counting registers are used instead * The phy error count (overflow) interrupts are also no longer used for ANI adjustments. All ANI adjustments are made via the polling routine and no adjustments are possible in the ISR context anymore * A history settings buffer is now correctly used for each channel; channel settings are initialized with the defaults but later changes are restored when returning back to that channel * When scanning, ANI is disabled settings are returned to (INI) defaults. * OFDM phy error thresholds are now 400 & 1000 (errors/second units) for low/high water marks, providing increased stability/hysteresis when changing levels. * Similarly CCK phy error thresholds are now 300 & 600 (errors/second) Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c676
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h74
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c361
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c385
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c10
10 files changed, 1390 insertions, 151 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index f5b971973d31..cc648b6ae31c 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc. 2 * Copyright (c) 2008-2010 Atheros Communications Inc.
3 * 3 *
4 * Permission to use, copy, modify, and/or distribute this software for any 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 5 * purpose with or without fee is hereby granted, provided that the above
@@ -17,14 +17,99 @@
17#include "hw.h" 17#include "hw.h"
18#include "hw-ops.h" 18#include "hw-ops.h"
19 19
20struct ani_ofdm_level_entry {
21 int spur_immunity_level;
22 int fir_step_level;
23 int ofdm_weak_signal_on;
24};
25
26/* values here are relative to the INI */
27
28/*
29 * Legend:
30 *
31 * SI: Spur immunity
32 * FS: FIR Step
33 * WS: OFDM / CCK Weak Signal detection
34 * MRC-CCK: Maximal Ratio Combining for CCK
35 */
36
37static const struct ani_ofdm_level_entry ofdm_level_table[] = {
38 /* SI FS WS */
39 { 0, 0, 1 }, /* lvl 0 */
40 { 1, 1, 1 }, /* lvl 1 */
41 { 2, 2, 1 }, /* lvl 2 */
42 { 3, 2, 1 }, /* lvl 3 (default) */
43 { 4, 3, 1 }, /* lvl 4 */
44 { 5, 4, 1 }, /* lvl 5 */
45 { 6, 5, 1 }, /* lvl 6 */
46 { 7, 6, 1 }, /* lvl 7 */
47 { 7, 7, 1 }, /* lvl 8 */
48 { 7, 8, 0 } /* lvl 9 */
49};
50#define ATH9K_ANI_OFDM_NUM_LEVEL \
51 (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0]))
52#define ATH9K_ANI_OFDM_MAX_LEVEL \
53 (ATH9K_ANI_OFDM_NUM_LEVEL-1)
54#define ATH9K_ANI_OFDM_DEF_LEVEL \
55 3 /* default level - matches the INI settings */
56
57/*
58 * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
59 * With OFDM for single stream you just add up all antenna inputs, you're
60 * only interested in what you get after FFT. Signal aligment is also not
61 * required for OFDM because any phase difference adds up in the frequency
62 * domain.
63 *
64 * MRC requires extra work for use with CCK. You need to align the antenna
65 * signals from the different antenna before you can add the signals together.
66 * You need aligment of signals as CCK is in time domain, so addition can cancel
67 * your signal completely if phase is 180 degrees (think of adding sine waves).
68 * You also need to remove noise before the addition and this is where ANI
69 * MRC CCK comes into play. One of the antenna inputs may be stronger but
70 * lower SNR, so just adding after alignment can be dangerous.
71 *
72 * Regardless of alignment in time, the antenna signals add constructively after
73 * FFT and improve your reception. For more information:
74 *
75 * http://en.wikipedia.org/wiki/Maximal-ratio_combining
76 */
77
78struct ani_cck_level_entry {
79 int fir_step_level;
80 int mrc_cck_on;
81};
82
83static const struct ani_cck_level_entry cck_level_table[] = {
84 /* FS MRC-CCK */
85 { 0, 1 }, /* lvl 0 */
86 { 1, 1 }, /* lvl 1 */
87 { 2, 1 }, /* lvl 2 (default) */
88 { 3, 1 }, /* lvl 3 */
89 { 4, 0 }, /* lvl 4 */
90 { 5, 0 }, /* lvl 5 */
91 { 6, 0 }, /* lvl 6 */
92 { 7, 0 }, /* lvl 7 (only for high rssi) */
93 { 8, 0 } /* lvl 8 (only for high rssi) */
94};
95
96#define ATH9K_ANI_CCK_NUM_LEVEL \
97 (sizeof(cck_level_table)/sizeof(cck_level_table[0]))
98#define ATH9K_ANI_CCK_MAX_LEVEL \
99 (ATH9K_ANI_CCK_NUM_LEVEL-1)
100#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
101 (ATH9K_ANI_CCK_NUM_LEVEL-3)
102#define ATH9K_ANI_CCK_DEF_LEVEL \
103 2 /* default level - matches the INI settings */
104
20/* Private to ani.c */ 105/* Private to ani.c */
21static inline void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) 106static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
22{ 107{
23 ath9k_hw_private_ops(ah)->ani_lower_immunity(ah); 108 ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
24} 109}
25 110
26static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, 111int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
27 struct ath9k_channel *chan) 112 struct ath9k_channel *chan)
28{ 113{
29 int i; 114 int i;
30 115
@@ -54,7 +139,7 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah,
54 stats->beacons += REG_READ(ah, AR_BEACON_CNT); 139 stats->beacons += REG_READ(ah, AR_BEACON_CNT);
55} 140}
56 141
57static void ath9k_ani_restart(struct ath_hw *ah) 142static void ath9k_ani_restart_old(struct ath_hw *ah)
58{ 143{
59 struct ar5416AniState *aniState; 144 struct ar5416AniState *aniState;
60 struct ath_common *common = ath9k_hw_common(ah); 145 struct ath_common *common = ath9k_hw_common(ah);
@@ -102,7 +187,42 @@ static void ath9k_ani_restart(struct ath_hw *ah)
102 aniState->cckPhyErrCount = 0; 187 aniState->cckPhyErrCount = 0;
103} 188}
104 189
105static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) 190static void ath9k_ani_restart_new(struct ath_hw *ah)
191{
192 struct ar5416AniState *aniState;
193 struct ath_common *common = ath9k_hw_common(ah);
194
195 if (!DO_ANI(ah))
196 return;
197
198 aniState = ah->curani;
199 aniState->listenTime = 0;
200
201 aniState->ofdmPhyErrBase = 0;
202 aniState->cckPhyErrBase = 0;
203
204 ath_print(common, ATH_DBG_ANI,
205 "Writing ofdmbase=%08x cckbase=%08x\n",
206 aniState->ofdmPhyErrBase,
207 aniState->cckPhyErrBase);
208
209 ENABLE_REGWRITE_BUFFER(ah);
210
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);
215
216 REGWRITE_BUFFER_FLUSH(ah);
217 DISABLE_REGWRITE_BUFFER(ah);
218
219 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
220
221 aniState->ofdmPhyErrCount = 0;
222 aniState->cckPhyErrCount = 0;
223}
224
225static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
106{ 226{
107 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 227 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
108 struct ar5416AniState *aniState; 228 struct ar5416AniState *aniState;
@@ -174,7 +294,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
174 } 294 }
175} 295}
176 296
177static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) 297static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
178{ 298{
179 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 299 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
180 struct ar5416AniState *aniState; 300 struct ar5416AniState *aniState;
@@ -212,6 +332,124 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
212 } 332 }
213} 333}
214 334
335/* Adjust the OFDM Noise Immunity Level */
336static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
337{
338 struct ar5416AniState *aniState = ah->curani;
339 struct ath_common *common = ath9k_hw_common(ah);
340 const struct ani_ofdm_level_entry *entry_ofdm;
341 const struct ani_cck_level_entry *entry_cck;
342
343 aniState->noiseFloor = BEACON_RSSI(ah);
344
345 ath_print(common, ATH_DBG_ANI,
346 "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
347 aniState->ofdmNoiseImmunityLevel,
348 immunityLevel, aniState->noiseFloor,
349 aniState->rssiThrLow, aniState->rssiThrHigh);
350
351 aniState->ofdmNoiseImmunityLevel = immunityLevel;
352
353 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
354 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
355
356 if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
357 ath9k_hw_ani_control(ah,
358 ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
359 entry_ofdm->spur_immunity_level);
360
361 if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
362 entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
363 ath9k_hw_ani_control(ah,
364 ATH9K_ANI_FIRSTEP_LEVEL,
365 entry_ofdm->fir_step_level);
366
367 if ((ah->opmode != NL80211_IFTYPE_STATION &&
368 ah->opmode != NL80211_IFTYPE_ADHOC) ||
369 aniState->noiseFloor <= aniState->rssiThrHigh) {
370 if (aniState->ofdmWeakSigDetectOff)
371 /* force on ofdm weak sig detect */
372 ath9k_hw_ani_control(ah,
373 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
374 true);
375 else if (aniState->ofdmWeakSigDetectOff ==
376 entry_ofdm->ofdm_weak_signal_on)
377 ath9k_hw_ani_control(ah,
378 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
379 entry_ofdm->ofdm_weak_signal_on);
380 }
381}
382
383static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
384{
385 struct ar5416AniState *aniState;
386
387 if (!DO_ANI(ah))
388 return;
389
390 aniState = ah->curani;
391
392 if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
393 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
394}
395
396/*
397 * Set the ANI settings to match an CCK level.
398 */
399static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
400{
401 struct ar5416AniState *aniState = ah->curani;
402 struct ath_common *common = ath9k_hw_common(ah);
403 const struct ani_ofdm_level_entry *entry_ofdm;
404 const struct ani_cck_level_entry *entry_cck;
405
406 aniState->noiseFloor = BEACON_RSSI(ah);
407 ath_print(common, ATH_DBG_ANI,
408 "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
409 aniState->cckNoiseImmunityLevel, immunityLevel,
410 aniState->noiseFloor, aniState->rssiThrLow,
411 aniState->rssiThrHigh);
412
413 if ((ah->opmode == NL80211_IFTYPE_STATION ||
414 ah->opmode == NL80211_IFTYPE_ADHOC) &&
415 aniState->noiseFloor <= aniState->rssiThrLow &&
416 immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
417 immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
418
419 aniState->cckNoiseImmunityLevel = immunityLevel;
420
421 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
422 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
423
424 if (aniState->firstepLevel != entry_cck->fir_step_level &&
425 entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
426 ath9k_hw_ani_control(ah,
427 ATH9K_ANI_FIRSTEP_LEVEL,
428 entry_cck->fir_step_level);
429
430 /* Skip MRC CCK for pre AR9003 families */
431 if (!AR_SREV_9300_20_OR_LATER(ah))
432 return;
433
434 if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
435 ath9k_hw_ani_control(ah,
436 ATH9K_ANI_MRC_CCK,
437 entry_cck->mrc_cck_on);
438}
439
440static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
441{
442 struct ar5416AniState *aniState;
443
444 if (!DO_ANI(ah))
445 return;
446
447 aniState = ah->curani;
448
449 if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
450 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
451}
452
215static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) 453static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
216{ 454{
217 struct ar5416AniState *aniState; 455 struct ar5416AniState *aniState;
@@ -265,6 +503,28 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
265 } 503 }
266} 504}
267 505
506/*
507 * only lower either OFDM or CCK errors per turn
508 * we lower the other one next time
509 */
510static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
511{
512 struct ar5416AniState *aniState;
513
514 aniState = ah->curani;
515
516 /* lower OFDM noise immunity */
517 if (aniState->ofdmNoiseImmunityLevel > 0 &&
518 (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
519 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
520 return;
521 }
522
523 /* lower CCK noise immunity */
524 if (aniState->cckNoiseImmunityLevel > 0)
525 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
526}
527
268static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) 528static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
269{ 529{
270 struct ath9k_channel *chan = ah->curchan; 530 struct ath9k_channel *chan = ah->curchan;
@@ -289,6 +549,7 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
289static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) 549static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
290{ 550{
291 struct ar5416AniState *aniState; 551 struct ar5416AniState *aniState;
552 struct ath_common *common = ath9k_hw_common(ah);
292 u32 txFrameCount, rxFrameCount, cycleCount; 553 u32 txFrameCount, rxFrameCount, cycleCount;
293 int32_t listenTime; 554 int32_t listenTime;
294 555
@@ -298,14 +559,16 @@ static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
298 559
299 aniState = ah->curani; 560 aniState = ah->curani;
300 if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { 561 if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
301
302 listenTime = 0; 562 listenTime = 0;
303 ah->stats.ast_ani_lzero++; 563 ah->stats.ast_ani_lzero++;
564 ath_print(common, ATH_DBG_ANI,
565 "1st call: aniState->cycleCount=%d\n",
566 aniState->cycleCount);
304 } else { 567 } else {
305 int32_t ccdelta = cycleCount - aniState->cycleCount; 568 int32_t ccdelta = cycleCount - aniState->cycleCount;
306 int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; 569 int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
307 int32_t tfdelta = txFrameCount - aniState->txFrameCount; 570 int32_t tfdelta = txFrameCount - aniState->txFrameCount;
308 int32_t clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; 571 int32_t clock_rate;
309 572
310 /* 573 /*
311 * convert HW counter values to ms using mode 574 * convert HW counter values to ms using mode
@@ -314,7 +577,13 @@ static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
314 clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; 577 clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;;
315 578
316 listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate; 579 listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate;
580
581 ath_print(common, ATH_DBG_ANI,
582 "cyclecount=%d, rfcount=%d, "
583 "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n",
584 ccdelta, rfdelta, tfdelta, listenTime, clock_rate);
317 } 585 }
586
318 aniState->cycleCount = cycleCount; 587 aniState->cycleCount = cycleCount;
319 aniState->txFrameCount = txFrameCount; 588 aniState->txFrameCount = txFrameCount;
320 aniState->rxFrameCount = rxFrameCount; 589 aniState->rxFrameCount = rxFrameCount;
@@ -375,7 +644,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
375 ah->curani->cckTrigLow = 644 ah->curani->cckTrigLow =
376 ah->config.cck_trig_low; 645 ah->config.cck_trig_low;
377 } 646 }
378 ath9k_ani_restart(ah); 647 ath9k_ani_restart_old(ah);
379 return; 648 return;
380 } 649 }
381 650
@@ -397,7 +666,101 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
397 666
398 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & 667 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
399 ~ATH9K_RX_FILTER_PHYERR); 668 ~ATH9K_RX_FILTER_PHYERR);
400 ath9k_ani_restart(ah); 669 ath9k_ani_restart_old(ah);
670
671 ENABLE_REGWRITE_BUFFER(ah);
672
673 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
674 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
675
676 REGWRITE_BUFFER_FLUSH(ah);
677 DISABLE_REGWRITE_BUFFER(ah);
678}
679
680/*
681 * Restore the ANI parameters in the HAL and reset the statistics.
682 * This routine should be called for every hardware reset and for
683 * every channel change.
684 */
685static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
686{
687 struct ar5416AniState *aniState = ah->curani;
688 struct ath9k_channel *chan = ah->curchan;
689 struct ath_common *common = ath9k_hw_common(ah);
690
691 if (!DO_ANI(ah))
692 return;
693
694 BUG_ON(aniState == NULL);
695 ah->stats.ast_ani_reset++;
696
697 /* only allow a subset of functions in AP mode */
698 if (ah->opmode == NL80211_IFTYPE_AP) {
699 if (IS_CHAN_2GHZ(chan)) {
700 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
701 ATH9K_ANI_FIRSTEP_LEVEL);
702 if (AR_SREV_9300_20_OR_LATER(ah))
703 ah->ani_function |= ATH9K_ANI_MRC_CCK;
704 } else
705 ah->ani_function = 0;
706 }
707
708 /* always allow mode (on/off) to be controlled */
709 ah->ani_function |= ATH9K_ANI_MODE;
710
711 if (is_scanning ||
712 (ah->opmode != NL80211_IFTYPE_STATION &&
713 ah->opmode != NL80211_IFTYPE_ADHOC)) {
714 /*
715 * If we're scanning or in AP mode, the defaults (ini)
716 * should be in place. For an AP we assume the historical
717 * levels for this channel are probably outdated so start
718 * from defaults instead.
719 */
720 if (aniState->ofdmNoiseImmunityLevel !=
721 ATH9K_ANI_OFDM_DEF_LEVEL ||
722 aniState->cckNoiseImmunityLevel !=
723 ATH9K_ANI_CCK_DEF_LEVEL) {
724 ath_print(common, ATH_DBG_ANI,
725 "Restore defaults: opmode %u "
726 "chan %d Mhz/0x%x is_scanning=%d "
727 "ofdm:%d cck:%d\n",
728 ah->opmode,
729 chan->channel,
730 chan->channelFlags,
731 is_scanning,
732 aniState->ofdmNoiseImmunityLevel,
733 aniState->cckNoiseImmunityLevel);
734
735 ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
736 ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
737 }
738 } else {
739 /*
740 * restore historical levels for this channel
741 */
742 ath_print(common, ATH_DBG_ANI,
743 "Restore history: opmode %u "
744 "chan %d Mhz/0x%x is_scanning=%d "
745 "ofdm:%d cck:%d\n",
746 ah->opmode,
747 chan->channel,
748 chan->channelFlags,
749 is_scanning,
750 aniState->ofdmNoiseImmunityLevel,
751 aniState->cckNoiseImmunityLevel);
752
753 ath9k_hw_set_ofdm_nil(ah,
754 aniState->ofdmNoiseImmunityLevel);
755 ath9k_hw_set_cck_nil(ah,
756 aniState->cckNoiseImmunityLevel);
757 }
758
759 /*
760 * enable phy counters if hw supports or if not, enable phy
761 * interrupts (so we can count each one)
762 */
763 ath9k_ani_restart_new(ah);
401 764
402 ENABLE_REGWRITE_BUFFER(ah); 765 ENABLE_REGWRITE_BUFFER(ah);
403 766
@@ -425,7 +788,7 @@ static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
425 listenTime = ath9k_hw_ani_get_listen_time(ah); 788 listenTime = ath9k_hw_ani_get_listen_time(ah);
426 if (listenTime < 0) { 789 if (listenTime < 0) {
427 ah->stats.ast_ani_lneg++; 790 ah->stats.ast_ani_lneg++;
428 ath9k_ani_restart(ah); 791 ath9k_ani_restart_old(ah);
429 return; 792 return;
430 } 793 }
431 794
@@ -479,17 +842,163 @@ static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
479 aniState->cckPhyErrCount <= aniState->listenTime * 842 aniState->cckPhyErrCount <= aniState->listenTime *
480 aniState->cckTrigLow / 1000) 843 aniState->cckTrigLow / 1000)
481 ath9k_hw_ani_lower_immunity(ah); 844 ath9k_hw_ani_lower_immunity(ah);
482 ath9k_ani_restart(ah); 845 ath9k_ani_restart_old(ah);
483 } else if (aniState->listenTime > ah->aniperiod) { 846 } else if (aniState->listenTime > ah->aniperiod) {
484 if (aniState->ofdmPhyErrCount > aniState->listenTime * 847 if (aniState->ofdmPhyErrCount > aniState->listenTime *
485 aniState->ofdmTrigHigh / 1000) { 848 aniState->ofdmTrigHigh / 1000) {
486 ath9k_hw_ani_ofdm_err_trigger(ah); 849 ath9k_hw_ani_ofdm_err_trigger_old(ah);
487 ath9k_ani_restart(ah); 850 ath9k_ani_restart_old(ah);
488 } else if (aniState->cckPhyErrCount > 851 } else if (aniState->cckPhyErrCount >
489 aniState->listenTime * aniState->cckTrigHigh / 852 aniState->listenTime * aniState->cckTrigHigh /
490 1000) { 853 1000) {
491 ath9k_hw_ani_cck_err_trigger(ah); 854 ath9k_hw_ani_cck_err_trigger_old(ah);
492 ath9k_ani_restart(ah); 855 ath9k_ani_restart_old(ah);
856 }
857 }
858}
859
860static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
861 struct ath9k_channel *chan)
862{
863 struct ar5416AniState *aniState;
864 struct ath_common *common = ath9k_hw_common(ah);
865 int32_t listenTime;
866 u32 phyCnt1, phyCnt2;
867 u32 ofdmPhyErrCnt, cckPhyErrCnt;
868 u32 ofdmPhyErrRate, cckPhyErrRate;
869
870 if (!DO_ANI(ah))
871 return;
872
873 aniState = ah->curani;
874 if (WARN_ON(!aniState))
875 return;
876
877 listenTime = ath9k_hw_ani_get_listen_time(ah);
878 if (listenTime <= 0) {
879 ah->stats.ast_ani_lneg++;
880 /* restart ANI period if listenTime is invalid */
881 ath_print(common, ATH_DBG_ANI,
882 "listenTime=%d - on new ani monitor\n",
883 listenTime);
884 ath9k_ani_restart_new(ah);
885 return;
886 }
887
888 aniState->listenTime += listenTime;
889
890 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
891
892 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
893 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
894
895 if (phyCnt1 < aniState->ofdmPhyErrBase ||
896 phyCnt2 < aniState->cckPhyErrBase) {
897 if (phyCnt1 < aniState->ofdmPhyErrBase) {
898 ath_print(common, ATH_DBG_ANI,
899 "phyCnt1 0x%x, resetting "
900 "counter value to 0x%x\n",
901 phyCnt1,
902 aniState->ofdmPhyErrBase);
903 REG_WRITE(ah, AR_PHY_ERR_1,
904 aniState->ofdmPhyErrBase);
905 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
906 AR_PHY_ERR_OFDM_TIMING);
907 }
908 if (phyCnt2 < aniState->cckPhyErrBase) {
909 ath_print(common, ATH_DBG_ANI,
910 "phyCnt2 0x%x, resetting "
911 "counter value to 0x%x\n",
912 phyCnt2,
913 aniState->cckPhyErrBase);
914 REG_WRITE(ah, AR_PHY_ERR_2,
915 aniState->cckPhyErrBase);
916 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
917 AR_PHY_ERR_CCK_TIMING);
918 }
919 return;
920 }
921
922 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
923 ah->stats.ast_ani_ofdmerrs +=
924 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
925 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
926
927 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
928 ah->stats.ast_ani_cckerrs +=
929 cckPhyErrCnt - aniState->cckPhyErrCount;
930 aniState->cckPhyErrCount = cckPhyErrCnt;
931
932 ath_print(common, ATH_DBG_ANI,
933 "Errors: OFDM=0x%08x-0x%08x=%d "
934 "CCK=0x%08x-0x%08x=%d\n",
935 phyCnt1,
936 aniState->ofdmPhyErrBase,
937 ofdmPhyErrCnt,
938 phyCnt2,
939 aniState->cckPhyErrBase,
940 cckPhyErrCnt);
941
942 ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
943 aniState->listenTime;
944 cckPhyErrRate = aniState->cckPhyErrCount * 1000 /
945 aniState->listenTime;
946
947 ath_print(common, ATH_DBG_ANI,
948 "listenTime=%d OFDM:%d errs=%d/s CCK:%d "
949 "errs=%d/s ofdm_turn=%d\n",
950 listenTime, aniState->ofdmNoiseImmunityLevel,
951 ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
952 cckPhyErrRate, aniState->ofdmsTurn);
953
954 if (aniState->listenTime > 5 * ah->aniperiod) {
955 if (ofdmPhyErrRate <= aniState->ofdmTrigLow &&
956 cckPhyErrRate <= aniState->cckTrigLow) {
957 ath_print(common, ATH_DBG_ANI,
958 "1. listenTime=%d OFDM:%d errs=%d/s(<%d) "
959 "CCK:%d errs=%d/s(<%d) -> "
960 "ath9k_hw_ani_lower_immunity()\n",
961 aniState->listenTime,
962 aniState->ofdmNoiseImmunityLevel,
963 ofdmPhyErrRate,
964 aniState->ofdmTrigLow,
965 aniState->cckNoiseImmunityLevel,
966 cckPhyErrRate,
967 aniState->cckTrigLow);
968 ath9k_hw_ani_lower_immunity(ah);
969 aniState->ofdmsTurn = !aniState->ofdmsTurn;
970 }
971 ath_print(common, ATH_DBG_ANI,
972 "1 listenTime=%d ofdm=%d/s cck=%d/s - "
973 "calling ath9k_ani_restart_new()\n",
974 aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate);
975 ath9k_ani_restart_new(ah);
976 } else if (aniState->listenTime > ah->aniperiod) {
977 /* check to see if need to raise immunity */
978 if (ofdmPhyErrRate > aniState->ofdmTrigHigh &&
979 (cckPhyErrRate <= aniState->cckTrigHigh ||
980 aniState->ofdmsTurn)) {
981 ath_print(common, ATH_DBG_ANI,
982 "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> "
983 "ath9k_hw_ani_ofdm_err_trigger_new()\n",
984 aniState->listenTime,
985 aniState->ofdmNoiseImmunityLevel,
986 ofdmPhyErrRate,
987 aniState->ofdmTrigHigh);
988 ath9k_hw_ani_ofdm_err_trigger_new(ah);
989 ath9k_ani_restart_new(ah);
990 aniState->ofdmsTurn = false;
991 } else if (cckPhyErrRate > aniState->cckTrigHigh) {
992 ath_print(common, ATH_DBG_ANI,
993 "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> "
994 "ath9k_hw_ani_cck_err_trigger_new()\n",
995 aniState->listenTime,
996 aniState->cckNoiseImmunityLevel,
997 cckPhyErrRate,
998 aniState->cckTrigHigh);
999 ath9k_hw_ani_cck_err_trigger_new(ah);
1000 ath9k_ani_restart_new(ah);
1001 aniState->ofdmsTurn = true;
493 } 1002 }
494 } 1003 }
495} 1004}
@@ -626,14 +1135,52 @@ static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
626 * check will never be true. 1135 * check will never be true.
627 */ 1136 */
628 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) 1137 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
629 ath9k_hw_ani_ofdm_err_trigger(ah); 1138 ath9k_hw_ani_ofdm_err_trigger_new(ah);
630 if (aniState->cckPhyErrCount > aniState->cckTrigHigh) 1139 if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
631 ath9k_hw_ani_cck_err_trigger(ah); 1140 ath9k_hw_ani_cck_err_trigger_old(ah);
632 /* NB: always restart to insure the h/w counters are reset */ 1141 /* NB: always restart to insure the h/w counters are reset */
633 ath9k_ani_restart(ah); 1142 ath9k_ani_restart_old(ah);
634 } 1143 }
635} 1144}
636 1145
1146/*
1147 * Process a MIB interrupt. We may potentially be invoked because
1148 * any of the MIB counters overflow/trigger so don't assume we're
1149 * here because a PHY error counter triggered.
1150 */
1151static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
1152{
1153 u32 phyCnt1, phyCnt2;
1154
1155 /* Reset these counters regardless */
1156 REG_WRITE(ah, AR_FILT_OFDM, 0);
1157 REG_WRITE(ah, AR_FILT_CCK, 0);
1158 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
1159 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
1160
1161 /* Clear the mib counters and save them in the stats */
1162 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1163
1164 if (!DO_ANI(ah)) {
1165 /*
1166 * We must always clear the interrupt cause by
1167 * resetting the phy error regs.
1168 */
1169 REG_WRITE(ah, AR_PHY_ERR_1, 0);
1170 REG_WRITE(ah, AR_PHY_ERR_2, 0);
1171 return;
1172 }
1173
1174 /* NB: these are not reset-on-read */
1175 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
1176 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
1177
1178 /* NB: always restart to insure the h/w counters are reset */
1179 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
1180 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK))
1181 ath9k_ani_restart_new(ah);
1182}
1183
637void ath9k_hw_ani_setup(struct ath_hw *ah) 1184void ath9k_hw_ani_setup(struct ath_hw *ah)
638{ 1185{
639 int i; 1186 int i;
@@ -660,22 +1207,70 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
660 1207
661 memset(ah->ani, 0, sizeof(ah->ani)); 1208 memset(ah->ani, 0, sizeof(ah->ani));
662 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { 1209 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
663 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH; 1210 if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
664 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW; 1211 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
665 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH; 1212 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
666 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW; 1213
1214 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
1215 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW;
1216
1217 ah->ani[i].spurImmunityLevel =
1218 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
1219
1220 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
1221
1222 ah->ani[i].ofdmPhyErrBase = 0;
1223 ah->ani[i].cckPhyErrBase = 0;
1224
1225 if (AR_SREV_9300_20_OR_LATER(ah))
1226 ah->ani[i].mrcCCKOff =
1227 !ATH9K_ANI_ENABLE_MRC_CCK;
1228 else
1229 ah->ani[i].mrcCCKOff = true;
1230
1231 ah->ani[i].ofdmsTurn = true;
1232 } else {
1233 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1234 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
1235
1236 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1237 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD;
1238
1239 ah->ani[i].spurImmunityLevel =
1240 ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
1241 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
1242
1243 ah->ani[i].ofdmPhyErrBase =
1244 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1245 ah->ani[i].cckPhyErrBase =
1246 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1247 ah->ani[i].cckWeakSigThreshold =
1248 ATH9K_ANI_CCK_WEAK_SIG_THR;
1249 }
1250
667 ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; 1251 ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
668 ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; 1252 ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
669 ah->ani[i].ofdmWeakSigDetectOff = 1253 ah->ani[i].ofdmWeakSigDetectOff =
670 !ATH9K_ANI_USE_OFDM_WEAK_SIG; 1254 !ATH9K_ANI_USE_OFDM_WEAK_SIG;
671 ah->ani[i].cckWeakSigThreshold = 1255 ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
672 ATH9K_ANI_CCK_WEAK_SIG_THR; 1256 }
673 ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; 1257
674 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; 1258 /*
675 ah->ani[i].ofdmPhyErrBase = 1259 * since we expect some ongoing maintenance on the tables, let's sanity
676 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; 1260 * check here default level should not modify INI setting.
677 ah->ani[i].cckPhyErrBase = 1261 */
678 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; 1262 if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
1263 const struct ani_ofdm_level_entry *entry_ofdm;
1264 const struct ani_cck_level_entry *entry_cck;
1265
1266 entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL];
1267 entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL];
1268
1269 ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
1270 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
1271 } else {
1272 ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
1273 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
679 } 1274 }
680 1275
681 ath_print(common, ATH_DBG_ANI, 1276 ath_print(common, ATH_DBG_ANI,
@@ -694,7 +1289,6 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
694 1289
695 ath9k_enable_mib_counters(ah); 1290 ath9k_enable_mib_counters(ah);
696 1291
697 ah->aniperiod = ATH9K_ANI_PERIOD;
698 if (ah->config.enable_ani) 1292 if (ah->config.enable_ani)
699 ah->proc_phyerr |= HAL_PROCESS_ANI; 1293 ah->proc_phyerr |= HAL_PROCESS_ANI;
700} 1294}
@@ -709,4 +1303,20 @@ void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
709 1303
710 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old; 1304 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
711 ops->ani_monitor = ath9k_hw_ani_monitor_old; 1305 ops->ani_monitor = ath9k_hw_ani_monitor_old;
1306
1307 ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
1308}
1309
1310void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
1311{
1312 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1313 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1314
1315 priv_ops->ani_reset = ath9k_ani_reset_new;
1316 priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
1317
1318 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
1319 ops->ani_monitor = ath9k_hw_ani_monitor_new;
1320
1321 ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");
712} 1322}
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index 4631ab269697..f4d0a4d48b37 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -23,23 +23,55 @@
23 23
24#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) 24#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
25 25
26#define ATH9K_ANI_OFDM_TRIG_HIGH 500 26/* units are errors per second */
27#define ATH9K_ANI_OFDM_TRIG_LOW 200 27#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500
28#define ATH9K_ANI_CCK_TRIG_HIGH 200 28#define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 1000
29#define ATH9K_ANI_CCK_TRIG_LOW 100 29
30/* units are errors per second */
31#define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200
32#define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400
33
34/* units are errors per second */
35#define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200
36#define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600
37
38/* units are errors per second */
39#define ATH9K_ANI_CCK_TRIG_LOW_OLD 100
40#define ATH9K_ANI_CCK_TRIG_LOW_NEW 300
41
30#define ATH9K_ANI_NOISE_IMMUNE_LVL 4 42#define ATH9K_ANI_NOISE_IMMUNE_LVL 4
31#define ATH9K_ANI_USE_OFDM_WEAK_SIG true 43#define ATH9K_ANI_USE_OFDM_WEAK_SIG true
32#define ATH9K_ANI_CCK_WEAK_SIG_THR false 44#define ATH9K_ANI_CCK_WEAK_SIG_THR false
33#define ATH9K_ANI_SPUR_IMMUNE_LVL 7 45
34#define ATH9K_ANI_FIRSTEP_LVL 0 46#define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7
47#define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3
48
49#define ATH9K_ANI_FIRSTEP_LVL_OLD 0
50#define ATH9K_ANI_FIRSTEP_LVL_NEW 2
51
35#define ATH9K_ANI_RSSI_THR_HIGH 40 52#define ATH9K_ANI_RSSI_THR_HIGH 40
36#define ATH9K_ANI_RSSI_THR_LOW 7 53#define ATH9K_ANI_RSSI_THR_LOW 7
37#define ATH9K_ANI_PERIOD 100 54
55#define ATH9K_ANI_PERIOD_OLD 100
56#define ATH9K_ANI_PERIOD_NEW 1000
57
58/* in ms */
59#define ATH9K_ANI_POLLINTERVAL_OLD 100
60#define ATH9K_ANI_POLLINTERVAL_NEW 1000
38 61
39#define HAL_NOISE_IMMUNE_MAX 4 62#define HAL_NOISE_IMMUNE_MAX 4
40#define HAL_SPUR_IMMUNE_MAX 7 63#define HAL_SPUR_IMMUNE_MAX 7
41#define HAL_FIRST_STEP_MAX 2 64#define HAL_FIRST_STEP_MAX 2
42 65
66#define ATH9K_SIG_FIRSTEP_SETTING_MIN 0
67#define ATH9K_SIG_FIRSTEP_SETTING_MAX 20
68#define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0
69#define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22
70
71#define ATH9K_ANI_ENABLE_MRC_CCK true
72
73/* values here are relative to the INI */
74
43enum ath9k_ani_cmd { 75enum ath9k_ani_cmd {
44 ATH9K_ANI_PRESENT = 0x1, 76 ATH9K_ANI_PRESENT = 0x1,
45 ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, 77 ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
@@ -49,7 +81,8 @@ enum ath9k_ani_cmd {
49 ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, 81 ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20,
50 ATH9K_ANI_MODE = 0x40, 82 ATH9K_ANI_MODE = 0x40,
51 ATH9K_ANI_PHYERR_RESET = 0x80, 83 ATH9K_ANI_PHYERR_RESET = 0x80,
52 ATH9K_ANI_ALL = 0xff 84 ATH9K_ANI_MRC_CCK = 0x100,
85 ATH9K_ANI_ALL = 0xfff
53}; 86};
54 87
55struct ath9k_mib_stats { 88struct ath9k_mib_stats {
@@ -60,9 +93,31 @@ struct ath9k_mib_stats {
60 u32 beacons; 93 u32 beacons;
61}; 94};
62 95
96/* INI default values for ANI registers */
97struct ath9k_ani_default {
98 u16 m1ThreshLow;
99 u16 m2ThreshLow;
100 u16 m1Thresh;
101 u16 m2Thresh;
102 u16 m2CountThr;
103 u16 m2CountThrLow;
104 u16 m1ThreshLowExt;
105 u16 m2ThreshLowExt;
106 u16 m1ThreshExt;
107 u16 m2ThreshExt;
108 u16 firstep;
109 u16 firstepLow;
110 u16 cycpwrThr1;
111 u16 cycpwrThr1Ext;
112};
113
63struct ar5416AniState { 114struct ar5416AniState {
64 struct ath9k_channel *c; 115 struct ath9k_channel *c;
65 u8 noiseImmunityLevel; 116 u8 noiseImmunityLevel;
117 u8 ofdmNoiseImmunityLevel;
118 u8 cckNoiseImmunityLevel;
119 bool ofdmsTurn;
120 u8 mrcCCKOff;
66 u8 spurImmunityLevel; 121 u8 spurImmunityLevel;
67 u8 firstepLevel; 122 u8 firstepLevel;
68 u8 ofdmWeakSigDetectOff; 123 u8 ofdmWeakSigDetectOff;
@@ -85,6 +140,7 @@ struct ar5416AniState {
85 int16_t pktRssi[2]; 140 int16_t pktRssi[2];
86 int16_t ofdmErrRssi[2]; 141 int16_t ofdmErrRssi[2];
87 int16_t cckErrRssi[2]; 142 int16_t cckErrRssi[2];
143 struct ath9k_ani_default iniDef;
88}; 144};
89 145
90struct ar5416Stats { 146struct ar5416Stats {
@@ -114,5 +170,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
114 u32 *rxf_pcnt, u32 *txf_pcnt); 170 u32 *rxf_pcnt, u32 *txf_pcnt);
115void ath9k_hw_ani_setup(struct ath_hw *ah); 171void ath9k_hw_ani_setup(struct ath_hw *ah);
116void ath9k_hw_ani_init(struct ath_hw *ah); 172void ath9k_hw_ani_init(struct ath_hw *ah);
173int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
174 struct ath9k_channel *chan);
117 175
118#endif /* ANI_H */ 176#endif /* ANI_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 96018d53f48e..ee34a495b0be 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -19,7 +19,30 @@
19#include "../regd.h" 19#include "../regd.h"
20#include "ar9002_phy.h" 20#include "ar9002_phy.h"
21 21
22/* All code below is for non single-chip solutions */ 22/* All code below is for AR5008, AR9001, AR9002 */
23
24static const int firstep_table[] =
25/* level: 0 1 2 3 4 5 6 7 8 */
26 { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */
27
28static const int cycpwrThr1_table[] =
29/* level: 0 1 2 3 4 5 6 7 8 */
30 { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
31
32/*
33 * register values to turn OFDM weak signal detection OFF
34 */
35static const int m1ThreshLow_off = 127;
36static const int m2ThreshLow_off = 127;
37static const int m1Thresh_off = 127;
38static const int m2Thresh_off = 127;
39static const int m2CountThr_off = 31;
40static const int m2CountThrLow_off = 63;
41static const int m1ThreshLowExt_off = 127;
42static const int m2ThreshLowExt_off = 127;
43static const int m1ThreshExt_off = 127;
44static const int m2ThreshExt_off = 127;
45
23 46
24/** 47/**
25 * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters 48 * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters
@@ -1026,8 +1049,9 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah,
1026 return pll; 1049 return pll;
1027} 1050}
1028 1051
1029static bool ar5008_hw_ani_control(struct ath_hw *ah, 1052static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
1030 enum ath9k_ani_cmd cmd, int param) 1053 enum ath9k_ani_cmd cmd,
1054 int param)
1031{ 1055{
1032 struct ar5416AniState *aniState = ah->curani; 1056 struct ar5416AniState *aniState = ah->curani;
1033 struct ath_common *common = ath9k_hw_common(ah); 1057 struct ath_common *common = ath9k_hw_common(ah);
@@ -1209,6 +1233,265 @@ static bool ar5008_hw_ani_control(struct ath_hw *ah,
1209 return true; 1233 return true;
1210} 1234}
1211 1235
1236static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
1237 enum ath9k_ani_cmd cmd,
1238 int param)
1239{
1240 struct ar5416AniState *aniState = ah->curani;
1241 struct ath_common *common = ath9k_hw_common(ah);
1242 struct ath9k_channel *chan = ah->curchan;
1243 s32 value, value2;
1244
1245 switch (cmd & ah->ani_function) {
1246 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
1247 /*
1248 * on == 1 means ofdm weak signal detection is ON
1249 * on == 1 is the default, for less noise immunity
1250 *
1251 * on == 0 means ofdm weak signal detection is OFF
1252 * on == 0 means more noise imm
1253 */
1254 u32 on = param ? 1 : 0;
1255 /*
1256 * make register setting for default
1257 * (weak sig detect ON) come from INI file
1258 */
1259 int m1ThreshLow = on ?
1260 aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
1261 int m2ThreshLow = on ?
1262 aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
1263 int m1Thresh = on ?
1264 aniState->iniDef.m1Thresh : m1Thresh_off;
1265 int m2Thresh = on ?
1266 aniState->iniDef.m2Thresh : m2Thresh_off;
1267 int m2CountThr = on ?
1268 aniState->iniDef.m2CountThr : m2CountThr_off;
1269 int m2CountThrLow = on ?
1270 aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
1271 int m1ThreshLowExt = on ?
1272 aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
1273 int m2ThreshLowExt = on ?
1274 aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
1275 int m1ThreshExt = on ?
1276 aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
1277 int m2ThreshExt = on ?
1278 aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
1279
1280 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
1281 AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
1282 m1ThreshLow);
1283 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
1284 AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
1285 m2ThreshLow);
1286 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
1287 AR_PHY_SFCORR_M1_THRESH, m1Thresh);
1288 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
1289 AR_PHY_SFCORR_M2_THRESH, m2Thresh);
1290 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
1291 AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
1292 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
1293 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
1294 m2CountThrLow);
1295
1296 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
1297 AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
1298 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
1299 AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
1300 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
1301 AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
1302 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
1303 AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
1304
1305 if (on)
1306 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
1307 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
1308 else
1309 REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
1310 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
1311
1312 if (!on != aniState->ofdmWeakSigDetectOff) {
1313 ath_print(common, ATH_DBG_ANI,
1314 "** ch %d: ofdm weak signal: %s=>%s\n",
1315 chan->channel,
1316 !aniState->ofdmWeakSigDetectOff ?
1317 "on" : "off",
1318 on ? "on" : "off");
1319 if (on)
1320 ah->stats.ast_ani_ofdmon++;
1321 else
1322 ah->stats.ast_ani_ofdmoff++;
1323 aniState->ofdmWeakSigDetectOff = !on;
1324 }
1325 break;
1326 }
1327 case ATH9K_ANI_FIRSTEP_LEVEL:{
1328 u32 level = param;
1329
1330 if (level >= ARRAY_SIZE(firstep_table)) {
1331 ath_print(common, ATH_DBG_ANI,
1332 "ATH9K_ANI_FIRSTEP_LEVEL: level "
1333 "out of range (%u > %u)\n",
1334 level,
1335 (unsigned) ARRAY_SIZE(firstep_table));
1336 return false;
1337 }
1338
1339 /*
1340 * make register setting relative to default
1341 * from INI file & cap value
1342 */
1343 value = firstep_table[level] -
1344 firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
1345 aniState->iniDef.firstep;
1346 if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
1347 value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
1348 if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
1349 value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
1350 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
1351 AR_PHY_FIND_SIG_FIRSTEP,
1352 value);
1353 /*
1354 * we need to set first step low register too
1355 * make register setting relative to default
1356 * from INI file & cap value
1357 */
1358 value2 = firstep_table[level] -
1359 firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
1360 aniState->iniDef.firstepLow;
1361 if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
1362 value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
1363 if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
1364 value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
1365
1366 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
1367 AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
1368
1369 if (level != aniState->firstepLevel) {
1370 ath_print(common, ATH_DBG_ANI,
1371 "** ch %d: level %d=>%d[def:%d] "
1372 "firstep[level]=%d ini=%d\n",
1373 chan->channel,
1374 aniState->firstepLevel,
1375 level,
1376 ATH9K_ANI_FIRSTEP_LVL_NEW,
1377 value,
1378 aniState->iniDef.firstep);
1379 ath_print(common, ATH_DBG_ANI,
1380 "** ch %d: level %d=>%d[def:%d] "
1381 "firstep_low[level]=%d ini=%d\n",
1382 chan->channel,
1383 aniState->firstepLevel,
1384 level,
1385 ATH9K_ANI_FIRSTEP_LVL_NEW,
1386 value2,
1387 aniState->iniDef.firstepLow);
1388 if (level > aniState->firstepLevel)
1389 ah->stats.ast_ani_stepup++;
1390 else if (level < aniState->firstepLevel)
1391 ah->stats.ast_ani_stepdown++;
1392 aniState->firstepLevel = level;
1393 }
1394 break;
1395 }
1396 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
1397 u32 level = param;
1398
1399 if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
1400 ath_print(common, ATH_DBG_ANI,
1401 "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level "
1402 "out of range (%u > %u)\n",
1403 level,
1404 (unsigned) ARRAY_SIZE(cycpwrThr1_table));
1405 return false;
1406 }
1407 /*
1408 * make register setting relative to default
1409 * from INI file & cap value
1410 */
1411 value = cycpwrThr1_table[level] -
1412 cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
1413 aniState->iniDef.cycpwrThr1;
1414 if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
1415 value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
1416 if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
1417 value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
1418 REG_RMW_FIELD(ah, AR_PHY_TIMING5,
1419 AR_PHY_TIMING5_CYCPWR_THR1,
1420 value);
1421
1422 /*
1423 * set AR_PHY_EXT_CCA for extension channel
1424 * make register setting relative to default
1425 * from INI file & cap value
1426 */
1427 value2 = cycpwrThr1_table[level] -
1428 cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
1429 aniState->iniDef.cycpwrThr1Ext;
1430 if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
1431 value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
1432 if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
1433 value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
1434 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
1435 AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2);
1436
1437 if (level != aniState->spurImmunityLevel) {
1438 ath_print(common, ATH_DBG_ANI,
1439 "** ch %d: level %d=>%d[def:%d] "
1440 "cycpwrThr1[level]=%d ini=%d\n",
1441 chan->channel,
1442 aniState->spurImmunityLevel,
1443 level,
1444 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
1445 value,
1446 aniState->iniDef.cycpwrThr1);
1447 ath_print(common, ATH_DBG_ANI,
1448 "** ch %d: level %d=>%d[def:%d] "
1449 "cycpwrThr1Ext[level]=%d ini=%d\n",
1450 chan->channel,
1451 aniState->spurImmunityLevel,
1452 level,
1453 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
1454 value2,
1455 aniState->iniDef.cycpwrThr1Ext);
1456 if (level > aniState->spurImmunityLevel)
1457 ah->stats.ast_ani_spurup++;
1458 else if (level < aniState->spurImmunityLevel)
1459 ah->stats.ast_ani_spurdown++;
1460 aniState->spurImmunityLevel = level;
1461 }
1462 break;
1463 }
1464 case ATH9K_ANI_MRC_CCK:
1465 /*
1466 * You should not see this as AR5008, AR9001, AR9002
1467 * does not have hardware support for MRC CCK.
1468 */
1469 WARN_ON(1);
1470 break;
1471 case ATH9K_ANI_PRESENT:
1472 break;
1473 default:
1474 ath_print(common, ATH_DBG_ANI,
1475 "invalid cmd %u\n", cmd);
1476 return false;
1477 }
1478
1479 ath_print(common, ATH_DBG_ANI,
1480 "ANI parameters: SI=%d, ofdmWS=%s FS=%d "
1481 "MRCcck=%s listenTime=%d CC=%d listen=%d "
1482 "ofdmErrs=%d cckErrs=%d\n",
1483 aniState->spurImmunityLevel,
1484 !aniState->ofdmWeakSigDetectOff ? "on" : "off",
1485 aniState->firstepLevel,
1486 !aniState->mrcCCKOff ? "on" : "off",
1487 aniState->listenTime,
1488 aniState->cycleCount,
1489 aniState->listenTime,
1490 aniState->ofdmPhyErrCount,
1491 aniState->cckPhyErrCount);
1492 return true;
1493}
1494
1212static void ar5008_hw_do_getnf(struct ath_hw *ah, 1495static void ar5008_hw_do_getnf(struct ath_hw *ah,
1213 int16_t nfarray[NUM_NF_READINGS]) 1496 int16_t nfarray[NUM_NF_READINGS])
1214{ 1497{
@@ -1329,6 +1612,71 @@ static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
1329 DISABLE_REGWRITE_BUFFER(ah); 1612 DISABLE_REGWRITE_BUFFER(ah);
1330} 1613}
1331 1614
1615/*
1616 * Initialize the ANI register values with default (ini) values.
1617 * This routine is called during a (full) hardware reset after
1618 * all the registers are initialised from the INI.
1619 */
1620static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
1621{
1622 struct ar5416AniState *aniState;
1623 struct ath_common *common = ath9k_hw_common(ah);
1624 struct ath9k_channel *chan = ah->curchan;
1625 struct ath9k_ani_default *iniDef;
1626 int index;
1627 u32 val;
1628
1629 index = ath9k_hw_get_ani_channel_idx(ah, chan);
1630 aniState = &ah->ani[index];
1631 ah->curani = aniState;
1632 iniDef = &aniState->iniDef;
1633
1634 ath_print(common, ATH_DBG_ANI,
1635 "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
1636 ah->hw_version.macVersion,
1637 ah->hw_version.macRev,
1638 ah->opmode,
1639 chan->channel,
1640 chan->channelFlags);
1641
1642 val = REG_READ(ah, AR_PHY_SFCORR);
1643 iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
1644 iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);
1645 iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);
1646
1647 val = REG_READ(ah, AR_PHY_SFCORR_LOW);
1648 iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
1649 iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
1650 iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
1651
1652 val = REG_READ(ah, AR_PHY_SFCORR_EXT);
1653 iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);
1654 iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);
1655 iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);
1656 iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);
1657 iniDef->firstep = REG_READ_FIELD(ah,
1658 AR_PHY_FIND_SIG,
1659 AR_PHY_FIND_SIG_FIRSTEP);
1660 iniDef->firstepLow = REG_READ_FIELD(ah,
1661 AR_PHY_FIND_SIG_LOW,
1662 AR_PHY_FIND_SIG_FIRSTEP_LOW);
1663 iniDef->cycpwrThr1 = REG_READ_FIELD(ah,
1664 AR_PHY_TIMING5,
1665 AR_PHY_TIMING5_CYCPWR_THR1);
1666 iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah,
1667 AR_PHY_EXT_CCA,
1668 AR_PHY_EXT_TIMING5_CYCPWR_THR1);
1669
1670 /* these levels just got reset to defaults by the INI */
1671 aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
1672 aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
1673 aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
1674 aniState->mrcCCKOff = true; /* not available on pre AR9003 */
1675
1676 aniState->cycleCount = 0;
1677}
1678
1679
1332void ar5008_hw_attach_phy_ops(struct ath_hw *ah) 1680void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
1333{ 1681{
1334 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 1682 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -1350,10 +1698,15 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
1350 priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; 1698 priv_ops->enable_rfkill = ar5008_hw_enable_rfkill;
1351 priv_ops->restore_chainmask = ar5008_restore_chainmask; 1699 priv_ops->restore_chainmask = ar5008_restore_chainmask;
1352 priv_ops->set_diversity = ar5008_set_diversity; 1700 priv_ops->set_diversity = ar5008_set_diversity;
1353 priv_ops->ani_control = ar5008_hw_ani_control;
1354 priv_ops->do_getnf = ar5008_hw_do_getnf; 1701 priv_ops->do_getnf = ar5008_hw_do_getnf;
1355 priv_ops->loadnf = ar5008_hw_loadnf; 1702 priv_ops->loadnf = ar5008_hw_loadnf;
1356 1703
1704 if (modparam_force_new_ani) {
1705 priv_ops->ani_control = ar5008_hw_ani_control_new;
1706 priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs;
1707 } else
1708 priv_ops->ani_control = ar5008_hw_ani_control_old;
1709
1357 if (AR_SREV_9100(ah)) 1710 if (AR_SREV_9100(ah))
1358 priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; 1711 priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
1359 else if (AR_SREV_9160_10_OR_LATER(ah)) 1712 else if (AR_SREV_9160_10_OR_LATER(ah))
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 917eae02acda..0317ac9fc1b7 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -20,6 +20,10 @@
20#include "ar9002_initvals.h" 20#include "ar9002_initvals.h"
21#include "ar9002_phy.h" 21#include "ar9002_phy.h"
22 22
23int modparam_force_new_ani;
24module_param_named(force_new_ani, modparam_force_new_ani, int, 0444);
25MODULE_PARM_DESC(nohwcrypt, "Force new ANI for AR5008, AR9001, AR9002");
26
23/* General hardware code for the A5008/AR9001/AR9002 hadware families */ 27/* General hardware code for the A5008/AR9001/AR9002 hadware families */
24 28
25static bool ar9002_hw_macversion_supported(u32 macversion) 29static bool ar9002_hw_macversion_supported(u32 macversion)
@@ -637,5 +641,8 @@ void ar9002_hw_attach_ops(struct ath_hw *ah)
637 ar9002_hw_attach_calib_ops(ah); 641 ar9002_hw_attach_calib_ops(ah);
638 ar9002_hw_attach_mac_ops(ah); 642 ar9002_hw_attach_mac_ops(ah);
639 643
640 ath9k_hw_attach_ani_ops_old(ah); 644 if (modparam_force_new_ani)
645 ath9k_hw_attach_ani_ops_new(ah);
646 else
647 ath9k_hw_attach_ani_ops_old(ah);
641} 648}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index b7574704f677..82c3ab756cd0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -314,5 +314,5 @@ void ar9003_hw_attach_ops(struct ath_hw *ah)
314 ar9003_hw_attach_calib_ops(ah); 314 ar9003_hw_attach_calib_ops(ah);
315 ar9003_hw_attach_mac_ops(ah); 315 ar9003_hw_attach_mac_ops(ah);
316 316
317 ath9k_hw_attach_ani_ops_old(ah); 317 ath9k_hw_attach_ani_ops_new(ah);
318} 318}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index c714579b5483..bababbe1edea 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -17,6 +17,28 @@
17#include "hw.h" 17#include "hw.h"
18#include "ar9003_phy.h" 18#include "ar9003_phy.h"
19 19
20static const int firstep_table[] =
21/* level: 0 1 2 3 4 5 6 7 8 */
22 { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */
23
24static const int cycpwrThr1_table[] =
25/* level: 0 1 2 3 4 5 6 7 8 */
26 { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
27
28/*
29 * register values to turn OFDM weak signal detection OFF
30 */
31static const int m1ThreshLow_off = 127;
32static const int m2ThreshLow_off = 127;
33static const int m1Thresh_off = 127;
34static const int m2Thresh_off = 127;
35static const int m2CountThr_off = 31;
36static const int m2CountThrLow_off = 63;
37static const int m1ThreshLowExt_off = 127;
38static const int m2ThreshLowExt_off = 127;
39static const int m1ThreshExt_off = 127;
40static const int m2ThreshExt_off = 127;
41
20/** 42/**
21 * ar9003_hw_set_channel - set channel on single-chip device 43 * ar9003_hw_set_channel - set channel on single-chip device
22 * @ah: atheros hardware structure 44 * @ah: atheros hardware structure
@@ -94,7 +116,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
94} 116}
95 117
96/** 118/**
97 * ar9003_hw_spur_mitigate - convert baseband spur frequency 119 * ar9003_hw_spur_mitigate_mrc_cck - convert baseband spur frequency
98 * @ah: atheros hardware structure 120 * @ah: atheros hardware structure
99 * @chan: 121 * @chan:
100 * 122 *
@@ -732,71 +754,68 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
732{ 754{
733 struct ar5416AniState *aniState = ah->curani; 755 struct ar5416AniState *aniState = ah->curani;
734 struct ath_common *common = ath9k_hw_common(ah); 756 struct ath_common *common = ath9k_hw_common(ah);
757 struct ath9k_channel *chan = ah->curchan;
758 s32 value, value2;
735 759
736 switch (cmd & ah->ani_function) { 760 switch (cmd & ah->ani_function) {
737 case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
738 u32 level = param;
739
740 if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
741 ath_print(common, ATH_DBG_ANI,
742 "level out of range (%u > %u)\n",
743 level,
744 (unsigned)ARRAY_SIZE(ah->totalSizeDesired));
745 return false;
746 }
747
748 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
749 AR_PHY_DESIRED_SZ_TOT_DES,
750 ah->totalSizeDesired[level]);
751 REG_RMW_FIELD(ah, AR_PHY_AGC,
752 AR_PHY_AGC_COARSE_LOW,
753 ah->coarse_low[level]);
754 REG_RMW_FIELD(ah, AR_PHY_AGC,
755 AR_PHY_AGC_COARSE_HIGH,
756 ah->coarse_high[level]);
757 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
758 AR_PHY_FIND_SIG_FIRPWR, ah->firpwr[level]);
759
760 if (level > aniState->noiseImmunityLevel)
761 ah->stats.ast_ani_niup++;
762 else if (level < aniState->noiseImmunityLevel)
763 ah->stats.ast_ani_nidown++;
764 aniState->noiseImmunityLevel = level;
765 break;
766 }
767 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ 761 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
768 const int m1ThreshLow[] = { 127, 50 }; 762 /*
769 const int m2ThreshLow[] = { 127, 40 }; 763 * on == 1 means ofdm weak signal detection is ON
770 const int m1Thresh[] = { 127, 0x4d }; 764 * on == 1 is the default, for less noise immunity
771 const int m2Thresh[] = { 127, 0x40 }; 765 *
772 const int m2CountThr[] = { 31, 16 }; 766 * on == 0 means ofdm weak signal detection is OFF
773 const int m2CountThrLow[] = { 63, 48 }; 767 * on == 0 means more noise imm
768 */
774 u32 on = param ? 1 : 0; 769 u32 on = param ? 1 : 0;
770 /*
771 * make register setting for default
772 * (weak sig detect ON) come from INI file
773 */
774 int m1ThreshLow = on ?
775 aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
776 int m2ThreshLow = on ?
777 aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
778 int m1Thresh = on ?
779 aniState->iniDef.m1Thresh : m1Thresh_off;
780 int m2Thresh = on ?
781 aniState->iniDef.m2Thresh : m2Thresh_off;
782 int m2CountThr = on ?
783 aniState->iniDef.m2CountThr : m2CountThr_off;
784 int m2CountThrLow = on ?
785 aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
786 int m1ThreshLowExt = on ?
787 aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
788 int m2ThreshLowExt = on ?
789 aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
790 int m1ThreshExt = on ?
791 aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
792 int m2ThreshExt = on ?
793 aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
775 794
776 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, 795 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
777 AR_PHY_SFCORR_LOW_M1_THRESH_LOW, 796 AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
778 m1ThreshLow[on]); 797 m1ThreshLow);
779 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, 798 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
780 AR_PHY_SFCORR_LOW_M2_THRESH_LOW, 799 AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
781 m2ThreshLow[on]); 800 m2ThreshLow);
782 REG_RMW_FIELD(ah, AR_PHY_SFCORR, 801 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
783 AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); 802 AR_PHY_SFCORR_M1_THRESH, m1Thresh);
784 REG_RMW_FIELD(ah, AR_PHY_SFCORR, 803 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
785 AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); 804 AR_PHY_SFCORR_M2_THRESH, m2Thresh);
786 REG_RMW_FIELD(ah, AR_PHY_SFCORR, 805 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
787 AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); 806 AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
788 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, 807 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
789 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, 808 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
790 m2CountThrLow[on]); 809 m2CountThrLow);
791 810
792 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, 811 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
793 AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); 812 AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
794 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, 813 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
795 AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); 814 AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
796 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, 815 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
797 AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); 816 AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
798 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, 817 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
799 AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); 818 AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
800 819
801 if (on) 820 if (on)
802 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, 821 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
@@ -806,6 +825,12 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
806 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); 825 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
807 826
808 if (!on != aniState->ofdmWeakSigDetectOff) { 827 if (!on != aniState->ofdmWeakSigDetectOff) {
828 ath_print(common, ATH_DBG_ANI,
829 "** ch %d: ofdm weak signal: %s=>%s\n",
830 chan->channel,
831 !aniState->ofdmWeakSigDetectOff ?
832 "on" : "off",
833 on ? "on" : "off");
809 if (on) 834 if (on)
810 ah->stats.ast_ani_ofdmon++; 835 ah->stats.ast_ani_ofdmon++;
811 else 836 else
@@ -814,64 +839,167 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
814 } 839 }
815 break; 840 break;
816 } 841 }
817 case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
818 const int weakSigThrCck[] = { 8, 6 };
819 u32 high = param ? 1 : 0;
820
821 REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
822 AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
823 weakSigThrCck[high]);
824 if (high != aniState->cckWeakSigThreshold) {
825 if (high)
826 ah->stats.ast_ani_cckhigh++;
827 else
828 ah->stats.ast_ani_ccklow++;
829 aniState->cckWeakSigThreshold = high;
830 }
831 break;
832 }
833 case ATH9K_ANI_FIRSTEP_LEVEL:{ 842 case ATH9K_ANI_FIRSTEP_LEVEL:{
834 const int firstep[] = { 0, 4, 8 };
835 u32 level = param; 843 u32 level = param;
836 844
837 if (level >= ARRAY_SIZE(firstep)) { 845 if (level >= ARRAY_SIZE(firstep_table)) {
838 ath_print(common, ATH_DBG_ANI, 846 ath_print(common, ATH_DBG_ANI,
839 "level out of range (%u > %u)\n", 847 "ATH9K_ANI_FIRSTEP_LEVEL: level "
848 "out of range (%u > %u)\n",
840 level, 849 level,
841 (unsigned) ARRAY_SIZE(firstep)); 850 (unsigned) ARRAY_SIZE(firstep_table));
842 return false; 851 return false;
843 } 852 }
853
854 /*
855 * make register setting relative to default
856 * from INI file & cap value
857 */
858 value = firstep_table[level] -
859 firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
860 aniState->iniDef.firstep;
861 if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
862 value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
863 if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
864 value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
844 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, 865 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
845 AR_PHY_FIND_SIG_FIRSTEP, 866 AR_PHY_FIND_SIG_FIRSTEP,
846 firstep[level]); 867 value);
847 if (level > aniState->firstepLevel) 868 /*
848 ah->stats.ast_ani_stepup++; 869 * we need to set first step low register too
849 else if (level < aniState->firstepLevel) 870 * make register setting relative to default
850 ah->stats.ast_ani_stepdown++; 871 * from INI file & cap value
851 aniState->firstepLevel = level; 872 */
873 value2 = firstep_table[level] -
874 firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] +
875 aniState->iniDef.firstepLow;
876 if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
877 value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
878 if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
879 value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
880
881 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
882 AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2);
883
884 if (level != aniState->firstepLevel) {
885 ath_print(common, ATH_DBG_ANI,
886 "** ch %d: level %d=>%d[def:%d] "
887 "firstep[level]=%d ini=%d\n",
888 chan->channel,
889 aniState->firstepLevel,
890 level,
891 ATH9K_ANI_FIRSTEP_LVL_NEW,
892 value,
893 aniState->iniDef.firstep);
894 ath_print(common, ATH_DBG_ANI,
895 "** ch %d: level %d=>%d[def:%d] "
896 "firstep_low[level]=%d ini=%d\n",
897 chan->channel,
898 aniState->firstepLevel,
899 level,
900 ATH9K_ANI_FIRSTEP_LVL_NEW,
901 value2,
902 aniState->iniDef.firstepLow);
903 if (level > aniState->firstepLevel)
904 ah->stats.ast_ani_stepup++;
905 else if (level < aniState->firstepLevel)
906 ah->stats.ast_ani_stepdown++;
907 aniState->firstepLevel = level;
908 }
852 break; 909 break;
853 } 910 }
854 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ 911 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
855 const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
856 u32 level = param; 912 u32 level = param;
857 913
858 if (level >= ARRAY_SIZE(cycpwrThr1)) { 914 if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
859 ath_print(common, ATH_DBG_ANI, 915 ath_print(common, ATH_DBG_ANI,
860 "level out of range (%u > %u)\n", 916 "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level "
917 "out of range (%u > %u)\n",
861 level, 918 level,
862 (unsigned) ARRAY_SIZE(cycpwrThr1)); 919 (unsigned) ARRAY_SIZE(cycpwrThr1_table));
863 return false; 920 return false;
864 } 921 }
922 /*
923 * make register setting relative to default
924 * from INI file & cap value
925 */
926 value = cycpwrThr1_table[level] -
927 cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
928 aniState->iniDef.cycpwrThr1;
929 if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
930 value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
931 if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
932 value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
865 REG_RMW_FIELD(ah, AR_PHY_TIMING5, 933 REG_RMW_FIELD(ah, AR_PHY_TIMING5,
866 AR_PHY_TIMING5_CYCPWR_THR1, 934 AR_PHY_TIMING5_CYCPWR_THR1,
867 cycpwrThr1[level]); 935 value);
868 if (level > aniState->spurImmunityLevel) 936
869 ah->stats.ast_ani_spurup++; 937 /*
870 else if (level < aniState->spurImmunityLevel) 938 * set AR_PHY_EXT_CCA for extension channel
871 ah->stats.ast_ani_spurdown++; 939 * make register setting relative to default
872 aniState->spurImmunityLevel = level; 940 * from INI file & cap value
941 */
942 value2 = cycpwrThr1_table[level] -
943 cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] +
944 aniState->iniDef.cycpwrThr1Ext;
945 if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
946 value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
947 if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
948 value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
949 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
950 AR_PHY_EXT_CYCPWR_THR1, value2);
951
952 if (level != aniState->spurImmunityLevel) {
953 ath_print(common, ATH_DBG_ANI,
954 "** ch %d: level %d=>%d[def:%d] "
955 "cycpwrThr1[level]=%d ini=%d\n",
956 chan->channel,
957 aniState->spurImmunityLevel,
958 level,
959 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
960 value,
961 aniState->iniDef.cycpwrThr1);
962 ath_print(common, ATH_DBG_ANI,
963 "** ch %d: level %d=>%d[def:%d] "
964 "cycpwrThr1Ext[level]=%d ini=%d\n",
965 chan->channel,
966 aniState->spurImmunityLevel,
967 level,
968 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW,
969 value2,
970 aniState->iniDef.cycpwrThr1Ext);
971 if (level > aniState->spurImmunityLevel)
972 ah->stats.ast_ani_spurup++;
973 else if (level < aniState->spurImmunityLevel)
974 ah->stats.ast_ani_spurdown++;
975 aniState->spurImmunityLevel = level;
976 }
873 break; 977 break;
874 } 978 }
979 case ATH9K_ANI_MRC_CCK:{
980 /*
981 * is_on == 1 means MRC CCK ON (default, less noise imm)
982 * is_on == 0 means MRC CCK is OFF (more noise imm)
983 */
984 bool is_on = param ? 1 : 0;
985 REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
986 AR_PHY_MRC_CCK_ENABLE, is_on);
987 REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
988 AR_PHY_MRC_CCK_MUX_REG, is_on);
989 if (!is_on != aniState->mrcCCKOff) {
990 ath_print(common, ATH_DBG_ANI,
991 "** ch %d: MRC CCK: %s=>%s\n",
992 chan->channel,
993 !aniState->mrcCCKOff ? "on" : "off",
994 is_on ? "on" : "off");
995 if (is_on)
996 ah->stats.ast_ani_ccklow++;
997 else
998 ah->stats.ast_ani_cckhigh++;
999 aniState->mrcCCKOff = !is_on;
1000 }
1001 break;
1002 }
875 case ATH9K_ANI_PRESENT: 1003 case ATH9K_ANI_PRESENT:
876 break; 1004 break;
877 default: 1005 default:
@@ -880,25 +1008,19 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
880 return false; 1008 return false;
881 } 1009 }
882 1010
883 ath_print(common, ATH_DBG_ANI, "ANI parameters:\n");
884 ath_print(common, ATH_DBG_ANI, 1011 ath_print(common, ATH_DBG_ANI,
885 "noiseImmunityLevel=%d, spurImmunityLevel=%d, " 1012 "ANI parameters: SI=%d, ofdmWS=%s FS=%d "
886 "ofdmWeakSigDetectOff=%d\n", 1013 "MRCcck=%s listenTime=%d CC=%d listen=%d "
887 aniState->noiseImmunityLevel, 1014 "ofdmErrs=%d cckErrs=%d\n",
888 aniState->spurImmunityLevel, 1015 aniState->spurImmunityLevel,
889 !aniState->ofdmWeakSigDetectOff); 1016 !aniState->ofdmWeakSigDetectOff ? "on" : "off",
890 ath_print(common, ATH_DBG_ANI,
891 "cckWeakSigThreshold=%d, "
892 "firstepLevel=%d, listenTime=%d\n",
893 aniState->cckWeakSigThreshold,
894 aniState->firstepLevel, 1017 aniState->firstepLevel,
895 aniState->listenTime); 1018 !aniState->mrcCCKOff ? "on" : "off",
896 ath_print(common, ATH_DBG_ANI, 1019 aniState->listenTime,
897 "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", 1020 aniState->cycleCount,
898 aniState->cycleCount, 1021 aniState->listenTime,
899 aniState->ofdmPhyErrCount, 1022 aniState->ofdmPhyErrCount,
900 aniState->cckPhyErrCount); 1023 aniState->cckPhyErrCount);
901
902 return true; 1024 return true;
903} 1025}
904 1026
@@ -1111,6 +1233,70 @@ static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
1111 } 1233 }
1112} 1234}
1113 1235
1236/*
1237 * Initialize the ANI register values with default (ini) values.
1238 * This routine is called during a (full) hardware reset after
1239 * all the registers are initialised from the INI.
1240 */
1241static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
1242{
1243 struct ar5416AniState *aniState;
1244 struct ath_common *common = ath9k_hw_common(ah);
1245 struct ath9k_channel *chan = ah->curchan;
1246 struct ath9k_ani_default *iniDef;
1247 int index;
1248 u32 val;
1249
1250 index = ath9k_hw_get_ani_channel_idx(ah, chan);
1251 aniState = &ah->ani[index];
1252 ah->curani = aniState;
1253 iniDef = &aniState->iniDef;
1254
1255 ath_print(common, ATH_DBG_ANI,
1256 "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
1257 ah->hw_version.macVersion,
1258 ah->hw_version.macRev,
1259 ah->opmode,
1260 chan->channel,
1261 chan->channelFlags);
1262
1263 val = REG_READ(ah, AR_PHY_SFCORR);
1264 iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH);
1265 iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH);
1266 iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR);
1267
1268 val = REG_READ(ah, AR_PHY_SFCORR_LOW);
1269 iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW);
1270 iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW);
1271 iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW);
1272
1273 val = REG_READ(ah, AR_PHY_SFCORR_EXT);
1274 iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH);
1275 iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH);
1276 iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW);
1277 iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW);
1278 iniDef->firstep = REG_READ_FIELD(ah,
1279 AR_PHY_FIND_SIG,
1280 AR_PHY_FIND_SIG_FIRSTEP);
1281 iniDef->firstepLow = REG_READ_FIELD(ah,
1282 AR_PHY_FIND_SIG_LOW,
1283 AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW);
1284 iniDef->cycpwrThr1 = REG_READ_FIELD(ah,
1285 AR_PHY_TIMING5,
1286 AR_PHY_TIMING5_CYCPWR_THR1);
1287 iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah,
1288 AR_PHY_EXT_CCA,
1289 AR_PHY_EXT_CYCPWR_THR1);
1290
1291 /* these levels just got reset to defaults by the INI */
1292 aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
1293 aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
1294 aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
1295 aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
1296
1297 aniState->cycleCount = 0;
1298}
1299
1114void ar9003_hw_attach_phy_ops(struct ath_hw *ah) 1300void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
1115{ 1301{
1116 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 1302 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -1131,6 +1317,7 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
1131 priv_ops->ani_control = ar9003_hw_ani_control; 1317 priv_ops->ani_control = ar9003_hw_ani_control;
1132 priv_ops->do_getnf = ar9003_hw_do_getnf; 1318 priv_ops->do_getnf = ar9003_hw_do_getnf;
1133 priv_ops->loadnf = ar9003_hw_loadnf; 1319 priv_ops->loadnf = ar9003_hw_loadnf;
1320 priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
1134} 1321}
1135 1322
1136void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) 1323void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 82aca4b6154c..c00946ddd97e 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -417,7 +417,8 @@ int ath_beaconq_config(struct ath_softc *sc);
417 417
418#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ 418#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */
419#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ 419#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */
420#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ 420#define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */
421#define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */
421#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ 422#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
422#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ 423#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
423 424
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 5f46861fd100..739be8f6e6af 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -75,6 +75,15 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
75 ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); 75 ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah);
76} 76}
77 77
78static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah)
79{
80 /* You will not have this callback if using the old ANI */
81 if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs)
82 return;
83
84 ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah);
85}
86
78/********************/ 87/********************/
79/* Helper Functions */ 88/* Helper Functions */
80/********************/ 89/********************/
@@ -560,6 +569,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)
560 ah->ani_function = ATH9K_ANI_ALL; 569 ah->ani_function = ATH9K_ANI_ALL;
561 if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) 570 if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
562 ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; 571 ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
572 if (!AR_SREV_9300_20_OR_LATER(ah))
573 ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
563 574
564 ath9k_hw_init_mode_regs(ah); 575 ath9k_hw_init_mode_regs(ah);
565 576
@@ -1360,6 +1371,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1360 ath9k_hw_resettxqueue(ah, i); 1371 ath9k_hw_resettxqueue(ah, i);
1361 1372
1362 ath9k_hw_init_interrupt_masks(ah, ah->opmode); 1373 ath9k_hw_init_interrupt_masks(ah, ah->opmode);
1374 ath9k_hw_ani_cache_ini_regs(ah);
1363 ath9k_hw_init_qos(ah); 1375 ath9k_hw_init_qos(ah);
1364 1376
1365 if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) 1377 if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 790a4572270f..009f0fafee5d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -266,6 +266,7 @@ struct ath9k_ops_config {
266 int spurmode; 266 int spurmode;
267 u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; 267 u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
268 u8 max_txtrig_level; 268 u8 max_txtrig_level;
269 u16 ani_poll_interval; /* ANI poll interval in ms */
269}; 270};
270 271
271enum ath9k_int { 272enum ath9k_int {
@@ -520,6 +521,8 @@ struct ath_gen_timer_table {
520 * few dB more of noise immunity. If you have a strong time-varying 521 * few dB more of noise immunity. If you have a strong time-varying
521 * interference that is causing false detections (OFDM timing errors or 522 * interference that is causing false detections (OFDM timing errors or
522 * CCK timing errors) the level can be increased. 523 * CCK timing errors) the level can be increased.
524 * @ani_cache_ini_regs: cache the values for ANI from the initial
525 * register settings through the register initialization.
523 */ 526 */
524struct ath_hw_private_ops { 527struct ath_hw_private_ops {
525 /* Calibration ops */ 528 /* Calibration ops */
@@ -567,6 +570,7 @@ struct ath_hw_private_ops {
567 /* ANI */ 570 /* ANI */
568 void (*ani_reset)(struct ath_hw *ah, bool is_scanning); 571 void (*ani_reset)(struct ath_hw *ah, bool is_scanning);
569 void (*ani_lower_immunity)(struct ath_hw *ah); 572 void (*ani_lower_immunity)(struct ath_hw *ah);
573 void (*ani_cache_ini_regs)(struct ath_hw *ah);
570}; 574};
571 575
572/** 576/**
@@ -959,9 +963,12 @@ void ar9003_hw_attach_ops(struct ath_hw *ah);
959 * ANI work can be shared between all families but a next 963 * ANI work can be shared between all families but a next
960 * generation implementation of ANI will be used only for AR9003 only 964 * generation implementation of ANI will be used only for AR9003 only
961 * for now as the other families still need to be tested with the same 965 * for now as the other families still need to be tested with the same
962 * next generation ANI. 966 * next generation ANI. Feel free to start testing it though for the
967 * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
963 */ 968 */
969extern int modparam_force_new_ani;
964void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah); 970void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah);
971void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah);
965 972
966#define ATH_PCIE_CAP_LINK_CTRL 0x70 973#define ATH_PCIE_CAP_LINK_CTRL 0x70
967#define ATH_PCIE_CAP_LINK_L0S 1 974#define ATH_PCIE_CAP_LINK_L0S 1
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e1b8456f3d2c..9959e89d5496 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -285,7 +285,8 @@ void ath_ani_calibrate(unsigned long data)
285 } 285 }
286 286
287 /* Verify whether we must check ANI */ 287 /* Verify whether we must check ANI */
288 if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { 288 if ((timestamp - common->ani.checkani_timer) >=
289 ah->config.ani_poll_interval) {
289 aniflag = true; 290 aniflag = true;
290 common->ani.checkani_timer = timestamp; 291 common->ani.checkani_timer = timestamp;
291 } 292 }
@@ -326,7 +327,8 @@ set_timer:
326 */ 327 */
327 cal_interval = ATH_LONG_CALINTERVAL; 328 cal_interval = ATH_LONG_CALINTERVAL;
328 if (sc->sc_ah->config.enable_ani) 329 if (sc->sc_ah->config.enable_ani)
329 cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); 330 cal_interval = min(cal_interval,
331 (u32)ah->config.ani_poll_interval);
330 if (!common->ani.caldone) 332 if (!common->ani.caldone)
331 cal_interval = min(cal_interval, (u32)short_cal_interval); 333 cal_interval = min(cal_interval, (u32)short_cal_interval);
332 334
@@ -335,6 +337,7 @@ set_timer:
335 337
336static void ath_start_ani(struct ath_common *common) 338static void ath_start_ani(struct ath_common *common)
337{ 339{
340 struct ath_hw *ah = common->ah;
338 unsigned long timestamp = jiffies_to_msecs(jiffies); 341 unsigned long timestamp = jiffies_to_msecs(jiffies);
339 342
340 common->ani.longcal_timer = timestamp; 343 common->ani.longcal_timer = timestamp;
@@ -342,7 +345,8 @@ static void ath_start_ani(struct ath_common *common)
342 common->ani.checkani_timer = timestamp; 345 common->ani.checkani_timer = timestamp;
343 346
344 mod_timer(&common->ani.timer, 347 mod_timer(&common->ani.timer,
345 jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); 348 jiffies +
349 msecs_to_jiffies((u32)ah->config.ani_poll_interval));
346} 350}
347 351
348/* 352/*