diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ani.c | 676 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ani.h | 74 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar5008_phy.c | 361 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9002_hw.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_hw.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.c | 385 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 10 |
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 | ||
20 | struct 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 | |||
37 | static 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 | |||
78 | struct ani_cck_level_entry { | ||
79 | int fir_step_level; | ||
80 | int mrc_cck_on; | ||
81 | }; | ||
82 | |||
83 | static 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 */ |
21 | static inline void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | 106 | static 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 | ||
26 | static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | 111 | int 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 | ||
57 | static void ath9k_ani_restart(struct ath_hw *ah) | 142 | static 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 | ||
105 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | 190 | static 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 | |||
225 | static 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 | ||
177 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | 297 | static 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 */ | ||
336 | static 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 | |||
383 | static 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 | */ | ||
399 | static 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 | |||
440 | static 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 | |||
215 | static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | 453 | static 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 | */ | ||
510 | static 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 | |||
268 | static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) | 528 | static 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) | |||
289 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | 549 | static 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 | */ | ||
685 | static 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 | |||
860 | static 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 | */ | ||
1151 | static 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 | |||
637 | void ath9k_hw_ani_setup(struct ath_hw *ah) | 1184 | void 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 | |||
1310 | void 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 | |||
43 | enum ath9k_ani_cmd { | 75 | enum 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 | ||
55 | struct ath9k_mib_stats { | 88 | struct 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 */ | ||
97 | struct 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 | |||
63 | struct ar5416AniState { | 114 | struct 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 | ||
90 | struct ar5416Stats { | 146 | struct 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); |
115 | void ath9k_hw_ani_setup(struct ath_hw *ah); | 171 | void ath9k_hw_ani_setup(struct ath_hw *ah); |
116 | void ath9k_hw_ani_init(struct ath_hw *ah); | 172 | void ath9k_hw_ani_init(struct ath_hw *ah); |
173 | int 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 | |||
24 | static 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 | |||
28 | static 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 | */ | ||
35 | static const int m1ThreshLow_off = 127; | ||
36 | static const int m2ThreshLow_off = 127; | ||
37 | static const int m1Thresh_off = 127; | ||
38 | static const int m2Thresh_off = 127; | ||
39 | static const int m2CountThr_off = 31; | ||
40 | static const int m2CountThrLow_off = 63; | ||
41 | static const int m1ThreshLowExt_off = 127; | ||
42 | static const int m2ThreshLowExt_off = 127; | ||
43 | static const int m1ThreshExt_off = 127; | ||
44 | static 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 | ||
1029 | static bool ar5008_hw_ani_control(struct ath_hw *ah, | 1052 | static 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 | ||
1236 | static 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 | |||
1212 | static void ar5008_hw_do_getnf(struct ath_hw *ah, | 1495 | static 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 | */ | ||
1620 | static 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 | |||
1332 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | 1680 | void 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 | ||
23 | int modparam_force_new_ani; | ||
24 | module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); | ||
25 | MODULE_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 | ||
25 | static bool ar9002_hw_macversion_supported(u32 macversion) | 29 | static 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 | ||
20 | static 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 | |||
24 | static 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 | */ | ||
31 | static const int m1ThreshLow_off = 127; | ||
32 | static const int m2ThreshLow_off = 127; | ||
33 | static const int m1Thresh_off = 127; | ||
34 | static const int m2Thresh_off = 127; | ||
35 | static const int m2CountThr_off = 31; | ||
36 | static const int m2CountThrLow_off = 63; | ||
37 | static const int m1ThreshLowExt_off = 127; | ||
38 | static const int m2ThreshLowExt_off = 127; | ||
39 | static const int m1ThreshExt_off = 127; | ||
40 | static 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 | */ | ||
1241 | static 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 | |||
1114 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1300 | void 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 | ||
1136 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) | 1323 | void 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 | ||
78 | static 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 | ||
271 | enum ath9k_int { | 272 | enum 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 | */ |
524 | struct ath_hw_private_ops { | 527 | struct 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 | */ |
969 | extern int modparam_force_new_ani; | ||
964 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah); | 970 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah); |
971 | void 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 | ||
336 | static void ath_start_ani(struct ath_common *common) | 338 | static 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 | /* |