2 * Copyright (c) 2008-2010 Atheros Communications Inc.
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.
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.
20 struct ani_ofdm_level_entry
{
21 int spur_immunity_level
;
23 int ofdm_weak_signal_on
;
26 /* values here are relative to the INI */
33 * WS: OFDM / CCK Weak Signal detection
34 * MRC-CCK: Maximal Ratio Combining for CCK
37 static const struct ani_ofdm_level_entry ofdm_level_table
[] = {
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 */
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 */
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
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.
72 * Regardless of alignment in time, the antenna signals add constructively after
73 * FFT and improve your reception. For more information:
75 * http://en.wikipedia.org/wiki/Maximal-ratio_combining
78 struct ani_cck_level_entry
{
83 static const struct ani_cck_level_entry cck_level_table
[] = {
87 { 2, 1 }, /* lvl 2 (default) */
92 { 7, 0 }, /* lvl 7 (only for high rssi) */
93 { 8, 0 } /* lvl 8 (only for high rssi) */
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 */
105 /* Private to ani.c */
106 static void ath9k_hw_ani_lower_immunity(struct ath_hw
*ah
)
108 ath9k_hw_private_ops(ah
)->ani_lower_immunity(ah
);
111 int ath9k_hw_get_ani_channel_idx(struct ath_hw
*ah
,
112 struct ath9k_channel
*chan
)
116 for (i
= 0; i
< ARRAY_SIZE(ah
->ani
); i
++) {
118 ah
->ani
[i
].c
->channel
== chan
->channel
)
120 if (ah
->ani
[i
].c
== NULL
) {
126 ath_print(ath9k_hw_common(ah
), ATH_DBG_ANI
,
127 "No more channel states left. Using channel 0\n");
132 static void ath9k_hw_update_mibstats(struct ath_hw
*ah
,
133 struct ath9k_mib_stats
*stats
)
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
);
142 static void ath9k_ani_restart_old(struct ath_hw
*ah
)
144 struct ar5416AniState
*aniState
;
145 struct ath_common
*common
= ath9k_hw_common(ah
);
150 aniState
= ah
->curani
;
151 aniState
->listenTime
= 0;
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");
158 aniState
->ofdmPhyErrBase
=
159 AR_PHY_COUNTMAX
- aniState
->ofdmTrigHigh
;
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");
166 aniState
->cckPhyErrBase
=
167 AR_PHY_COUNTMAX
- aniState
->cckTrigHigh
;
169 ath_print(common
, ATH_DBG_ANI
,
170 "Writing ofdmbase=%u cckbase=%u\n",
171 aniState
->ofdmPhyErrBase
,
172 aniState
->cckPhyErrBase
);
174 ENABLE_REGWRITE_BUFFER(ah
);
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
);
181 REGWRITE_BUFFER_FLUSH(ah
);
182 DISABLE_REGWRITE_BUFFER(ah
);
184 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
186 aniState
->ofdmPhyErrCount
= 0;
187 aniState
->cckPhyErrCount
= 0;
190 static void ath9k_ani_restart_new(struct ath_hw
*ah
)
192 struct ar5416AniState
*aniState
;
193 struct ath_common
*common
= ath9k_hw_common(ah
);
198 aniState
= ah
->curani
;
199 aniState
->listenTime
= 0;
201 aniState
->ofdmPhyErrBase
= 0;
202 aniState
->cckPhyErrBase
= 0;
204 ath_print(common
, ATH_DBG_ANI
,
205 "Writing ofdmbase=%08x cckbase=%08x\n",
206 aniState
->ofdmPhyErrBase
,
207 aniState
->cckPhyErrBase
);
209 ENABLE_REGWRITE_BUFFER(ah
);
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
);
216 REGWRITE_BUFFER_FLUSH(ah
);
217 DISABLE_REGWRITE_BUFFER(ah
);
219 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
221 aniState
->ofdmPhyErrCount
= 0;
222 aniState
->cckPhyErrCount
= 0;
225 static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw
*ah
)
227 struct ieee80211_conf
*conf
= &ath9k_hw_common(ah
)->hw
->conf
;
228 struct ar5416AniState
*aniState
;
234 aniState
= ah
->curani
;
236 if (aniState
->noiseImmunityLevel
< HAL_NOISE_IMMUNE_MAX
) {
237 if (ath9k_hw_ani_control(ah
, ATH9K_ANI_NOISE_IMMUNITY_LEVEL
,
238 aniState
->noiseImmunityLevel
+ 1)) {
243 if (aniState
->spurImmunityLevel
< HAL_SPUR_IMMUNE_MAX
) {
244 if (ath9k_hw_ani_control(ah
, ATH9K_ANI_SPUR_IMMUNITY_LEVEL
,
245 aniState
->spurImmunityLevel
+ 1)) {
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);
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
,
263 ath9k_hw_ani_control(ah
,
264 ATH9K_ANI_SPUR_IMMUNITY_LEVEL
, 0);
268 if (aniState
->firstepLevel
< HAL_FIRST_STEP_MAX
) {
269 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
270 aniState
->firstepLevel
+ 1);
273 } else if (rssi
> aniState
->rssiThrLow
) {
274 if (aniState
->ofdmWeakSigDetectOff
)
275 ath9k_hw_ani_control(ah
,
276 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
278 if (aniState
->firstepLevel
< HAL_FIRST_STEP_MAX
)
279 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
280 aniState
->firstepLevel
+ 1);
283 if ((conf
->channel
->band
== IEEE80211_BAND_2GHZ
) &&
285 if (!aniState
->ofdmWeakSigDetectOff
)
286 ath9k_hw_ani_control(ah
,
287 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
289 if (aniState
->firstepLevel
> 0)
290 ath9k_hw_ani_control(ah
,
291 ATH9K_ANI_FIRSTEP_LEVEL
, 0);
297 static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw
*ah
)
299 struct ieee80211_conf
*conf
= &ath9k_hw_common(ah
)->hw
->conf
;
300 struct ar5416AniState
*aniState
;
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)) {
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);
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);
326 if ((conf
->channel
->band
== IEEE80211_BAND_2GHZ
) &&
328 if (aniState
->firstepLevel
> 0)
329 ath9k_hw_ani_control(ah
,
330 ATH9K_ANI_FIRSTEP_LEVEL
, 0);
335 /* Adjust the OFDM Noise Immunity Level */
336 static void ath9k_hw_set_ofdm_nil(struct ath_hw
*ah
, u8 immunityLevel
)
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
;
343 aniState
->noiseFloor
= BEACON_RSSI(ah
);
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
);
351 aniState
->ofdmNoiseImmunityLevel
= immunityLevel
;
353 entry_ofdm
= &ofdm_level_table
[aniState
->ofdmNoiseImmunityLevel
];
354 entry_cck
= &cck_level_table
[aniState
->cckNoiseImmunityLevel
];
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
);
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
);
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
,
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
);
383 static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw
*ah
)
385 struct ar5416AniState
*aniState
;
390 aniState
= ah
->curani
;
392 if (aniState
->ofdmNoiseImmunityLevel
< ATH9K_ANI_OFDM_MAX_LEVEL
)
393 ath9k_hw_set_ofdm_nil(ah
, aniState
->ofdmNoiseImmunityLevel
+ 1);
397 * Set the ANI settings to match an CCK level.
399 static void ath9k_hw_set_cck_nil(struct ath_hw
*ah
, u_int8_t immunityLevel
)
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
;
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
);
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
;
419 aniState
->cckNoiseImmunityLevel
= immunityLevel
;
421 entry_ofdm
= &ofdm_level_table
[aniState
->ofdmNoiseImmunityLevel
];
422 entry_cck
= &cck_level_table
[aniState
->cckNoiseImmunityLevel
];
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
);
430 /* Skip MRC CCK for pre AR9003 families */
431 if (!AR_SREV_9300_20_OR_LATER(ah
))
434 if (aniState
->mrcCCKOff
== entry_cck
->mrc_cck_on
)
435 ath9k_hw_ani_control(ah
,
437 entry_cck
->mrc_cck_on
);
440 static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw
*ah
)
442 struct ar5416AniState
*aniState
;
447 aniState
= ah
->curani
;
449 if (aniState
->cckNoiseImmunityLevel
< ATH9K_ANI_CCK_MAX_LEVEL
)
450 ath9k_hw_set_cck_nil(ah
, aniState
->cckNoiseImmunityLevel
+ 1);
453 static void ath9k_hw_ani_lower_immunity_old(struct ath_hw
*ah
)
455 struct ar5416AniState
*aniState
;
458 aniState
= ah
->curani
;
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))
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
,
476 if (aniState
->firstepLevel
> 0) {
477 if (ath9k_hw_ani_control(ah
,
478 ATH9K_ANI_FIRSTEP_LEVEL
,
479 aniState
->firstepLevel
- 1) == true)
483 if (aniState
->firstepLevel
> 0) {
484 if (ath9k_hw_ani_control(ah
,
485 ATH9K_ANI_FIRSTEP_LEVEL
,
486 aniState
->firstepLevel
- 1) == true)
492 if (aniState
->spurImmunityLevel
> 0) {
493 if (ath9k_hw_ani_control(ah
, ATH9K_ANI_SPUR_IMMUNITY_LEVEL
,
494 aniState
->spurImmunityLevel
- 1))
498 if (aniState
->noiseImmunityLevel
> 0) {
499 ath9k_hw_ani_control(ah
, ATH9K_ANI_NOISE_IMMUNITY_LEVEL
,
500 aniState
->noiseImmunityLevel
- 1);
506 * only lower either OFDM or CCK errors per turn
507 * we lower the other one next time
509 static void ath9k_hw_ani_lower_immunity_new(struct ath_hw
*ah
)
511 struct ar5416AniState
*aniState
;
513 aniState
= ah
->curani
;
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);
522 /* lower CCK noise immunity */
523 if (aniState
->cckNoiseImmunityLevel
> 0)
524 ath9k_hw_set_cck_nil(ah
, aniState
->cckNoiseImmunityLevel
- 1);
527 static u8
ath9k_hw_chan_2_clockrate_mhz(struct ath_hw
*ah
)
529 struct ath9k_channel
*chan
= ah
->curchan
;
530 struct ieee80211_conf
*conf
= &ath9k_hw_common(ah
)->hw
->conf
;
531 u8 clockrate
; /* in MHz */
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
;
540 clockrate
= ATH9K_CLOCK_RATE_5GHZ_OFDM
;
542 if (conf_is_ht40(conf
))
543 return clockrate
* 2;
548 static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw
*ah
)
550 struct ar5416AniState
*aniState
;
551 struct ath_common
*common
= ath9k_hw_common(ah
);
552 u32 txFrameCount
, rxFrameCount
, cycleCount
;
555 txFrameCount
= REG_READ(ah
, AR_TFCNT
);
556 rxFrameCount
= REG_READ(ah
, AR_RFCNT
);
557 cycleCount
= REG_READ(ah
, AR_CCCNT
);
559 aniState
= ah
->curani
;
560 if (aniState
->cycleCount
== 0 || aniState
->cycleCount
> cycleCount
) {
562 ah
->stats
.ast_ani_lzero
++;
563 ath_print(common
, ATH_DBG_ANI
,
564 "1st call: aniState->cycleCount=%d\n",
565 aniState
->cycleCount
);
567 int32_t ccdelta
= cycleCount
- aniState
->cycleCount
;
568 int32_t rfdelta
= rxFrameCount
- aniState
->rxFrameCount
;
569 int32_t tfdelta
= txFrameCount
- aniState
->txFrameCount
;
573 * convert HW counter values to ms using mode
574 * specifix clock rate
576 clock_rate
= ath9k_hw_chan_2_clockrate_mhz(ah
) * 1000;;
578 listenTime
= (ccdelta
- rfdelta
- tfdelta
) / clock_rate
;
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
);
586 aniState
->cycleCount
= cycleCount
;
587 aniState
->txFrameCount
= txFrameCount
;
588 aniState
->rxFrameCount
= rxFrameCount
;
593 static void ath9k_ani_reset_old(struct ath_hw
*ah
, bool is_scanning
)
595 struct ar5416AniState
*aniState
;
596 struct ath9k_channel
*chan
= ah
->curchan
;
597 struct ath_common
*common
= ath9k_hw_common(ah
);
603 index
= ath9k_hw_get_ani_channel_idx(ah
, chan
);
604 aniState
= &ah
->ani
[index
];
605 ah
->curani
= aniState
;
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
++;
613 if (ah
->opmode
== NL80211_IFTYPE_AP
) {
615 * ath9k_hw_ani_control() will only process items set on
618 if (IS_CHAN_2GHZ(chan
))
619 ah
->ani_function
= (ATH9K_ANI_SPUR_IMMUNITY_LEVEL
|
620 ATH9K_ANI_FIRSTEP_LEVEL
);
622 ah
->ani_function
= 0;
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
);
633 ath9k_hw_setrxfilter(ah
, ath9k_hw_getrxfilter(ah
) |
634 ATH9K_RX_FILTER_PHYERR
);
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
;
646 ath9k_ani_restart_old(ah
);
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
);
666 ath9k_hw_setrxfilter(ah
, ath9k_hw_getrxfilter(ah
) &
667 ~ATH9K_RX_FILTER_PHYERR
);
668 ath9k_ani_restart_old(ah
);
670 ENABLE_REGWRITE_BUFFER(ah
);
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
);
675 REGWRITE_BUFFER_FLUSH(ah
);
676 DISABLE_REGWRITE_BUFFER(ah
);
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.
684 static void ath9k_ani_reset_new(struct ath_hw
*ah
, bool is_scanning
)
686 struct ar5416AniState
*aniState
= ah
->curani
;
687 struct ath9k_channel
*chan
= ah
->curchan
;
688 struct ath_common
*common
= ath9k_hw_common(ah
);
693 BUG_ON(aniState
== NULL
);
694 ah
->stats
.ast_ani_reset
++;
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
;
704 ah
->ani_function
= 0;
707 /* always allow mode (on/off) to be controlled */
708 ah
->ani_function
|= ATH9K_ANI_MODE
;
711 (ah
->opmode
!= NL80211_IFTYPE_STATION
&&
712 ah
->opmode
!= NL80211_IFTYPE_ADHOC
)) {
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.
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 "
731 aniState
->ofdmNoiseImmunityLevel
,
732 aniState
->cckNoiseImmunityLevel
);
734 ath9k_hw_set_ofdm_nil(ah
, ATH9K_ANI_OFDM_DEF_LEVEL
);
735 ath9k_hw_set_cck_nil(ah
, ATH9K_ANI_CCK_DEF_LEVEL
);
739 * restore historical levels for this channel
741 ath_print(common
, ATH_DBG_ANI
,
742 "Restore history: opmode %u "
743 "chan %d Mhz/0x%x is_scanning=%d "
749 aniState
->ofdmNoiseImmunityLevel
,
750 aniState
->cckNoiseImmunityLevel
);
752 ath9k_hw_set_ofdm_nil(ah
,
753 aniState
->ofdmNoiseImmunityLevel
);
754 ath9k_hw_set_cck_nil(ah
,
755 aniState
->cckNoiseImmunityLevel
);
759 * enable phy counters if hw supports or if not, enable phy
760 * interrupts (so we can count each one)
762 ath9k_ani_restart_new(ah
);
764 ENABLE_REGWRITE_BUFFER(ah
);
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
);
769 REGWRITE_BUFFER_FLUSH(ah
);
770 DISABLE_REGWRITE_BUFFER(ah
);
773 static void ath9k_hw_ani_monitor_old(struct ath_hw
*ah
,
774 struct ath9k_channel
*chan
)
776 struct ar5416AniState
*aniState
;
777 struct ath_common
*common
= ath9k_hw_common(ah
);
779 u32 phyCnt1
, phyCnt2
;
780 u32 ofdmPhyErrCnt
, cckPhyErrCnt
;
785 aniState
= ah
->curani
;
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
);
794 aniState
->listenTime
+= listenTime
;
796 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
798 phyCnt1
= REG_READ(ah
, AR_PHY_ERR_1
);
799 phyCnt2
= REG_READ(ah
, AR_PHY_ERR_2
);
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",
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
);
814 if (phyCnt2
< aniState
->cckPhyErrBase
) {
815 ath_print(common
, ATH_DBG_ANI
,
816 "phyCnt2 0x%x, resetting "
817 "counter value to 0x%x\n",
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
);
828 ofdmPhyErrCnt
= phyCnt1
- aniState
->ofdmPhyErrBase
;
829 ah
->stats
.ast_ani_ofdmerrs
+=
830 ofdmPhyErrCnt
- aniState
->ofdmPhyErrCount
;
831 aniState
->ofdmPhyErrCount
= ofdmPhyErrCnt
;
833 cckPhyErrCnt
= phyCnt2
- aniState
->cckPhyErrBase
;
834 ah
->stats
.ast_ani_cckerrs
+=
835 cckPhyErrCnt
- aniState
->cckPhyErrCount
;
836 aniState
->cckPhyErrCount
= cckPhyErrCnt
;
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
/
853 ath9k_hw_ani_cck_err_trigger_old(ah
);
854 ath9k_ani_restart_old(ah
);
859 static void ath9k_hw_ani_monitor_new(struct ath_hw
*ah
,
860 struct ath9k_channel
*chan
)
862 struct ar5416AniState
*aniState
;
863 struct ath_common
*common
= ath9k_hw_common(ah
);
865 u32 phyCnt1
, phyCnt2
;
866 u32 ofdmPhyErrCnt
, cckPhyErrCnt
;
867 u32 ofdmPhyErrRate
, cckPhyErrRate
;
872 aniState
= ah
->curani
;
873 if (WARN_ON(!aniState
))
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",
883 ath9k_ani_restart_new(ah
);
887 aniState
->listenTime
+= listenTime
;
889 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
891 phyCnt1
= REG_READ(ah
, AR_PHY_ERR_1
);
892 phyCnt2
= REG_READ(ah
, AR_PHY_ERR_2
);
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",
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
);
907 if (phyCnt2
< aniState
->cckPhyErrBase
) {
908 ath_print(common
, ATH_DBG_ANI
,
909 "phyCnt2 0x%x, resetting "
910 "counter value to 0x%x\n",
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
);
921 ofdmPhyErrCnt
= phyCnt1
- aniState
->ofdmPhyErrBase
;
922 ah
->stats
.ast_ani_ofdmerrs
+=
923 ofdmPhyErrCnt
- aniState
->ofdmPhyErrCount
;
924 aniState
->ofdmPhyErrCount
= ofdmPhyErrCnt
;
926 cckPhyErrCnt
= phyCnt2
- aniState
->cckPhyErrBase
;
927 ah
->stats
.ast_ani_cckerrs
+=
928 cckPhyErrCnt
- aniState
->cckPhyErrCount
;
929 aniState
->cckPhyErrCount
= cckPhyErrCnt
;
931 ath_print(common
, ATH_DBG_ANI
,
932 "Errors: OFDM=0x%08x-0x%08x=%d "
933 "CCK=0x%08x-0x%08x=%d\n",
935 aniState
->ofdmPhyErrBase
,
938 aniState
->cckPhyErrBase
,
941 ofdmPhyErrRate
= aniState
->ofdmPhyErrCount
* 1000 /
942 aniState
->listenTime
;
943 cckPhyErrRate
= aniState
->cckPhyErrCount
* 1000 /
944 aniState
->listenTime
;
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
);
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
,
963 aniState
->ofdmTrigLow
,
964 aniState
->cckNoiseImmunityLevel
,
966 aniState
->cckTrigLow
);
967 ath9k_hw_ani_lower_immunity(ah
);
968 aniState
->ofdmsTurn
= !aniState
->ofdmsTurn
;
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
,
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
,
997 aniState
->cckTrigHigh
);
998 ath9k_hw_ani_cck_err_trigger_new(ah
);
999 ath9k_ani_restart_new(ah
);
1000 aniState
->ofdmsTurn
= true;
1005 void ath9k_enable_mib_counters(struct ath_hw
*ah
)
1007 struct ath_common
*common
= ath9k_hw_common(ah
);
1009 ath_print(common
, ATH_DBG_ANI
, "Enable MIB counters\n");
1011 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
1013 ENABLE_REGWRITE_BUFFER(ah
);
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
)
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
);
1023 REGWRITE_BUFFER_FLUSH(ah
);
1024 DISABLE_REGWRITE_BUFFER(ah
);
1027 /* Freeze the MIB counters, get the stats and then clear them */
1028 void ath9k_hw_disable_mib_counters(struct ath_hw
*ah
)
1030 struct ath_common
*common
= ath9k_hw_common(ah
);
1032 ath_print(common
, ATH_DBG_ANI
, "Disable MIB counters\n");
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);
1040 EXPORT_SYMBOL(ath9k_hw_disable_mib_counters
);
1042 u32
ath9k_hw_GetMibCycleCountsPct(struct ath_hw
*ah
,
1047 struct ath_common
*common
= ath9k_hw_common(ah
);
1048 static u32 cycles
, rx_clear
, rx_frame
, tx_frame
;
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
);
1056 if (cycles
== 0 || cycles
> cc
) {
1057 ath_print(common
, ATH_DBG_ANI
,
1058 "cycle counter wrap. ExtBusy = 0\n");
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
;
1067 *rxc_pcnt
= rc_d
* 100 / cc_d
;
1068 *rxf_pcnt
= rf_d
* 100 / cc_d
;
1069 *txf_pcnt
= tf_d
* 100 / cc_d
;
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.
1088 static void ath9k_hw_proc_mib_event_old(struct ath_hw
*ah
)
1090 u32 phyCnt1
, phyCnt2
;
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
);
1098 /* Clear the mib counters and save them in the stats */
1099 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
1103 * We must always clear the interrupt cause by
1104 * resetting the phy error regs.
1106 REG_WRITE(ah
, AR_PHY_ERR_1
, 0);
1107 REG_WRITE(ah
, AR_PHY_ERR_2
, 0);
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
;
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
;
1125 cckPhyErrCnt
= phyCnt2
- aniState
->cckPhyErrBase
;
1126 ah
->stats
.ast_ani_cckerrs
+=
1127 cckPhyErrCnt
- aniState
->cckPhyErrCount
;
1128 aniState
->cckPhyErrCount
= cckPhyErrCnt
;
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.
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
);
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.
1150 static void ath9k_hw_proc_mib_event_new(struct ath_hw
*ah
)
1152 u32 phyCnt1
, phyCnt2
;
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
);
1160 /* Clear the mib counters and save them in the stats */
1161 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
1165 * We must always clear the interrupt cause by
1166 * resetting the phy error regs.
1168 REG_WRITE(ah
, AR_PHY_ERR_1
, 0);
1169 REG_WRITE(ah
, AR_PHY_ERR_2
, 0);
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
);
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
);
1183 void ath9k_hw_ani_setup(struct ath_hw
*ah
)
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 };
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
];
1200 void ath9k_hw_ani_init(struct ath_hw
*ah
)
1202 struct ath_common
*common
= ath9k_hw_common(ah
);
1205 ath_print(common
, ATH_DBG_ANI
, "Initialize ANI\n");
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
;
1213 ah
->ani
[i
].cckTrigHigh
= ATH9K_ANI_CCK_TRIG_HIGH_NEW
;
1214 ah
->ani
[i
].cckTrigLow
= ATH9K_ANI_CCK_TRIG_LOW_NEW
;
1216 ah
->ani
[i
].spurImmunityLevel
=
1217 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW
;
1219 ah
->ani
[i
].firstepLevel
= ATH9K_ANI_FIRSTEP_LVL_NEW
;
1221 ah
->ani
[i
].ofdmPhyErrBase
= 0;
1222 ah
->ani
[i
].cckPhyErrBase
= 0;
1224 if (AR_SREV_9300_20_OR_LATER(ah
))
1225 ah
->ani
[i
].mrcCCKOff
=
1226 !ATH9K_ANI_ENABLE_MRC_CCK
;
1228 ah
->ani
[i
].mrcCCKOff
= true;
1230 ah
->ani
[i
].ofdmsTurn
= true;
1232 ah
->ani
[i
].ofdmTrigHigh
= ATH9K_ANI_OFDM_TRIG_HIGH_OLD
;
1233 ah
->ani
[i
].ofdmTrigLow
= ATH9K_ANI_OFDM_TRIG_LOW_OLD
;
1235 ah
->ani
[i
].cckTrigHigh
= ATH9K_ANI_CCK_TRIG_HIGH_OLD
;
1236 ah
->ani
[i
].cckTrigLow
= ATH9K_ANI_CCK_TRIG_LOW_OLD
;
1238 ah
->ani
[i
].spurImmunityLevel
=
1239 ATH9K_ANI_SPUR_IMMUNE_LVL_OLD
;
1240 ah
->ani
[i
].firstepLevel
= ATH9K_ANI_FIRSTEP_LVL_OLD
;
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
;
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
;
1258 * since we expect some ongoing maintenance on the tables, let's sanity
1259 * check here default level should not modify INI setting.
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
;
1265 entry_ofdm
= &ofdm_level_table
[ATH9K_ANI_OFDM_DEF_LEVEL
];
1266 entry_cck
= &cck_level_table
[ATH9K_ANI_CCK_DEF_LEVEL
];
1268 ah
->aniperiod
= ATH9K_ANI_PERIOD_NEW
;
1269 ah
->config
.ani_poll_interval
= ATH9K_ANI_POLLINTERVAL_NEW
;
1271 ah
->aniperiod
= ATH9K_ANI_PERIOD_OLD
;
1272 ah
->config
.ani_poll_interval
= ATH9K_ANI_POLLINTERVAL_OLD
;
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
);
1281 ENABLE_REGWRITE_BUFFER(ah
);
1283 REG_WRITE(ah
, AR_PHY_ERR_1
, ah
->ani
[0].ofdmPhyErrBase
);
1284 REG_WRITE(ah
, AR_PHY_ERR_2
, ah
->ani
[0].cckPhyErrBase
);
1286 REGWRITE_BUFFER_FLUSH(ah
);
1287 DISABLE_REGWRITE_BUFFER(ah
);
1289 ath9k_enable_mib_counters(ah
);
1291 if (ah
->config
.enable_ani
)
1292 ah
->proc_phyerr
|= HAL_PROCESS_ANI
;
1295 void ath9k_hw_attach_ani_ops_old(struct ath_hw
*ah
)
1297 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
1298 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
1300 priv_ops
->ani_reset
= ath9k_ani_reset_old
;
1301 priv_ops
->ani_lower_immunity
= ath9k_hw_ani_lower_immunity_old
;
1303 ops
->ani_proc_mib_event
= ath9k_hw_proc_mib_event_old
;
1304 ops
->ani_monitor
= ath9k_hw_ani_monitor_old
;
1306 ath_print(ath9k_hw_common(ah
), ATH_DBG_ANY
, "Using ANI v1\n");
1309 void ath9k_hw_attach_ani_ops_new(struct ath_hw
*ah
)
1311 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
1312 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
1314 priv_ops
->ani_reset
= ath9k_ani_reset_new
;
1315 priv_ops
->ani_lower_immunity
= ath9k_hw_ani_lower_immunity_new
;
1317 ops
->ani_proc_mib_event
= ath9k_hw_proc_mib_event_new
;
1318 ops
->ani_monitor
= ath9k_hw_ani_monitor_new
;
1320 ath_print(ath9k_hw_common(ah
), ATH_DBG_ANY
, "Using ANI v2\n");