diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ani.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ani.c | 655 |
1 files changed, 169 insertions, 486 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 0496f965314f..f2a907b4acb8 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -103,31 +103,9 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
103 | #define ATH9K_ANI_CCK_DEF_LEVEL \ | 103 | #define ATH9K_ANI_CCK_DEF_LEVEL \ |
104 | 2 /* default level - matches the INI settings */ | 104 | 2 /* default level - matches the INI settings */ |
105 | 105 | ||
106 | /* Private to ani.c */ | 106 | static bool use_new_ani(struct ath_hw *ah) |
107 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | ||
108 | { | ||
109 | ath9k_hw_private_ops(ah)->ani_lower_immunity(ah); | ||
110 | } | ||
111 | |||
112 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | ||
113 | struct ath9k_channel *chan) | ||
114 | { | 107 | { |
115 | int i; | 108 | return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani; |
116 | |||
117 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | ||
118 | if (ah->ani[i].c && | ||
119 | ah->ani[i].c->channel == chan->channel) | ||
120 | return i; | ||
121 | if (ah->ani[i].c == NULL) { | ||
122 | ah->ani[i].c = chan; | ||
123 | return i; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, | ||
128 | "No more channel states left. Using channel 0\n"); | ||
129 | |||
130 | return 0; | ||
131 | } | 109 | } |
132 | 110 | ||
133 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, | 111 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, |
@@ -140,82 +118,34 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, | |||
140 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); | 118 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); |
141 | } | 119 | } |
142 | 120 | ||
143 | static void ath9k_ani_restart_old(struct ath_hw *ah) | 121 | static void ath9k_ani_restart(struct ath_hw *ah) |
144 | { | 122 | { |
145 | struct ar5416AniState *aniState; | 123 | struct ar5416AniState *aniState; |
146 | struct ath_common *common = ath9k_hw_common(ah); | 124 | struct ath_common *common = ath9k_hw_common(ah); |
125 | u32 ofdm_base = 0, cck_base = 0; | ||
147 | 126 | ||
148 | if (!DO_ANI(ah)) | 127 | if (!DO_ANI(ah)) |
149 | return; | 128 | return; |
150 | 129 | ||
151 | aniState = ah->curani; | 130 | aniState = &ah->curchan->ani; |
152 | aniState->listenTime = 0; | 131 | aniState->listenTime = 0; |
153 | 132 | ||
154 | if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { | 133 | if (!use_new_ani(ah)) { |
155 | aniState->ofdmPhyErrBase = 0; | 134 | ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high; |
156 | ath_print(common, ATH_DBG_ANI, | 135 | cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; |
157 | "OFDM Trigger is too high for hw counters\n"); | ||
158 | } else { | ||
159 | aniState->ofdmPhyErrBase = | ||
160 | AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; | ||
161 | } | 136 | } |
162 | if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { | ||
163 | aniState->cckPhyErrBase = 0; | ||
164 | ath_print(common, ATH_DBG_ANI, | ||
165 | "CCK Trigger is too high for hw counters\n"); | ||
166 | } else { | ||
167 | aniState->cckPhyErrBase = | ||
168 | AR_PHY_COUNTMAX - aniState->cckTrigHigh; | ||
169 | } | ||
170 | ath_print(common, ATH_DBG_ANI, | ||
171 | "Writing ofdmbase=%u cckbase=%u\n", | ||
172 | aniState->ofdmPhyErrBase, | ||
173 | aniState->cckPhyErrBase); | ||
174 | |||
175 | ENABLE_REGWRITE_BUFFER(ah); | ||
176 | |||
177 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | ||
178 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | ||
179 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
180 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
181 | |||
182 | REGWRITE_BUFFER_FLUSH(ah); | ||
183 | DISABLE_REGWRITE_BUFFER(ah); | ||
184 | |||
185 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
186 | |||
187 | aniState->ofdmPhyErrCount = 0; | ||
188 | aniState->cckPhyErrCount = 0; | ||
189 | } | ||
190 | |||
191 | static void ath9k_ani_restart_new(struct ath_hw *ah) | ||
192 | { | ||
193 | struct ar5416AniState *aniState; | ||
194 | struct ath_common *common = ath9k_hw_common(ah); | ||
195 | |||
196 | if (!DO_ANI(ah)) | ||
197 | return; | ||
198 | |||
199 | aniState = ah->curani; | ||
200 | aniState->listenTime = 0; | ||
201 | |||
202 | aniState->ofdmPhyErrBase = 0; | ||
203 | aniState->cckPhyErrBase = 0; | ||
204 | 137 | ||
205 | ath_print(common, ATH_DBG_ANI, | 138 | ath_print(common, ATH_DBG_ANI, |
206 | "Writing ofdmbase=%08x cckbase=%08x\n", | 139 | "Writing ofdmbase=%u cckbase=%u\n", ofdm_base, cck_base); |
207 | aniState->ofdmPhyErrBase, | ||
208 | aniState->cckPhyErrBase); | ||
209 | 140 | ||
210 | ENABLE_REGWRITE_BUFFER(ah); | 141 | ENABLE_REGWRITE_BUFFER(ah); |
211 | 142 | ||
212 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | 143 | REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); |
213 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | 144 | REG_WRITE(ah, AR_PHY_ERR_2, cck_base); |
214 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | 145 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); |
215 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 146 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
216 | 147 | ||
217 | REGWRITE_BUFFER_FLUSH(ah); | 148 | REGWRITE_BUFFER_FLUSH(ah); |
218 | DISABLE_REGWRITE_BUFFER(ah); | ||
219 | 149 | ||
220 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 150 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
221 | 151 | ||
@@ -229,10 +159,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah) | |||
229 | struct ar5416AniState *aniState; | 159 | struct ar5416AniState *aniState; |
230 | int32_t rssi; | 160 | int32_t rssi; |
231 | 161 | ||
232 | if (!DO_ANI(ah)) | 162 | aniState = &ah->curchan->ani; |
233 | return; | ||
234 | |||
235 | aniState = ah->curani; | ||
236 | 163 | ||
237 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | 164 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { |
238 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | 165 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, |
@@ -301,10 +228,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) | |||
301 | struct ar5416AniState *aniState; | 228 | struct ar5416AniState *aniState; |
302 | int32_t rssi; | 229 | int32_t rssi; |
303 | 230 | ||
304 | if (!DO_ANI(ah)) | 231 | aniState = &ah->curchan->ani; |
305 | return; | ||
306 | |||
307 | aniState = ah->curani; | ||
308 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | 232 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { |
309 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | 233 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, |
310 | aniState->noiseImmunityLevel + 1)) { | 234 | aniState->noiseImmunityLevel + 1)) { |
@@ -336,7 +260,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) | |||
336 | /* Adjust the OFDM Noise Immunity Level */ | 260 | /* Adjust the OFDM Noise Immunity Level */ |
337 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | 261 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) |
338 | { | 262 | { |
339 | struct ar5416AniState *aniState = ah->curani; | 263 | struct ar5416AniState *aniState = &ah->curchan->ani; |
340 | struct ath_common *common = ath9k_hw_common(ah); | 264 | struct ath_common *common = ath9k_hw_common(ah); |
341 | const struct ani_ofdm_level_entry *entry_ofdm; | 265 | const struct ani_ofdm_level_entry *entry_ofdm; |
342 | const struct ani_cck_level_entry *entry_cck; | 266 | const struct ani_cck_level_entry *entry_cck; |
@@ -381,14 +305,19 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | |||
381 | } | 305 | } |
382 | } | 306 | } |
383 | 307 | ||
384 | static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) | 308 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) |
385 | { | 309 | { |
386 | struct ar5416AniState *aniState; | 310 | struct ar5416AniState *aniState; |
387 | 311 | ||
388 | if (!DO_ANI(ah)) | 312 | if (!DO_ANI(ah)) |
389 | return; | 313 | return; |
390 | 314 | ||
391 | aniState = ah->curani; | 315 | if (!use_new_ani(ah)) { |
316 | ath9k_hw_ani_ofdm_err_trigger_old(ah); | ||
317 | return; | ||
318 | } | ||
319 | |||
320 | aniState = &ah->curchan->ani; | ||
392 | 321 | ||
393 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) | 322 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) |
394 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); | 323 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); |
@@ -399,7 +328,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) | |||
399 | */ | 328 | */ |
400 | static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | 329 | static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) |
401 | { | 330 | { |
402 | struct ar5416AniState *aniState = ah->curani; | 331 | struct ar5416AniState *aniState = &ah->curchan->ani; |
403 | struct ath_common *common = ath9k_hw_common(ah); | 332 | struct ath_common *common = ath9k_hw_common(ah); |
404 | const struct ani_ofdm_level_entry *entry_ofdm; | 333 | const struct ani_ofdm_level_entry *entry_ofdm; |
405 | const struct ani_cck_level_entry *entry_cck; | 334 | const struct ani_cck_level_entry *entry_cck; |
@@ -438,14 +367,19 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | |||
438 | entry_cck->mrc_cck_on); | 367 | entry_cck->mrc_cck_on); |
439 | } | 368 | } |
440 | 369 | ||
441 | static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah) | 370 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) |
442 | { | 371 | { |
443 | struct ar5416AniState *aniState; | 372 | struct ar5416AniState *aniState; |
444 | 373 | ||
445 | if (!DO_ANI(ah)) | 374 | if (!DO_ANI(ah)) |
446 | return; | 375 | return; |
447 | 376 | ||
448 | aniState = ah->curani; | 377 | if (!use_new_ani(ah)) { |
378 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | aniState = &ah->curchan->ani; | ||
449 | 383 | ||
450 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) | 384 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) |
451 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); | 385 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); |
@@ -456,7 +390,7 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | |||
456 | struct ar5416AniState *aniState; | 390 | struct ar5416AniState *aniState; |
457 | int32_t rssi; | 391 | int32_t rssi; |
458 | 392 | ||
459 | aniState = ah->curani; | 393 | aniState = &ah->curchan->ani; |
460 | 394 | ||
461 | if (ah->opmode == NL80211_IFTYPE_AP) { | 395 | if (ah->opmode == NL80211_IFTYPE_AP) { |
462 | if (aniState->firstepLevel > 0) { | 396 | if (aniState->firstepLevel > 0) { |
@@ -508,11 +442,16 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | |||
508 | * only lower either OFDM or CCK errors per turn | 442 | * only lower either OFDM or CCK errors per turn |
509 | * we lower the other one next time | 443 | * we lower the other one next time |
510 | */ | 444 | */ |
511 | static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah) | 445 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) |
512 | { | 446 | { |
513 | struct ar5416AniState *aniState; | 447 | struct ar5416AniState *aniState; |
514 | 448 | ||
515 | aniState = ah->curani; | 449 | aniState = &ah->curchan->ani; |
450 | |||
451 | if (!use_new_ani(ah)) { | ||
452 | ath9k_hw_ani_lower_immunity_old(ah); | ||
453 | return; | ||
454 | } | ||
516 | 455 | ||
517 | /* lower OFDM noise immunity */ | 456 | /* lower OFDM noise immunity */ |
518 | if (aniState->ofdmNoiseImmunityLevel > 0 && | 457 | if (aniState->ofdmNoiseImmunityLevel > 0 && |
@@ -544,52 +483,20 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) | |||
544 | if (conf_is_ht40(conf)) | 483 | if (conf_is_ht40(conf)) |
545 | return clockrate * 2; | 484 | return clockrate * 2; |
546 | 485 | ||
547 | return clockrate * 2; | 486 | return clockrate; |
548 | } | 487 | } |
549 | 488 | ||
550 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | 489 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) |
551 | { | 490 | { |
552 | struct ar5416AniState *aniState; | 491 | int32_t listen_time; |
553 | struct ath_common *common = ath9k_hw_common(ah); | 492 | int32_t clock_rate; |
554 | u32 txFrameCount, rxFrameCount, cycleCount; | ||
555 | int32_t listenTime; | ||
556 | |||
557 | txFrameCount = REG_READ(ah, AR_TFCNT); | ||
558 | rxFrameCount = REG_READ(ah, AR_RFCNT); | ||
559 | cycleCount = REG_READ(ah, AR_CCCNT); | ||
560 | |||
561 | aniState = ah->curani; | ||
562 | if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { | ||
563 | listenTime = 0; | ||
564 | ah->stats.ast_ani_lzero++; | ||
565 | ath_print(common, ATH_DBG_ANI, | ||
566 | "1st call: aniState->cycleCount=%d\n", | ||
567 | aniState->cycleCount); | ||
568 | } else { | ||
569 | int32_t ccdelta = cycleCount - aniState->cycleCount; | ||
570 | int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; | ||
571 | int32_t tfdelta = txFrameCount - aniState->txFrameCount; | ||
572 | int32_t clock_rate; | ||
573 | 493 | ||
574 | /* | 494 | ath9k_hw_update_cycle_counters(ah); |
575 | * convert HW counter values to ms using mode | 495 | clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000; |
576 | * specifix clock rate | 496 | listen_time = ah->listen_time / clock_rate; |
577 | */ | 497 | ah->listen_time = 0; |
578 | clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; | ||
579 | 498 | ||
580 | listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate; | 499 | return listen_time; |
581 | |||
582 | ath_print(common, ATH_DBG_ANI, | ||
583 | "cyclecount=%d, rfcount=%d, " | ||
584 | "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n", | ||
585 | ccdelta, rfdelta, tfdelta, listenTime, clock_rate); | ||
586 | } | ||
587 | |||
588 | aniState->cycleCount = cycleCount; | ||
589 | aniState->txFrameCount = txFrameCount; | ||
590 | aniState->rxFrameCount = rxFrameCount; | ||
591 | |||
592 | return listenTime; | ||
593 | } | 500 | } |
594 | 501 | ||
595 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | 502 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) |
@@ -597,16 +504,13 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
597 | struct ar5416AniState *aniState; | 504 | struct ar5416AniState *aniState; |
598 | struct ath9k_channel *chan = ah->curchan; | 505 | struct ath9k_channel *chan = ah->curchan; |
599 | struct ath_common *common = ath9k_hw_common(ah); | 506 | struct ath_common *common = ath9k_hw_common(ah); |
600 | int index; | ||
601 | 507 | ||
602 | if (!DO_ANI(ah)) | 508 | if (!DO_ANI(ah)) |
603 | return; | 509 | return; |
604 | 510 | ||
605 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | 511 | aniState = &ah->curchan->ani; |
606 | aniState = &ah->ani[index]; | ||
607 | ah->curani = aniState; | ||
608 | 512 | ||
609 | if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION | 513 | if (ah->opmode != NL80211_IFTYPE_STATION |
610 | && ah->opmode != NL80211_IFTYPE_ADHOC) { | 514 | && ah->opmode != NL80211_IFTYPE_ADHOC) { |
611 | ath_print(common, ATH_DBG_ANI, | 515 | ath_print(common, ATH_DBG_ANI, |
612 | "Reset ANI state opmode %u\n", ah->opmode); | 516 | "Reset ANI state opmode %u\n", ah->opmode); |
@@ -635,17 +539,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
635 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | | 539 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | |
636 | ATH9K_RX_FILTER_PHYERR); | 540 | ATH9K_RX_FILTER_PHYERR); |
637 | 541 | ||
638 | if (ah->opmode == NL80211_IFTYPE_AP) { | 542 | ath9k_ani_restart(ah); |
639 | ah->curani->ofdmTrigHigh = | ||
640 | ah->config.ofdm_trig_high; | ||
641 | ah->curani->ofdmTrigLow = | ||
642 | ah->config.ofdm_trig_low; | ||
643 | ah->curani->cckTrigHigh = | ||
644 | ah->config.cck_trig_high; | ||
645 | ah->curani->cckTrigLow = | ||
646 | ah->config.cck_trig_low; | ||
647 | } | ||
648 | ath9k_ani_restart_old(ah); | ||
649 | return; | 543 | return; |
650 | } | 544 | } |
651 | 545 | ||
@@ -667,7 +561,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
667 | 561 | ||
668 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & | 562 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & |
669 | ~ATH9K_RX_FILTER_PHYERR); | 563 | ~ATH9K_RX_FILTER_PHYERR); |
670 | ath9k_ani_restart_old(ah); | 564 | ath9k_ani_restart(ah); |
671 | 565 | ||
672 | ENABLE_REGWRITE_BUFFER(ah); | 566 | ENABLE_REGWRITE_BUFFER(ah); |
673 | 567 | ||
@@ -675,7 +569,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
675 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 569 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
676 | 570 | ||
677 | REGWRITE_BUFFER_FLUSH(ah); | 571 | REGWRITE_BUFFER_FLUSH(ah); |
678 | DISABLE_REGWRITE_BUFFER(ah); | ||
679 | } | 572 | } |
680 | 573 | ||
681 | /* | 574 | /* |
@@ -683,15 +576,18 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
683 | * This routine should be called for every hardware reset and for | 576 | * This routine should be called for every hardware reset and for |
684 | * every channel change. | 577 | * every channel change. |
685 | */ | 578 | */ |
686 | static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | 579 | void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) |
687 | { | 580 | { |
688 | struct ar5416AniState *aniState = ah->curani; | 581 | struct ar5416AniState *aniState = &ah->curchan->ani; |
689 | struct ath9k_channel *chan = ah->curchan; | 582 | struct ath9k_channel *chan = ah->curchan; |
690 | struct ath_common *common = ath9k_hw_common(ah); | 583 | struct ath_common *common = ath9k_hw_common(ah); |
691 | 584 | ||
692 | if (!DO_ANI(ah)) | 585 | if (!DO_ANI(ah)) |
693 | return; | 586 | return; |
694 | 587 | ||
588 | if (!use_new_ani(ah)) | ||
589 | return ath9k_ani_reset_old(ah, is_scanning); | ||
590 | |||
695 | BUG_ON(aniState == NULL); | 591 | BUG_ON(aniState == NULL); |
696 | ah->stats.ast_ani_reset++; | 592 | ah->stats.ast_ani_reset++; |
697 | 593 | ||
@@ -761,7 +657,7 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | |||
761 | * enable phy counters if hw supports or if not, enable phy | 657 | * enable phy counters if hw supports or if not, enable phy |
762 | * interrupts (so we can count each one) | 658 | * interrupts (so we can count each one) |
763 | */ | 659 | */ |
764 | ath9k_ani_restart_new(ah); | 660 | ath9k_ani_restart(ah); |
765 | 661 | ||
766 | ENABLE_REGWRITE_BUFFER(ah); | 662 | ENABLE_REGWRITE_BUFFER(ah); |
767 | 663 | ||
@@ -769,30 +665,30 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | |||
769 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 665 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
770 | 666 | ||
771 | REGWRITE_BUFFER_FLUSH(ah); | 667 | REGWRITE_BUFFER_FLUSH(ah); |
772 | DISABLE_REGWRITE_BUFFER(ah); | ||
773 | } | 668 | } |
774 | 669 | ||
775 | static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, | 670 | static void ath9k_hw_ani_read_counters(struct ath_hw *ah) |
776 | struct ath9k_channel *chan) | ||
777 | { | 671 | { |
778 | struct ar5416AniState *aniState; | ||
779 | struct ath_common *common = ath9k_hw_common(ah); | 672 | struct ath_common *common = ath9k_hw_common(ah); |
780 | int32_t listenTime; | 673 | struct ar5416AniState *aniState = &ah->curchan->ani; |
781 | u32 phyCnt1, phyCnt2; | 674 | u32 ofdm_base = 0; |
675 | u32 cck_base = 0; | ||
782 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | 676 | u32 ofdmPhyErrCnt, cckPhyErrCnt; |
783 | 677 | u32 phyCnt1, phyCnt2; | |
784 | if (!DO_ANI(ah)) | 678 | int32_t listenTime; |
785 | return; | ||
786 | |||
787 | aniState = ah->curani; | ||
788 | 679 | ||
789 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 680 | listenTime = ath9k_hw_ani_get_listen_time(ah); |
790 | if (listenTime < 0) { | 681 | if (listenTime < 0) { |
791 | ah->stats.ast_ani_lneg++; | 682 | ah->stats.ast_ani_lneg++; |
792 | ath9k_ani_restart_old(ah); | 683 | ath9k_ani_restart(ah); |
793 | return; | 684 | return; |
794 | } | 685 | } |
795 | 686 | ||
687 | if (!use_new_ani(ah)) { | ||
688 | ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high; | ||
689 | cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; | ||
690 | } | ||
691 | |||
796 | aniState->listenTime += listenTime; | 692 | aniState->listenTime += listenTime; |
797 | 693 | ||
798 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 694 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
@@ -800,145 +696,54 @@ static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, | |||
800 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 696 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
801 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 697 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); |
802 | 698 | ||
803 | if (phyCnt1 < aniState->ofdmPhyErrBase || | 699 | if (use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) { |
804 | phyCnt2 < aniState->cckPhyErrBase) { | 700 | if (phyCnt1 < ofdm_base) { |
805 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | ||
806 | ath_print(common, ATH_DBG_ANI, | 701 | ath_print(common, ATH_DBG_ANI, |
807 | "phyCnt1 0x%x, resetting " | 702 | "phyCnt1 0x%x, resetting " |
808 | "counter value to 0x%x\n", | 703 | "counter value to 0x%x\n", |
809 | phyCnt1, | 704 | phyCnt1, ofdm_base); |
810 | aniState->ofdmPhyErrBase); | 705 | REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); |
811 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
812 | aniState->ofdmPhyErrBase); | ||
813 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | 706 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, |
814 | AR_PHY_ERR_OFDM_TIMING); | 707 | AR_PHY_ERR_OFDM_TIMING); |
815 | } | 708 | } |
816 | if (phyCnt2 < aniState->cckPhyErrBase) { | 709 | if (phyCnt2 < cck_base) { |
817 | ath_print(common, ATH_DBG_ANI, | 710 | ath_print(common, ATH_DBG_ANI, |
818 | "phyCnt2 0x%x, resetting " | 711 | "phyCnt2 0x%x, resetting " |
819 | "counter value to 0x%x\n", | 712 | "counter value to 0x%x\n", |
820 | phyCnt2, | 713 | phyCnt2, cck_base); |
821 | aniState->cckPhyErrBase); | 714 | REG_WRITE(ah, AR_PHY_ERR_2, cck_base); |
822 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
823 | aniState->cckPhyErrBase); | ||
824 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | 715 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, |
825 | AR_PHY_ERR_CCK_TIMING); | 716 | AR_PHY_ERR_CCK_TIMING); |
826 | } | 717 | } |
827 | return; | 718 | return; |
828 | } | 719 | } |
829 | 720 | ||
830 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | 721 | ofdmPhyErrCnt = phyCnt1 - ofdm_base; |
831 | ah->stats.ast_ani_ofdmerrs += | 722 | ah->stats.ast_ani_ofdmerrs += |
832 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | 723 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; |
833 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | 724 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; |
834 | 725 | ||
835 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | 726 | cckPhyErrCnt = phyCnt2 - cck_base; |
836 | ah->stats.ast_ani_cckerrs += | 727 | ah->stats.ast_ani_cckerrs += |
837 | cckPhyErrCnt - aniState->cckPhyErrCount; | 728 | cckPhyErrCnt - aniState->cckPhyErrCount; |
838 | aniState->cckPhyErrCount = cckPhyErrCnt; | 729 | aniState->cckPhyErrCount = cckPhyErrCnt; |
839 | 730 | ||
840 | if (aniState->listenTime > 5 * ah->aniperiod) { | ||
841 | if (aniState->ofdmPhyErrCount <= aniState->listenTime * | ||
842 | aniState->ofdmTrigLow / 1000 && | ||
843 | aniState->cckPhyErrCount <= aniState->listenTime * | ||
844 | aniState->cckTrigLow / 1000) | ||
845 | ath9k_hw_ani_lower_immunity(ah); | ||
846 | ath9k_ani_restart_old(ah); | ||
847 | } else if (aniState->listenTime > ah->aniperiod) { | ||
848 | if (aniState->ofdmPhyErrCount > aniState->listenTime * | ||
849 | aniState->ofdmTrigHigh / 1000) { | ||
850 | ath9k_hw_ani_ofdm_err_trigger_old(ah); | ||
851 | ath9k_ani_restart_old(ah); | ||
852 | } else if (aniState->cckPhyErrCount > | ||
853 | aniState->listenTime * aniState->cckTrigHigh / | ||
854 | 1000) { | ||
855 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
856 | ath9k_ani_restart_old(ah); | ||
857 | } | ||
858 | } | ||
859 | } | 731 | } |
860 | 732 | ||
861 | static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, | 733 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) |
862 | struct ath9k_channel *chan) | ||
863 | { | 734 | { |
864 | struct ar5416AniState *aniState; | 735 | struct ar5416AniState *aniState; |
865 | struct ath_common *common = ath9k_hw_common(ah); | 736 | struct ath_common *common = ath9k_hw_common(ah); |
866 | int32_t listenTime; | ||
867 | u32 phyCnt1, phyCnt2; | ||
868 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
869 | u32 ofdmPhyErrRate, cckPhyErrRate; | 737 | u32 ofdmPhyErrRate, cckPhyErrRate; |
870 | 738 | ||
871 | if (!DO_ANI(ah)) | 739 | if (!DO_ANI(ah)) |
872 | return; | 740 | return; |
873 | 741 | ||
874 | aniState = ah->curani; | 742 | aniState = &ah->curchan->ani; |
875 | if (WARN_ON(!aniState)) | 743 | if (WARN_ON(!aniState)) |
876 | return; | 744 | return; |
877 | 745 | ||
878 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 746 | ath9k_hw_ani_read_counters(ah); |
879 | if (listenTime <= 0) { | ||
880 | ah->stats.ast_ani_lneg++; | ||
881 | /* restart ANI period if listenTime is invalid */ | ||
882 | ath_print(common, ATH_DBG_ANI, | ||
883 | "listenTime=%d - on new ani monitor\n", | ||
884 | listenTime); | ||
885 | ath9k_ani_restart_new(ah); | ||
886 | return; | ||
887 | } | ||
888 | |||
889 | aniState->listenTime += listenTime; | ||
890 | |||
891 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
892 | |||
893 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
894 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
895 | |||
896 | if (phyCnt1 < aniState->ofdmPhyErrBase || | ||
897 | phyCnt2 < aniState->cckPhyErrBase) { | ||
898 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | ||
899 | ath_print(common, ATH_DBG_ANI, | ||
900 | "phyCnt1 0x%x, resetting " | ||
901 | "counter value to 0x%x\n", | ||
902 | phyCnt1, | ||
903 | aniState->ofdmPhyErrBase); | ||
904 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
905 | aniState->ofdmPhyErrBase); | ||
906 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | ||
907 | AR_PHY_ERR_OFDM_TIMING); | ||
908 | } | ||
909 | if (phyCnt2 < aniState->cckPhyErrBase) { | ||
910 | ath_print(common, ATH_DBG_ANI, | ||
911 | "phyCnt2 0x%x, resetting " | ||
912 | "counter value to 0x%x\n", | ||
913 | phyCnt2, | ||
914 | aniState->cckPhyErrBase); | ||
915 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
916 | aniState->cckPhyErrBase); | ||
917 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | ||
918 | AR_PHY_ERR_CCK_TIMING); | ||
919 | } | ||
920 | return; | ||
921 | } | ||
922 | |||
923 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
924 | ah->stats.ast_ani_ofdmerrs += | ||
925 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
926 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
927 | |||
928 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
929 | ah->stats.ast_ani_cckerrs += | ||
930 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
931 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
932 | |||
933 | ath_print(common, ATH_DBG_ANI, | ||
934 | "Errors: OFDM=0x%08x-0x%08x=%d " | ||
935 | "CCK=0x%08x-0x%08x=%d\n", | ||
936 | phyCnt1, | ||
937 | aniState->ofdmPhyErrBase, | ||
938 | ofdmPhyErrCnt, | ||
939 | phyCnt2, | ||
940 | aniState->cckPhyErrBase, | ||
941 | cckPhyErrCnt); | ||
942 | 747 | ||
943 | ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / | 748 | ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / |
944 | aniState->listenTime; | 749 | aniState->listenTime; |
@@ -948,61 +753,34 @@ static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, | |||
948 | ath_print(common, ATH_DBG_ANI, | 753 | ath_print(common, ATH_DBG_ANI, |
949 | "listenTime=%d OFDM:%d errs=%d/s CCK:%d " | 754 | "listenTime=%d OFDM:%d errs=%d/s CCK:%d " |
950 | "errs=%d/s ofdm_turn=%d\n", | 755 | "errs=%d/s ofdm_turn=%d\n", |
951 | listenTime, aniState->ofdmNoiseImmunityLevel, | 756 | aniState->listenTime, |
757 | aniState->ofdmNoiseImmunityLevel, | ||
952 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, | 758 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, |
953 | cckPhyErrRate, aniState->ofdmsTurn); | 759 | cckPhyErrRate, aniState->ofdmsTurn); |
954 | 760 | ||
955 | if (aniState->listenTime > 5 * ah->aniperiod) { | 761 | if (aniState->listenTime > 5 * ah->aniperiod) { |
956 | if (ofdmPhyErrRate <= aniState->ofdmTrigLow && | 762 | if (ofdmPhyErrRate <= ah->config.ofdm_trig_low && |
957 | cckPhyErrRate <= aniState->cckTrigLow) { | 763 | cckPhyErrRate <= ah->config.cck_trig_low) { |
958 | ath_print(common, ATH_DBG_ANI, | ||
959 | "1. listenTime=%d OFDM:%d errs=%d/s(<%d) " | ||
960 | "CCK:%d errs=%d/s(<%d) -> " | ||
961 | "ath9k_hw_ani_lower_immunity()\n", | ||
962 | aniState->listenTime, | ||
963 | aniState->ofdmNoiseImmunityLevel, | ||
964 | ofdmPhyErrRate, | ||
965 | aniState->ofdmTrigLow, | ||
966 | aniState->cckNoiseImmunityLevel, | ||
967 | cckPhyErrRate, | ||
968 | aniState->cckTrigLow); | ||
969 | ath9k_hw_ani_lower_immunity(ah); | 764 | ath9k_hw_ani_lower_immunity(ah); |
970 | aniState->ofdmsTurn = !aniState->ofdmsTurn; | 765 | aniState->ofdmsTurn = !aniState->ofdmsTurn; |
971 | } | 766 | } |
972 | ath_print(common, ATH_DBG_ANI, | 767 | ath9k_ani_restart(ah); |
973 | "1 listenTime=%d ofdm=%d/s cck=%d/s - " | ||
974 | "calling ath9k_ani_restart_new()\n", | ||
975 | aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate); | ||
976 | ath9k_ani_restart_new(ah); | ||
977 | } else if (aniState->listenTime > ah->aniperiod) { | 768 | } else if (aniState->listenTime > ah->aniperiod) { |
978 | /* check to see if need to raise immunity */ | 769 | /* check to see if need to raise immunity */ |
979 | if (ofdmPhyErrRate > aniState->ofdmTrigHigh && | 770 | if (ofdmPhyErrRate > ah->config.ofdm_trig_high && |
980 | (cckPhyErrRate <= aniState->cckTrigHigh || | 771 | (cckPhyErrRate <= ah->config.cck_trig_high || |
981 | aniState->ofdmsTurn)) { | 772 | aniState->ofdmsTurn)) { |
982 | ath_print(common, ATH_DBG_ANI, | 773 | ath9k_hw_ani_ofdm_err_trigger(ah); |
983 | "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> " | 774 | ath9k_ani_restart(ah); |
984 | "ath9k_hw_ani_ofdm_err_trigger_new()\n", | ||
985 | aniState->listenTime, | ||
986 | aniState->ofdmNoiseImmunityLevel, | ||
987 | ofdmPhyErrRate, | ||
988 | aniState->ofdmTrigHigh); | ||
989 | ath9k_hw_ani_ofdm_err_trigger_new(ah); | ||
990 | ath9k_ani_restart_new(ah); | ||
991 | aniState->ofdmsTurn = false; | 775 | aniState->ofdmsTurn = false; |
992 | } else if (cckPhyErrRate > aniState->cckTrigHigh) { | 776 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { |
993 | ath_print(common, ATH_DBG_ANI, | 777 | ath9k_hw_ani_cck_err_trigger(ah); |
994 | "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> " | 778 | ath9k_ani_restart(ah); |
995 | "ath9k_hw_ani_cck_err_trigger_new()\n", | ||
996 | aniState->listenTime, | ||
997 | aniState->cckNoiseImmunityLevel, | ||
998 | cckPhyErrRate, | ||
999 | aniState->cckTrigHigh); | ||
1000 | ath9k_hw_ani_cck_err_trigger_new(ah); | ||
1001 | ath9k_ani_restart_new(ah); | ||
1002 | aniState->ofdmsTurn = true; | 779 | aniState->ofdmsTurn = true; |
1003 | } | 780 | } |
1004 | } | 781 | } |
1005 | } | 782 | } |
783 | EXPORT_SYMBOL(ath9k_hw_ani_monitor); | ||
1006 | 784 | ||
1007 | void ath9k_enable_mib_counters(struct ath_hw *ah) | 785 | void ath9k_enable_mib_counters(struct ath_hw *ah) |
1008 | { | 786 | { |
@@ -1023,7 +801,6 @@ void ath9k_enable_mib_counters(struct ath_hw *ah) | |||
1023 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 801 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
1024 | 802 | ||
1025 | REGWRITE_BUFFER_FLUSH(ah); | 803 | REGWRITE_BUFFER_FLUSH(ah); |
1026 | DISABLE_REGWRITE_BUFFER(ah); | ||
1027 | } | 804 | } |
1028 | 805 | ||
1029 | /* Freeze the MIB counters, get the stats and then clear them */ | 806 | /* Freeze the MIB counters, get the stats and then clear them */ |
@@ -1041,107 +818,52 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) | |||
1041 | } | 818 | } |
1042 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); | 819 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); |
1043 | 820 | ||
1044 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | 821 | void ath9k_hw_update_cycle_counters(struct ath_hw *ah) |
1045 | u32 *rxc_pcnt, | ||
1046 | u32 *rxf_pcnt, | ||
1047 | u32 *txf_pcnt) | ||
1048 | { | 822 | { |
1049 | struct ath_common *common = ath9k_hw_common(ah); | 823 | struct ath_cycle_counters cc; |
1050 | static u32 cycles, rx_clear, rx_frame, tx_frame; | 824 | bool clear; |
1051 | u32 good = 1; | ||
1052 | 825 | ||
1053 | u32 rc = REG_READ(ah, AR_RCCNT); | 826 | memcpy(&cc, &ah->cc, sizeof(cc)); |
1054 | u32 rf = REG_READ(ah, AR_RFCNT); | ||
1055 | u32 tf = REG_READ(ah, AR_TFCNT); | ||
1056 | u32 cc = REG_READ(ah, AR_CCCNT); | ||
1057 | 827 | ||
1058 | if (cycles == 0 || cycles > cc) { | 828 | /* freeze counters */ |
1059 | ath_print(common, ATH_DBG_ANI, | 829 | REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); |
1060 | "cycle counter wrap. ExtBusy = 0\n"); | ||
1061 | good = 0; | ||
1062 | } else { | ||
1063 | u32 cc_d = cc - cycles; | ||
1064 | u32 rc_d = rc - rx_clear; | ||
1065 | u32 rf_d = rf - rx_frame; | ||
1066 | u32 tf_d = tf - tx_frame; | ||
1067 | |||
1068 | if (cc_d != 0) { | ||
1069 | *rxc_pcnt = rc_d * 100 / cc_d; | ||
1070 | *rxf_pcnt = rf_d * 100 / cc_d; | ||
1071 | *txf_pcnt = tf_d * 100 / cc_d; | ||
1072 | } else { | ||
1073 | good = 0; | ||
1074 | } | ||
1075 | } | ||
1076 | 830 | ||
1077 | cycles = cc; | 831 | ah->cc.cycles = REG_READ(ah, AR_CCCNT); |
1078 | rx_frame = rf; | 832 | if (ah->cc.cycles < cc.cycles) { |
1079 | rx_clear = rc; | 833 | clear = true; |
1080 | tx_frame = tf; | 834 | goto skip; |
835 | } | ||
1081 | 836 | ||
1082 | return good; | 837 | ah->cc.rx_clear = REG_READ(ah, AR_RCCNT); |
1083 | } | 838 | ah->cc.rx_frame = REG_READ(ah, AR_RFCNT); |
839 | ah->cc.tx_frame = REG_READ(ah, AR_TFCNT); | ||
1084 | 840 | ||
1085 | /* | 841 | /* prevent wraparound */ |
1086 | * Process a MIB interrupt. We may potentially be invoked because | 842 | if (ah->cc.cycles & BIT(31)) |
1087 | * any of the MIB counters overflow/trigger so don't assume we're | 843 | clear = true; |
1088 | * here because a PHY error counter triggered. | ||
1089 | */ | ||
1090 | static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) | ||
1091 | { | ||
1092 | u32 phyCnt1, phyCnt2; | ||
1093 | 844 | ||
1094 | /* Reset these counters regardless */ | 845 | #define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field |
1095 | REG_WRITE(ah, AR_FILT_OFDM, 0); | 846 | CC_DELTA(cycles, AR_CCCNT); |
1096 | REG_WRITE(ah, AR_FILT_CCK, 0); | 847 | CC_DELTA(rx_frame, AR_RFCNT); |
1097 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) | 848 | CC_DELTA(rx_clear, AR_RCCNT); |
1098 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); | 849 | CC_DELTA(tx_frame, AR_TFCNT); |
850 | #undef CC_DELTA | ||
1099 | 851 | ||
1100 | /* Clear the mib counters and save them in the stats */ | 852 | ah->listen_time += (ah->cc.cycles - cc.cycles) - |
1101 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 853 | ((ah->cc.rx_frame - cc.rx_frame) + |
854 | (ah->cc.tx_frame - cc.tx_frame)); | ||
1102 | 855 | ||
1103 | if (!DO_ANI(ah)) { | 856 | skip: |
1104 | /* | 857 | if (clear) { |
1105 | * We must always clear the interrupt cause by | 858 | REG_WRITE(ah, AR_CCCNT, 0); |
1106 | * resetting the phy error regs. | 859 | REG_WRITE(ah, AR_RFCNT, 0); |
1107 | */ | 860 | REG_WRITE(ah, AR_RCCNT, 0); |
1108 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | 861 | REG_WRITE(ah, AR_TFCNT, 0); |
1109 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | 862 | memset(&ah->cc, 0, sizeof(ah->cc)); |
1110 | return; | ||
1111 | } | 863 | } |
1112 | 864 | ||
1113 | /* NB: these are not reset-on-read */ | 865 | /* unfreeze counters */ |
1114 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 866 | REG_WRITE(ah, AR_MIBC, 0); |
1115 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
1116 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | ||
1117 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { | ||
1118 | struct ar5416AniState *aniState = ah->curani; | ||
1119 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
1120 | |||
1121 | /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ | ||
1122 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
1123 | ah->stats.ast_ani_ofdmerrs += | ||
1124 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
1125 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
1126 | |||
1127 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
1128 | ah->stats.ast_ani_cckerrs += | ||
1129 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
1130 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
1131 | |||
1132 | /* | ||
1133 | * NB: figure out which counter triggered. If both | ||
1134 | * trigger we'll only deal with one as the processing | ||
1135 | * clobbers the error counter so the trigger threshold | ||
1136 | * check will never be true. | ||
1137 | */ | ||
1138 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) | ||
1139 | ath9k_hw_ani_ofdm_err_trigger_new(ah); | ||
1140 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) | ||
1141 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
1142 | /* NB: always restart to insure the h/w counters are reset */ | ||
1143 | ath9k_ani_restart_old(ah); | ||
1144 | } | ||
1145 | } | 867 | } |
1146 | 868 | ||
1147 | /* | 869 | /* |
@@ -1149,7 +871,7 @@ static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) | |||
1149 | * any of the MIB counters overflow/trigger so don't assume we're | 871 | * any of the MIB counters overflow/trigger so don't assume we're |
1150 | * here because a PHY error counter triggered. | 872 | * here because a PHY error counter triggered. |
1151 | */ | 873 | */ |
1152 | static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) | 874 | void ath9k_hw_proc_mib_event(struct ath_hw *ah) |
1153 | { | 875 | { |
1154 | u32 phyCnt1, phyCnt2; | 876 | u32 phyCnt1, phyCnt2; |
1155 | 877 | ||
@@ -1175,12 +897,17 @@ static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) | |||
1175 | /* NB: these are not reset-on-read */ | 897 | /* NB: these are not reset-on-read */ |
1176 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 898 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
1177 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 899 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); |
1178 | |||
1179 | /* NB: always restart to insure the h/w counters are reset */ | ||
1180 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | 900 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || |
1181 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) | 901 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { |
1182 | ath9k_ani_restart_new(ah); | 902 | |
903 | if (!use_new_ani(ah)) | ||
904 | ath9k_hw_ani_read_counters(ah); | ||
905 | |||
906 | /* NB: always restart to insure the h/w counters are reset */ | ||
907 | ath9k_ani_restart(ah); | ||
908 | } | ||
1183 | } | 909 | } |
910 | EXPORT_SYMBOL(ath9k_hw_proc_mib_event); | ||
1184 | 911 | ||
1185 | void ath9k_hw_ani_setup(struct ath_hw *ah) | 912 | void ath9k_hw_ani_setup(struct ath_hw *ah) |
1186 | { | 913 | { |
@@ -1206,61 +933,58 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
1206 | 933 | ||
1207 | ath_print(common, ATH_DBG_ANI, "Initialize ANI\n"); | 934 | ath_print(common, ATH_DBG_ANI, "Initialize ANI\n"); |
1208 | 935 | ||
1209 | memset(ah->ani, 0, sizeof(ah->ani)); | 936 | if (use_new_ani(ah)) { |
1210 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | 937 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; |
1211 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { | 938 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW; |
1212 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; | ||
1213 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW; | ||
1214 | 939 | ||
1215 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW; | 940 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW; |
1216 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW; | 941 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW; |
942 | } else { | ||
943 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
944 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
1217 | 945 | ||
1218 | ah->ani[i].spurImmunityLevel = | 946 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD; |
1219 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | 947 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD; |
948 | } | ||
949 | |||
950 | for (i = 0; i < ARRAY_SIZE(ah->channels); i++) { | ||
951 | struct ath9k_channel *chan = &ah->channels[i]; | ||
952 | struct ar5416AniState *ani = &chan->ani; | ||
1220 | 953 | ||
1221 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 954 | if (use_new_ani(ah)) { |
955 | ani->spurImmunityLevel = | ||
956 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
1222 | 957 | ||
1223 | ah->ani[i].ofdmPhyErrBase = 0; | 958 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; |
1224 | ah->ani[i].cckPhyErrBase = 0; | ||
1225 | 959 | ||
1226 | if (AR_SREV_9300_20_OR_LATER(ah)) | 960 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1227 | ah->ani[i].mrcCCKOff = | 961 | ani->mrcCCKOff = |
1228 | !ATH9K_ANI_ENABLE_MRC_CCK; | 962 | !ATH9K_ANI_ENABLE_MRC_CCK; |
1229 | else | 963 | else |
1230 | ah->ani[i].mrcCCKOff = true; | 964 | ani->mrcCCKOff = true; |
1231 | 965 | ||
1232 | ah->ani[i].ofdmsTurn = true; | 966 | ani->ofdmsTurn = true; |
1233 | } else { | 967 | } else { |
1234 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | 968 | ani->spurImmunityLevel = |
1235 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
1236 | |||
1237 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1238 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD; | ||
1239 | |||
1240 | ah->ani[i].spurImmunityLevel = | ||
1241 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; | 969 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; |
1242 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; | 970 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; |
1243 | 971 | ||
1244 | ah->ani[i].ofdmPhyErrBase = | 972 | ani->cckWeakSigThreshold = |
1245 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
1246 | ah->ani[i].cckPhyErrBase = | ||
1247 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1248 | ah->ani[i].cckWeakSigThreshold = | ||
1249 | ATH9K_ANI_CCK_WEAK_SIG_THR; | 973 | ATH9K_ANI_CCK_WEAK_SIG_THR; |
1250 | } | 974 | } |
1251 | 975 | ||
1252 | ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; | 976 | ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; |
1253 | ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; | 977 | ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; |
1254 | ah->ani[i].ofdmWeakSigDetectOff = | 978 | ani->ofdmWeakSigDetectOff = |
1255 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 979 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1256 | ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; | 980 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; |
1257 | } | 981 | } |
1258 | 982 | ||
1259 | /* | 983 | /* |
1260 | * since we expect some ongoing maintenance on the tables, let's sanity | 984 | * since we expect some ongoing maintenance on the tables, let's sanity |
1261 | * check here default level should not modify INI setting. | 985 | * check here default level should not modify INI setting. |
1262 | */ | 986 | */ |
1263 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { | 987 | if (use_new_ani(ah)) { |
1264 | const struct ani_ofdm_level_entry *entry_ofdm; | 988 | const struct ani_ofdm_level_entry *entry_ofdm; |
1265 | const struct ani_cck_level_entry *entry_cck; | 989 | const struct ani_cck_level_entry *entry_cck; |
1266 | 990 | ||
@@ -1274,50 +998,9 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
1274 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; | 998 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; |
1275 | } | 999 | } |
1276 | 1000 | ||
1277 | ath_print(common, ATH_DBG_ANI, | ||
1278 | "Setting OfdmErrBase = 0x%08x\n", | ||
1279 | ah->ani[0].ofdmPhyErrBase); | ||
1280 | ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", | ||
1281 | ah->ani[0].cckPhyErrBase); | ||
1282 | |||
1283 | ENABLE_REGWRITE_BUFFER(ah); | ||
1284 | |||
1285 | REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); | ||
1286 | REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); | ||
1287 | |||
1288 | REGWRITE_BUFFER_FLUSH(ah); | ||
1289 | DISABLE_REGWRITE_BUFFER(ah); | ||
1290 | |||
1291 | ath9k_enable_mib_counters(ah); | ||
1292 | |||
1293 | if (ah->config.enable_ani) | 1001 | if (ah->config.enable_ani) |
1294 | ah->proc_phyerr |= HAL_PROCESS_ANI; | 1002 | ah->proc_phyerr |= HAL_PROCESS_ANI; |
1295 | } | ||
1296 | |||
1297 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah) | ||
1298 | { | ||
1299 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1300 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1301 | 1003 | ||
1302 | priv_ops->ani_reset = ath9k_ani_reset_old; | 1004 | ath9k_ani_restart(ah); |
1303 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old; | 1005 | ath9k_enable_mib_counters(ah); |
1304 | |||
1305 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old; | ||
1306 | ops->ani_monitor = ath9k_hw_ani_monitor_old; | ||
1307 | |||
1308 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n"); | ||
1309 | } | ||
1310 | |||
1311 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah) | ||
1312 | { | ||
1313 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1314 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1315 | |||
1316 | priv_ops->ani_reset = ath9k_ani_reset_new; | ||
1317 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new; | ||
1318 | |||
1319 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new; | ||
1320 | ops->ani_monitor = ath9k_hw_ani_monitor_new; | ||
1321 | |||
1322 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n"); | ||
1323 | } | 1006 | } |