1/* 2 * Copyright (c) 2008-2010 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include "hw.h" 18#include "hw-ops.h" 19 20struct ani_ofdm_level_entry { 21 int spur_immunity_level; 22 int fir_step_level; 23 int ofdm_weak_signal_on; 24}; 25 26/* values here are relative to the INI */ 27 28/* 29 * Legend: 30 * 31 * SI: Spur immunity 32 * FS: FIR Step 33 * WS: OFDM / CCK Weak Signal detection 34 * MRC-CCK: Maximal Ratio Combining for CCK 35 */ 36 37static const struct ani_ofdm_level_entry ofdm_level_table[] = { 38 /* SI FS WS */ 39 { 0, 0, 1 }, /* lvl 0 */ 40 { 1, 1, 1 }, /* lvl 1 */ 41 { 2, 2, 1 }, /* lvl 2 */ 42 { 3, 2, 1 }, /* lvl 3 (default) */ 43 { 4, 3, 1 }, /* lvl 4 */ 44 { 5, 4, 1 }, /* lvl 5 */ 45 { 6, 5, 1 }, /* lvl 6 */ 46 { 7, 6, 1 }, /* lvl 7 */ 47 { 7, 7, 1 }, /* lvl 8 */ 48 { 7, 8, 0 } /* lvl 9 */ 49}; 50#define ATH9K_ANI_OFDM_NUM_LEVEL \ 51 (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0])) 52#define ATH9K_ANI_OFDM_MAX_LEVEL \ 53 (ATH9K_ANI_OFDM_NUM_LEVEL-1) 54#define ATH9K_ANI_OFDM_DEF_LEVEL \ 55 3 /* default level - matches the INI settings */ 56 57/* 58 * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm. 59 * With OFDM for single stream you just add up all antenna inputs, you're 60 * only interested in what you get after FFT. Signal aligment is also not 61 * required for OFDM because any phase difference adds up in the frequency 62 * domain. 63 * 64 * MRC requires extra work for use with CCK. You need to align the antenna 65 * signals from the different antenna before you can add the signals together. 66 * You need aligment of signals as CCK is in time domain, so addition can cancel 67 * your signal completely if phase is 180 degrees (think of adding sine waves). 68 * You also need to remove noise before the addition and this is where ANI 69 * MRC CCK comes into play. One of the antenna inputs may be stronger but 70 * lower SNR, so just adding after alignment can be dangerous. 71 * 72 * Regardless of alignment in time, the antenna signals add constructively after 73 * FFT and improve your reception. For more information: 74 * 75 * http://en.wikipedia.org/wiki/Maximal-ratio_combining 76 */ 77 78struct ani_cck_level_entry { 79 int fir_step_level; 80 int mrc_cck_on; 81}; 82 83static const struct ani_cck_level_entry cck_level_table[] = { 84 /* FS MRC-CCK */ 85 { 0, 1 }, /* lvl 0 */ 86 { 1, 1 }, /* lvl 1 */ 87 { 2, 1 }, /* lvl 2 (default) */ 88 { 3, 1 }, /* lvl 3 */ 89 { 4, 0 }, /* lvl 4 */ 90 { 5, 0 }, /* lvl 5 */ 91 { 6, 0 }, /* lvl 6 */ 92 { 7, 0 }, /* lvl 7 (only for high rssi) */ 93 { 8, 0 } /* lvl 8 (only for high rssi) */ 94}; 95 96#define ATH9K_ANI_CCK_NUM_LEVEL \ 97 (sizeof(cck_level_table)/sizeof(cck_level_table[0])) 98#define ATH9K_ANI_CCK_MAX_LEVEL \ 99 (ATH9K_ANI_CCK_NUM_LEVEL-1) 100#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ 101 (ATH9K_ANI_CCK_NUM_LEVEL-3) 102#define ATH9K_ANI_CCK_DEF_LEVEL \ 103 2 /* default level - matches the INI settings */ 104 105/* Private to ani.c */ 106static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) 107{ 108 ath9k_hw_private_ops(ah)->ani_lower_immunity(ah); 109} 110 111int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, 112 struct ath9k_channel *chan) 113{ 114 int i; 115 116 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { 117 if (ah->ani[i].c && 118 ah->ani[i].c->channel == chan->channel) 119 return i; 120 if (ah->ani[i].c == NULL) { 121 ah->ani[i].c = chan; 122 return i; 123 } 124 } 125 126 ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, 127 "No more channel states left. Using channel 0\n"); 128 129 return 0; 130} 131 132static void ath9k_hw_update_mibstats(struct ath_hw *ah, 133 struct ath9k_mib_stats *stats) 134{ 135 stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL); 136 stats->rts_bad += REG_READ(ah, AR_RTS_FAIL); 137 stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL); 138 stats->rts_good += REG_READ(ah, AR_RTS_OK); 139 stats->beacons += REG_READ(ah, AR_BEACON_CNT); 140} 141 142static void ath9k_ani_restart_old(struct ath_hw *ah) 143{ 144 struct ar5416AniState *aniState; 145 struct ath_common *common = ath9k_hw_common(ah); 146 147 if (!DO_ANI(ah)) 148 return; 149 150 aniState = ah->curani; 151 aniState->listenTime = 0; 152 153 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { 154 aniState->ofdmPhyErrBase = 0; 155 ath_print(common, ATH_DBG_ANI, 156 "OFDM Trigger is too high for hw counters\n"); 157 } else { 158 aniState->ofdmPhyErrBase = 159 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; 160 } 161 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { 162 aniState->cckPhyErrBase = 0; 163 ath_print(common, ATH_DBG_ANI, 164 "CCK Trigger is too high for hw counters\n"); 165 } else { 166 aniState->cckPhyErrBase = 167 AR_PHY_COUNTMAX - aniState->cckTrigHigh; 168 } 169 ath_print(common, ATH_DBG_ANI, 170 "Writing ofdmbase=%u cckbase=%u\n", 171 aniState->ofdmPhyErrBase, 172 aniState->cckPhyErrBase); 173 174 ENABLE_REGWRITE_BUFFER(ah); 175 176 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); 177 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); 178 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 179 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 180 181 REGWRITE_BUFFER_FLUSH(ah); 182 DISABLE_REGWRITE_BUFFER(ah); 183 184 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 185 186 aniState->ofdmPhyErrCount = 0; 187 aniState->cckPhyErrCount = 0; 188} 189 190static void ath9k_ani_restart_new(struct ath_hw *ah) 191{ 192 struct ar5416AniState *aniState; 193 struct ath_common *common = ath9k_hw_common(ah); 194 195 if (!DO_ANI(ah)) 196 return; 197 198 aniState = ah->curani; 199 aniState->listenTime = 0; 200 201 aniState->ofdmPhyErrBase = 0; 202 aniState->cckPhyErrBase = 0; 203 204 ath_print(common, ATH_DBG_ANI, 205 "Writing ofdmbase=%08x cckbase=%08x\n", 206 aniState->ofdmPhyErrBase, 207 aniState->cckPhyErrBase); 208 209 ENABLE_REGWRITE_BUFFER(ah); 210 211 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); 212 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); 213 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 214 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 215 216 REGWRITE_BUFFER_FLUSH(ah); 217 DISABLE_REGWRITE_BUFFER(ah); 218 219 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 220 221 aniState->ofdmPhyErrCount = 0; 222 aniState->cckPhyErrCount = 0; 223} 224 225static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah) 226{ 227 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 228 struct ar5416AniState *aniState; 229 int32_t rssi; 230 231 if (!DO_ANI(ah)) 232 return; 233 234 aniState = ah->curani; 235 236 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { 237 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 238 aniState->noiseImmunityLevel + 1)) { 239 return; 240 } 241 } 242 243 if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) { 244 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 245 aniState->spurImmunityLevel + 1)) { 246 return; 247 } 248 } 249 250 if (ah->opmode == NL80211_IFTYPE_AP) { 251 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { 252 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 253 aniState->firstepLevel + 1); 254 } 255 return; 256 } 257 rssi = BEACON_RSSI(ah); 258 if (rssi > aniState->rssiThrHigh) { 259 if (!aniState->ofdmWeakSigDetectOff) { 260 if (ath9k_hw_ani_control(ah, 261 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, 262 false)) { 263 ath9k_hw_ani_control(ah, 264 ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); 265 return; 266 } 267 } 268 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { 269 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 270 aniState->firstepLevel + 1); 271 return; 272 } 273 } else if (rssi > aniState->rssiThrLow) { 274 if (aniState->ofdmWeakSigDetectOff) 275 ath9k_hw_ani_control(ah, 276 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, 277 true); 278 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) 279 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 280 aniState->firstepLevel + 1); 281 return; 282 } else { 283 if ((conf->channel->band == IEEE80211_BAND_2GHZ) && 284 !conf_is_ht(conf)) { 285 if (!aniState->ofdmWeakSigDetectOff) 286 ath9k_hw_ani_control(ah, 287 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, 288 false); 289 if (aniState->firstepLevel > 0) 290 ath9k_hw_ani_control(ah, 291 ATH9K_ANI_FIRSTEP_LEVEL, 0); 292 return; 293 } 294 } 295} 296 297static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) 298{ 299 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 300 struct ar5416AniState *aniState; 301 int32_t rssi; 302 303 if (!DO_ANI(ah)) 304 return; 305 306 aniState = ah->curani; 307 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { 308 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 309 aniState->noiseImmunityLevel + 1)) { 310 return; 311 } 312 } 313 if (ah->opmode == NL80211_IFTYPE_AP) { 314 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { 315 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 316 aniState->firstepLevel + 1); 317 } 318 return; 319 } 320 rssi = BEACON_RSSI(ah); 321 if (rssi > aniState->rssiThrLow) { 322 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) 323 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 324 aniState->firstepLevel + 1); 325 } else { 326 if ((conf->channel->band == IEEE80211_BAND_2GHZ) && 327 !conf_is_ht(conf)) { 328 if (aniState->firstepLevel > 0) 329 ath9k_hw_ani_control(ah, 330 ATH9K_ANI_FIRSTEP_LEVEL, 0); 331 } 332 } 333} 334 335/* Adjust the OFDM Noise Immunity Level */ 336static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) 337{ 338 struct ar5416AniState *aniState = ah->curani; 339 struct ath_common *common = ath9k_hw_common(ah); 340 const struct ani_ofdm_level_entry *entry_ofdm; 341 const struct ani_cck_level_entry *entry_cck; 342 343 aniState->noiseFloor = BEACON_RSSI(ah); 344 345 ath_print(common, ATH_DBG_ANI, 346 "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", 347 aniState->ofdmNoiseImmunityLevel, 348 immunityLevel, aniState->noiseFloor, 349 aniState->rssiThrLow, aniState->rssiThrHigh); 350 351 aniState->ofdmNoiseImmunityLevel = immunityLevel; 352 353 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; 354 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; 355 356 if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level) 357 ath9k_hw_ani_control(ah, 358 ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 359 entry_ofdm->spur_immunity_level); 360 361 if (aniState->firstepLevel != entry_ofdm->fir_step_level && 362 entry_ofdm->fir_step_level >= entry_cck->fir_step_level) 363 ath9k_hw_ani_control(ah, 364 ATH9K_ANI_FIRSTEP_LEVEL, 365 entry_ofdm->fir_step_level); 366 367 if ((ah->opmode != NL80211_IFTYPE_STATION && 368 ah->opmode != NL80211_IFTYPE_ADHOC) || 369 aniState->noiseFloor <= aniState->rssiThrHigh) { 370 if (aniState->ofdmWeakSigDetectOff) 371 /* force on ofdm weak sig detect */ 372 ath9k_hw_ani_control(ah, 373 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, 374 true); 375 else if (aniState->ofdmWeakSigDetectOff == 376 entry_ofdm->ofdm_weak_signal_on) 377 ath9k_hw_ani_control(ah, 378 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, 379 entry_ofdm->ofdm_weak_signal_on); 380 } 381} 382 383static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) 384{ 385 struct ar5416AniState *aniState; 386 387 if (!DO_ANI(ah)) 388 return; 389 390 aniState = ah->curani; 391 392 if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) 393 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); 394} 395 396/* 397 * Set the ANI settings to match an CCK level. 398 */ 399static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) 400{ 401 struct ar5416AniState *aniState = ah->curani; 402 struct ath_common *common = ath9k_hw_common(ah); 403 const struct ani_ofdm_level_entry *entry_ofdm; 404 const struct ani_cck_level_entry *entry_cck; 405 406 aniState->noiseFloor = BEACON_RSSI(ah); 407 ath_print(common, ATH_DBG_ANI, 408 "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", 409 aniState->cckNoiseImmunityLevel, immunityLevel, 410 aniState->noiseFloor, aniState->rssiThrLow, 411 aniState->rssiThrHigh); 412 413 if ((ah->opmode == NL80211_IFTYPE_STATION || 414 ah->opmode == NL80211_IFTYPE_ADHOC) && 415 aniState->noiseFloor <= aniState->rssiThrLow && 416 immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) 417 immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; 418 419 aniState->cckNoiseImmunityLevel = immunityLevel; 420 421 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; 422 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; 423 424 if (aniState->firstepLevel != entry_cck->fir_step_level && 425 entry_cck->fir_step_level >= entry_ofdm->fir_step_level) 426 ath9k_hw_ani_control(ah, 427 ATH9K_ANI_FIRSTEP_LEVEL, 428 entry_cck->fir_step_level); 429 430 /* Skip MRC CCK for pre AR9003 families */ 431 if (!AR_SREV_9300_20_OR_LATER(ah)) 432 return; 433 434 if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) 435 ath9k_hw_ani_control(ah, 436 ATH9K_ANI_MRC_CCK, 437 entry_cck->mrc_cck_on); 438} 439 440static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah) 441{ 442 struct ar5416AniState *aniState; 443 444 if (!DO_ANI(ah)) 445 return; 446 447 aniState = ah->curani; 448 449 if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) 450 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); 451} 452 453static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) 454{ 455 struct ar5416AniState *aniState; 456 int32_t rssi; 457 458 aniState = ah->curani; 459 460 if (ah->opmode == NL80211_IFTYPE_AP) { 461 if (aniState->firstepLevel > 0) { 462 if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 463 aniState->firstepLevel - 1)) 464 return; 465 } 466 } else { 467 rssi = BEACON_RSSI(ah); 468 if (rssi > aniState->rssiThrHigh) { 469 } else if (rssi > aniState->rssiThrLow) { 470 if (aniState->ofdmWeakSigDetectOff) { 471 if (ath9k_hw_ani_control(ah, 472 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, 473 true) == true) 474 return; 475 } 476 if (aniState->firstepLevel > 0) { 477 if (ath9k_hw_ani_control(ah, 478 ATH9K_ANI_FIRSTEP_LEVEL, 479 aniState->firstepLevel - 1) == true) 480 return; 481 } 482 } else { 483 if (aniState->firstepLevel > 0) { 484 if (ath9k_hw_ani_control(ah, 485 ATH9K_ANI_FIRSTEP_LEVEL, 486 aniState->firstepLevel - 1) == true) 487 return; 488 } 489 } 490 } 491 492 if (aniState->spurImmunityLevel > 0) { 493 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 494 aniState->spurImmunityLevel - 1)) 495 return; 496 } 497 498 if (aniState->noiseImmunityLevel > 0) { 499 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 500 aniState->noiseImmunityLevel - 1); 501 return; 502 } 503} 504 505/* 506 * only lower either OFDM or CCK errors per turn 507 * we lower the other one next time 508 */ 509static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah) 510{ 511 struct ar5416AniState *aniState; 512 513 aniState = ah->curani; 514 515 /* lower OFDM noise immunity */ 516 if (aniState->ofdmNoiseImmunityLevel > 0 && 517 (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) { 518 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1); 519 return; 520 } 521 522 /* lower CCK noise immunity */ 523 if (aniState->cckNoiseImmunityLevel > 0) 524 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); 525} 526 527static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) 528{ 529 struct ath9k_channel *chan = ah->curchan; 530 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; 531 u8 clockrate; /* in MHz */ 532 533 if (!ah->curchan) /* should really check for CCK instead */ 534 clockrate = ATH9K_CLOCK_RATE_CCK; 535 else if (conf->channel->band == IEEE80211_BAND_2GHZ) 536 clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; 537 else if (IS_CHAN_A_FAST_CLOCK(ah, chan)) 538 clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; 539 else 540 clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; 541 542 if (conf_is_ht40(conf)) 543 return clockrate * 2; 544 545 return clockrate; 546} 547 548static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) 549{ 550 struct ar5416AniState *aniState; 551 struct ath_common *common = ath9k_hw_common(ah); 552 u32 txFrameCount, rxFrameCount, cycleCount; 553 int32_t listenTime; 554 555 txFrameCount = REG_READ(ah, AR_TFCNT); 556 rxFrameCount = REG_READ(ah, AR_RFCNT); 557 cycleCount = REG_READ(ah, AR_CCCNT); 558 559 aniState = ah->curani; 560 if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { 561 listenTime = 0; 562 ah->stats.ast_ani_lzero++; 563 ath_print(common, ATH_DBG_ANI, 564 "1st call: aniState->cycleCount=%d\n", 565 aniState->cycleCount); 566 } else { 567 int32_t ccdelta = cycleCount - aniState->cycleCount; 568 int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; 569 int32_t tfdelta = txFrameCount - aniState->txFrameCount; 570 int32_t clock_rate; 571 572 /* 573 * convert HW counter values to ms using mode 574 * specifix clock rate 575 */ 576 clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; 577 578 listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate; 579 580 ath_print(common, ATH_DBG_ANI, 581 "cyclecount=%d, rfcount=%d, " 582 "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n", 583 ccdelta, rfdelta, tfdelta, listenTime, clock_rate); 584 } 585 586 aniState->cycleCount = cycleCount; 587 aniState->txFrameCount = txFrameCount; 588 aniState->rxFrameCount = rxFrameCount; 589 590 return listenTime; 591} 592 593static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) 594{ 595 struct ar5416AniState *aniState; 596 struct ath9k_channel *chan = ah->curchan; 597 struct ath_common *common = ath9k_hw_common(ah); 598 int index; 599 600 if (!DO_ANI(ah)) 601 return; 602 603 index = ath9k_hw_get_ani_channel_idx(ah, chan); 604 aniState = &ah->ani[index]; 605 ah->curani = aniState; 606 607 if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION 608 && ah->opmode != NL80211_IFTYPE_ADHOC) { 609 ath_print(common, ATH_DBG_ANI, 610 "Reset ANI state opmode %u\n", ah->opmode); 611 ah->stats.ast_ani_reset++; 612 613 if (ah->opmode == NL80211_IFTYPE_AP) { 614 /* 615 * ath9k_hw_ani_control() will only process items set on 616 * ah->ani_function 617 */ 618 if (IS_CHAN_2GHZ(chan)) 619 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | 620 ATH9K_ANI_FIRSTEP_LEVEL); 621 else 622 ah->ani_function = 0; 623 } 624 625 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0); 626 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); 627 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); 628 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, 629 !ATH9K_ANI_USE_OFDM_WEAK_SIG); 630 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, 631 ATH9K_ANI_CCK_WEAK_SIG_THR); 632 633 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | 634 ATH9K_RX_FILTER_PHYERR); 635 636 if (ah->opmode == NL80211_IFTYPE_AP) { 637 ah->curani->ofdmTrigHigh = 638 ah->config.ofdm_trig_high; 639 ah->curani->ofdmTrigLow = 640 ah->config.ofdm_trig_low; 641 ah->curani->cckTrigHigh = 642 ah->config.cck_trig_high; 643 ah->curani->cckTrigLow = 644 ah->config.cck_trig_low; 645 } 646 ath9k_ani_restart_old(ah); 647 return; 648 } 649 650 if (aniState->noiseImmunityLevel != 0) 651 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 652 aniState->noiseImmunityLevel); 653 if (aniState->spurImmunityLevel != 0) 654 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 655 aniState->spurImmunityLevel); 656 if (aniState->ofdmWeakSigDetectOff) 657 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, 658 !aniState->ofdmWeakSigDetectOff); 659 if (aniState->cckWeakSigThreshold) 660 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, 661 aniState->cckWeakSigThreshold); 662 if (aniState->firstepLevel != 0) 663 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 664 aniState->firstepLevel); 665 666 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & 667 ~ATH9K_RX_FILTER_PHYERR); 668 ath9k_ani_restart_old(ah); 669 670 ENABLE_REGWRITE_BUFFER(ah); 671 672 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 673 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 674 675 REGWRITE_BUFFER_FLUSH(ah); 676 DISABLE_REGWRITE_BUFFER(ah); 677} 678 679/* 680 * Restore the ANI parameters in the HAL and reset the statistics. 681 * This routine should be called for every hardware reset and for 682 * every channel change. 683 */ 684static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) 685{ 686 struct ar5416AniState *aniState = ah->curani; 687 struct ath9k_channel *chan = ah->curchan; 688 struct ath_common *common = ath9k_hw_common(ah); 689 690 if (!DO_ANI(ah)) 691 return; 692 693 BUG_ON(aniState == NULL); 694 ah->stats.ast_ani_reset++; 695 696 /* only allow a subset of functions in AP mode */ 697 if (ah->opmode == NL80211_IFTYPE_AP) { 698 if (IS_CHAN_2GHZ(chan)) { 699 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | 700 ATH9K_ANI_FIRSTEP_LEVEL); 701 if (AR_SREV_9300_20_OR_LATER(ah)) 702 ah->ani_function |= ATH9K_ANI_MRC_CCK; 703 } else 704 ah->ani_function = 0; 705 } 706 707 /* always allow mode (on/off) to be controlled */ 708 ah->ani_function |= ATH9K_ANI_MODE; 709 710 if (is_scanning || 711 (ah->opmode != NL80211_IFTYPE_STATION && 712 ah->opmode != NL80211_IFTYPE_ADHOC)) { 713 /* 714 * If we're scanning or in AP mode, the defaults (ini) 715 * should be in place. For an AP we assume the historical 716 * levels for this channel are probably outdated so start 717 * from defaults instead. 718 */ 719 if (aniState->ofdmNoiseImmunityLevel != 720 ATH9K_ANI_OFDM_DEF_LEVEL || 721 aniState->cckNoiseImmunityLevel != 722 ATH9K_ANI_CCK_DEF_LEVEL) { 723 ath_print(common, ATH_DBG_ANI, 724 "Restore defaults: opmode %u " 725 "chan %d Mhz/0x%x is_scanning=%d " 726 "ofdm:%d cck:%d\n", 727 ah->opmode, 728 chan->channel, 729 chan->channelFlags, 730 is_scanning, 731 aniState->ofdmNoiseImmunityLevel, 732 aniState->cckNoiseImmunityLevel); 733 734 ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); 735 ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); 736 } 737 } else { 738 /* 739 * restore historical levels for this channel 740 */ 741 ath_print(common, ATH_DBG_ANI, 742 "Restore history: opmode %u " 743 "chan %d Mhz/0x%x is_scanning=%d " 744 "ofdm:%d cck:%d\n", 745 ah->opmode, 746 chan->channel, 747 chan->channelFlags, 748 is_scanning, 749 aniState->ofdmNoiseImmunityLevel, 750 aniState->cckNoiseImmunityLevel); 751 752 ath9k_hw_set_ofdm_nil(ah, 753 aniState->ofdmNoiseImmunityLevel); 754 ath9k_hw_set_cck_nil(ah, 755 aniState->cckNoiseImmunityLevel); 756 } 757 758 /* 759 * enable phy counters if hw supports or if not, enable phy 760 * interrupts (so we can count each one) 761 */ 762 ath9k_ani_restart_new(ah); 763 764 ENABLE_REGWRITE_BUFFER(ah); 765 766 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 767 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 768 769 REGWRITE_BUFFER_FLUSH(ah); 770 DISABLE_REGWRITE_BUFFER(ah); 771} 772 773static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, 774 struct ath9k_channel *chan) 775{ 776 struct ar5416AniState *aniState; 777 struct ath_common *common = ath9k_hw_common(ah); 778 int32_t listenTime; 779 u32 phyCnt1, phyCnt2; 780 u32 ofdmPhyErrCnt, cckPhyErrCnt; 781 782 if (!DO_ANI(ah)) 783 return; 784 785 aniState = ah->curani; 786 787 listenTime = ath9k_hw_ani_get_listen_time(ah); 788 if (listenTime < 0) { 789 ah->stats.ast_ani_lneg++; 790 ath9k_ani_restart_old(ah); 791 return; 792 } 793 794 aniState->listenTime += listenTime; 795 796 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 797 798 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); 799 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); 800 801 if (phyCnt1 < aniState->ofdmPhyErrBase || 802 phyCnt2 < aniState->cckPhyErrBase) { 803 if (phyCnt1 < aniState->ofdmPhyErrBase) { 804 ath_print(common, ATH_DBG_ANI, 805 "phyCnt1 0x%x, resetting " 806 "counter value to 0x%x\n", 807 phyCnt1, 808 aniState->ofdmPhyErrBase); 809 REG_WRITE(ah, AR_PHY_ERR_1, 810 aniState->ofdmPhyErrBase); 811 REG_WRITE(ah, AR_PHY_ERR_MASK_1, 812 AR_PHY_ERR_OFDM_TIMING); 813 } 814 if (phyCnt2 < aniState->cckPhyErrBase) { 815 ath_print(common, ATH_DBG_ANI, 816 "phyCnt2 0x%x, resetting " 817 "counter value to 0x%x\n", 818 phyCnt2, 819 aniState->cckPhyErrBase); 820 REG_WRITE(ah, AR_PHY_ERR_2, 821 aniState->cckPhyErrBase); 822 REG_WRITE(ah, AR_PHY_ERR_MASK_2, 823 AR_PHY_ERR_CCK_TIMING); 824 } 825 return; 826 } 827 828 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; 829 ah->stats.ast_ani_ofdmerrs += 830 ofdmPhyErrCnt - aniState->ofdmPhyErrCount; 831 aniState->ofdmPhyErrCount = ofdmPhyErrCnt; 832 833 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; 834 ah->stats.ast_ani_cckerrs += 835 cckPhyErrCnt - aniState->cckPhyErrCount; 836 aniState->cckPhyErrCount = cckPhyErrCnt; 837 838 if (aniState->listenTime > 5 * ah->aniperiod) { 839 if (aniState->ofdmPhyErrCount <= aniState->listenTime * 840 aniState->ofdmTrigLow / 1000 && 841 aniState->cckPhyErrCount <= aniState->listenTime * 842 aniState->cckTrigLow / 1000) 843 ath9k_hw_ani_lower_immunity(ah); 844 ath9k_ani_restart_old(ah); 845 } else if (aniState->listenTime > ah->aniperiod) { 846 if (aniState->ofdmPhyErrCount > aniState->listenTime * 847 aniState->ofdmTrigHigh / 1000) { 848 ath9k_hw_ani_ofdm_err_trigger_old(ah); 849 ath9k_ani_restart_old(ah); 850 } else if (aniState->cckPhyErrCount > 851 aniState->listenTime * aniState->cckTrigHigh / 852 1000) { 853 ath9k_hw_ani_cck_err_trigger_old(ah); 854 ath9k_ani_restart_old(ah); 855 } 856 } 857} 858 859static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, 860 struct ath9k_channel *chan) 861{ 862 struct ar5416AniState *aniState; 863 struct ath_common *common = ath9k_hw_common(ah); 864 int32_t listenTime; 865 u32 phyCnt1, phyCnt2; 866 u32 ofdmPhyErrCnt, cckPhyErrCnt; 867 u32 ofdmPhyErrRate, cckPhyErrRate; 868 869 if (!DO_ANI(ah)) 870 return; 871 872 aniState = ah->curani; 873 if (WARN_ON(!aniState)) 874 return; 875 876 listenTime = ath9k_hw_ani_get_listen_time(ah); 877 if (listenTime <= 0) { 878 ah->stats.ast_ani_lneg++; 879 /* restart ANI period if listenTime is invalid */ 880 ath_print(common, ATH_DBG_ANI, 881 "listenTime=%d - on new ani monitor\n", 882 listenTime); 883 ath9k_ani_restart_new(ah); 884 return; 885 } 886 887 aniState->listenTime += listenTime; 888 889 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 890 891 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); 892 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); 893 894 if (phyCnt1 < aniState->ofdmPhyErrBase || 895 phyCnt2 < aniState->cckPhyErrBase) { 896 if (phyCnt1 < aniState->ofdmPhyErrBase) { 897 ath_print(common, ATH_DBG_ANI, 898 "phyCnt1 0x%x, resetting " 899 "counter value to 0x%x\n", 900 phyCnt1, 901 aniState->ofdmPhyErrBase); 902 REG_WRITE(ah, AR_PHY_ERR_1, 903 aniState->ofdmPhyErrBase); 904 REG_WRITE(ah, AR_PHY_ERR_MASK_1, 905 AR_PHY_ERR_OFDM_TIMING); 906 } 907 if (phyCnt2 < aniState->cckPhyErrBase) { 908 ath_print(common, ATH_DBG_ANI, 909 "phyCnt2 0x%x, resetting " 910 "counter value to 0x%x\n", 911 phyCnt2, 912 aniState->cckPhyErrBase); 913 REG_WRITE(ah, AR_PHY_ERR_2, 914 aniState->cckPhyErrBase); 915 REG_WRITE(ah, AR_PHY_ERR_MASK_2, 916 AR_PHY_ERR_CCK_TIMING); 917 } 918 return; 919 } 920 921 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; 922 ah->stats.ast_ani_ofdmerrs += 923 ofdmPhyErrCnt - aniState->ofdmPhyErrCount; 924 aniState->ofdmPhyErrCount = ofdmPhyErrCnt; 925 926 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; 927 ah->stats.ast_ani_cckerrs += 928 cckPhyErrCnt - aniState->cckPhyErrCount; 929 aniState->cckPhyErrCount = cckPhyErrCnt; 930 931 ath_print(common, ATH_DBG_ANI, 932 "Errors: OFDM=0x%08x-0x%08x=%d " 933 "CCK=0x%08x-0x%08x=%d\n", 934 phyCnt1, 935 aniState->ofdmPhyErrBase, 936 ofdmPhyErrCnt, 937 phyCnt2, 938 aniState->cckPhyErrBase, 939 cckPhyErrCnt); 940 941 ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / 942 aniState->listenTime; 943 cckPhyErrRate = aniState->cckPhyErrCount * 1000 / 944 aniState->listenTime; 945 946 ath_print(common, ATH_DBG_ANI, 947 "listenTime=%d OFDM:%d errs=%d/s CCK:%d " 948 "errs=%d/s ofdm_turn=%d\n", 949 listenTime, aniState->ofdmNoiseImmunityLevel, 950 ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, 951 cckPhyErrRate, aniState->ofdmsTurn); 952 953 if (aniState->listenTime > 5 * ah->aniperiod) { 954 if (ofdmPhyErrRate <= aniState->ofdmTrigLow && 955 cckPhyErrRate <= aniState->cckTrigLow) { 956 ath_print(common, ATH_DBG_ANI, 957 "1. listenTime=%d OFDM:%d errs=%d/s(<%d) " 958 "CCK:%d errs=%d/s(<%d) -> " 959 "ath9k_hw_ani_lower_immunity()\n", 960 aniState->listenTime, 961 aniState->ofdmNoiseImmunityLevel, 962 ofdmPhyErrRate, 963 aniState->ofdmTrigLow, 964 aniState->cckNoiseImmunityLevel, 965 cckPhyErrRate, 966 aniState->cckTrigLow); 967 ath9k_hw_ani_lower_immunity(ah); 968 aniState->ofdmsTurn = !aniState->ofdmsTurn; 969 } 970 ath_print(common, ATH_DBG_ANI, 971 "1 listenTime=%d ofdm=%d/s cck=%d/s - " 972 "calling ath9k_ani_restart_new()\n", 973 aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate); 974 ath9k_ani_restart_new(ah); 975 } else if (aniState->listenTime > ah->aniperiod) { 976 /* check to see if need to raise immunity */ 977 if (ofdmPhyErrRate > aniState->ofdmTrigHigh && 978 (cckPhyErrRate <= aniState->cckTrigHigh || 979 aniState->ofdmsTurn)) { 980 ath_print(common, ATH_DBG_ANI, 981 "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> " 982 "ath9k_hw_ani_ofdm_err_trigger_new()\n", 983 aniState->listenTime, 984 aniState->ofdmNoiseImmunityLevel, 985 ofdmPhyErrRate, 986 aniState->ofdmTrigHigh); 987 ath9k_hw_ani_ofdm_err_trigger_new(ah); 988 ath9k_ani_restart_new(ah); 989 aniState->ofdmsTurn = false; 990 } else if (cckPhyErrRate > aniState->cckTrigHigh) { 991 ath_print(common, ATH_DBG_ANI, 992 "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> " 993 "ath9k_hw_ani_cck_err_trigger_new()\n", 994 aniState->listenTime, 995 aniState->cckNoiseImmunityLevel, 996 cckPhyErrRate, 997 aniState->cckTrigHigh); 998 ath9k_hw_ani_cck_err_trigger_new(ah); 999 ath9k_ani_restart_new(ah); 1000 aniState->ofdmsTurn = true; 1001 } 1002 } 1003} 1004 1005void ath9k_enable_mib_counters(struct ath_hw *ah) 1006{ 1007 struct ath_common *common = ath9k_hw_common(ah); 1008 1009 ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n"); 1010 1011 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 1012 1013 ENABLE_REGWRITE_BUFFER(ah); 1014 1015 REG_WRITE(ah, AR_FILT_OFDM, 0); 1016 REG_WRITE(ah, AR_FILT_CCK, 0); 1017 REG_WRITE(ah, AR_MIBC, 1018 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) 1019 & 0x0f); 1020 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 1021 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 1022 1023 REGWRITE_BUFFER_FLUSH(ah); 1024 DISABLE_REGWRITE_BUFFER(ah); 1025} 1026 1027/* Freeze the MIB counters, get the stats and then clear them */ 1028void ath9k_hw_disable_mib_counters(struct ath_hw *ah) 1029{ 1030 struct ath_common *common = ath9k_hw_common(ah); 1031 1032 ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n"); 1033 1034 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); 1035 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 1036 REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC); 1037 REG_WRITE(ah, AR_FILT_OFDM, 0); 1038 REG_WRITE(ah, AR_FILT_CCK, 0); 1039} 1040EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); 1041 1042u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, 1043 u32 *rxc_pcnt, 1044 u32 *rxf_pcnt, 1045 u32 *txf_pcnt) 1046{ 1047 struct ath_common *common = ath9k_hw_common(ah); 1048 static u32 cycles, rx_clear, rx_frame, tx_frame; 1049 u32 good = 1; 1050 1051 u32 rc = REG_READ(ah, AR_RCCNT); 1052 u32 rf = REG_READ(ah, AR_RFCNT); 1053 u32 tf = REG_READ(ah, AR_TFCNT); 1054 u32 cc = REG_READ(ah, AR_CCCNT); 1055 1056 if (cycles == 0 || cycles > cc) { 1057 ath_print(common, ATH_DBG_ANI, 1058 "cycle counter wrap. ExtBusy = 0\n"); 1059 good = 0; 1060 } else { 1061 u32 cc_d = cc - cycles; 1062 u32 rc_d = rc - rx_clear; 1063 u32 rf_d = rf - rx_frame; 1064 u32 tf_d = tf - tx_frame; 1065 1066 if (cc_d != 0) { 1067 *rxc_pcnt = rc_d * 100 / cc_d; 1068 *rxf_pcnt = rf_d * 100 / cc_d; 1069 *txf_pcnt = tf_d * 100 / cc_d; 1070 } else { 1071 good = 0; 1072 } 1073 } 1074 1075 cycles = cc; 1076 rx_frame = rf; 1077 rx_clear = rc; 1078 tx_frame = tf; 1079 1080 return good; 1081} 1082 1083/* 1084 * Process a MIB interrupt. We may potentially be invoked because 1085 * any of the MIB counters overflow/trigger so don't assume we're 1086 * here because a PHY error counter triggered. 1087 */ 1088static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) 1089{ 1090 u32 phyCnt1, phyCnt2; 1091 1092 /* Reset these counters regardless */ 1093 REG_WRITE(ah, AR_FILT_OFDM, 0); 1094 REG_WRITE(ah, AR_FILT_CCK, 0); 1095 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) 1096 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); 1097 1098 /* Clear the mib counters and save them in the stats */ 1099 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 1100 1101 if (!DO_ANI(ah)) { 1102 /* 1103 * We must always clear the interrupt cause by 1104 * resetting the phy error regs. 1105 */ 1106 REG_WRITE(ah, AR_PHY_ERR_1, 0); 1107 REG_WRITE(ah, AR_PHY_ERR_2, 0); 1108 return; 1109 } 1110 1111 /* NB: these are not reset-on-read */ 1112 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); 1113 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); 1114 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || 1115 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { 1116 struct ar5416AniState *aniState = ah->curani; 1117 u32 ofdmPhyErrCnt, cckPhyErrCnt; 1118 1119 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ 1120 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; 1121 ah->stats.ast_ani_ofdmerrs += 1122 ofdmPhyErrCnt - aniState->ofdmPhyErrCount; 1123 aniState->ofdmPhyErrCount = ofdmPhyErrCnt; 1124 1125 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; 1126 ah->stats.ast_ani_cckerrs += 1127 cckPhyErrCnt - aniState->cckPhyErrCount; 1128 aniState->cckPhyErrCount = cckPhyErrCnt; 1129 1130 /* 1131 * NB: figure out which counter triggered. If both 1132 * trigger we'll only deal with one as the processing 1133 * clobbers the error counter so the trigger threshold 1134 * check will never be true. 1135 */ 1136 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) 1137 ath9k_hw_ani_ofdm_err_trigger_new(ah); 1138 if (aniState->cckPhyErrCount > aniState->cckTrigHigh) 1139 ath9k_hw_ani_cck_err_trigger_old(ah); 1140 /* NB: always restart to insure the h/w counters are reset */ 1141 ath9k_ani_restart_old(ah); 1142 } 1143} 1144 1145/* 1146 * Process a MIB interrupt. We may potentially be invoked because 1147 * any of the MIB counters overflow/trigger so don't assume we're 1148 * here because a PHY error counter triggered. 1149 */ 1150static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) 1151{ 1152 u32 phyCnt1, phyCnt2; 1153 1154 /* Reset these counters regardless */ 1155 REG_WRITE(ah, AR_FILT_OFDM, 0); 1156 REG_WRITE(ah, AR_FILT_CCK, 0); 1157 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) 1158 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); 1159 1160 /* Clear the mib counters and save them in the stats */ 1161 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 1162 1163 if (!DO_ANI(ah)) { 1164 /* 1165 * We must always clear the interrupt cause by 1166 * resetting the phy error regs. 1167 */ 1168 REG_WRITE(ah, AR_PHY_ERR_1, 0); 1169 REG_WRITE(ah, AR_PHY_ERR_2, 0); 1170 return; 1171 } 1172 1173 /* NB: these are not reset-on-read */ 1174 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); 1175 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); 1176 1177 /* NB: always restart to insure the h/w counters are reset */ 1178 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || 1179 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) 1180 ath9k_ani_restart_new(ah); 1181} 1182 1183void ath9k_hw_ani_setup(struct ath_hw *ah) 1184{ 1185 int i; 1186 1187 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; 1188 const int coarseHigh[] = { -14, -14, -14, -14, -12 }; 1189 const int coarseLow[] = { -64, -64, -64, -64, -70 }; 1190 const int firpwr[] = { -78, -78, -78, -78, -80 }; 1191 1192 for (i = 0; i < 5; i++) { 1193 ah->totalSizeDesired[i] = totalSizeDesired[i]; 1194 ah->coarse_high[i] = coarseHigh[i]; 1195 ah->coarse_low[i] = coarseLow[i]; 1196 ah->firpwr[i] = firpwr[i]; 1197 } 1198} 1199 1200void ath9k_hw_ani_init(struct ath_hw *ah) 1201{ 1202 struct ath_common *common = ath9k_hw_common(ah); 1203 int i; 1204 1205 ath_print(common, ATH_DBG_ANI, "Initialize ANI\n"); 1206 1207 memset(ah->ani, 0, sizeof(ah->ani)); 1208 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { 1209 if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { 1210 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; 1211 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW; 1212 1213 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW; 1214 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW; 1215 1216 ah->ani[i].spurImmunityLevel = 1217 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; 1218 1219 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; 1220 1221 ah->ani[i].ofdmPhyErrBase = 0; 1222 ah->ani[i].cckPhyErrBase = 0; 1223 1224 if (AR_SREV_9300_20_OR_LATER(ah)) 1225 ah->ani[i].mrcCCKOff = 1226 !ATH9K_ANI_ENABLE_MRC_CCK; 1227 else 1228 ah->ani[i].mrcCCKOff = true; 1229 1230 ah->ani[i].ofdmsTurn = true; 1231 } else { 1232 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; 1233 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD; 1234 1235 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD; 1236 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD; 1237 1238 ah->ani[i].spurImmunityLevel = 1239 ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; 1240 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; 1241 1242 ah->ani[i].ofdmPhyErrBase = 1243 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD; 1244 ah->ani[i].cckPhyErrBase = 1245 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD; 1246 ah->ani[i].cckWeakSigThreshold = 1247 ATH9K_ANI_CCK_WEAK_SIG_THR; 1248 } 1249 1250 ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; 1251 ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; 1252 ah->ani[i].ofdmWeakSigDetectOff = 1253 !ATH9K_ANI_USE_OFDM_WEAK_SIG; 1254 ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; 1255 } 1256 1257 /* 1258 * since we expect some ongoing maintenance on the tables, let's sanity 1259 * check here default level should not modify INI setting. 1260 */ 1261 if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { 1262 const struct ani_ofdm_level_entry *entry_ofdm; 1263 const struct ani_cck_level_entry *entry_cck; 1264 1265 entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; 1266 entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; 1267 1268 ah->aniperiod = ATH9K_ANI_PERIOD_NEW; 1269 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; 1270 } else { 1271 ah->aniperiod = ATH9K_ANI_PERIOD_OLD; 1272 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; 1273 } 1274 1275 ath_print(common, ATH_DBG_ANI, 1276 "Setting OfdmErrBase = 0x%08x\n", 1277 ah->ani[0].ofdmPhyErrBase); 1278 ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", 1279 ah->ani[0].cckPhyErrBase); 1280 1281 ENABLE_REGWRITE_BUFFER(ah); 1282 1283 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); 1284 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); 1285 1286 REGWRITE_BUFFER_FLUSH(ah); 1287 DISABLE_REGWRITE_BUFFER(ah); 1288 1289 ath9k_enable_mib_counters(ah); 1290 1291 if (ah->config.enable_ani) 1292 ah->proc_phyerr |= HAL_PROCESS_ANI; 1293} 1294 1295void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah) 1296{ 1297 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 1298 struct ath_hw_ops *ops = ath9k_hw_ops(ah); 1299 1300 priv_ops->ani_reset = ath9k_ani_reset_old; 1301 priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old; 1302 1303 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old; 1304 ops->ani_monitor = ath9k_hw_ani_monitor_old; 1305 1306 ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n"); 1307} 1308 1309void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah) 1310{ 1311 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 1312 struct ath_hw_ops *ops = ath9k_hw_ops(ah); 1313 1314 priv_ops->ani_reset = ath9k_ani_reset_new; 1315 priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new; 1316 1317 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new; 1318 ops->ani_monitor = ath9k_hw_ani_monitor_new; 1319 1320 ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n"); 1321} 1322