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 | /* |
