2 * Copyright (c) 2008-2009 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.
19 static int ath9k_hw_get_ani_channel_idx(struct ath_hw
*ah
,
20 struct ath9k_channel
*chan
)
24 for (i
= 0; i
< ARRAY_SIZE(ah
->ani
); i
++) {
26 ah
->ani
[i
].c
->channel
== chan
->channel
)
28 if (ah
->ani
[i
].c
== NULL
) {
34 ath_print(ath9k_hw_common(ah
), ATH_DBG_ANI
,
35 "No more channel states left. Using channel 0\n");
40 static bool ath9k_hw_ani_control(struct ath_hw
*ah
,
41 enum ath9k_ani_cmd cmd
, int param
)
43 struct ar5416AniState
*aniState
= ah
->curani
;
44 struct ath_common
*common
= ath9k_hw_common(ah
);
46 switch (cmd
& ah
->ani_function
) {
47 case ATH9K_ANI_NOISE_IMMUNITY_LEVEL
:{
50 if (level
>= ARRAY_SIZE(ah
->totalSizeDesired
)) {
51 ath_print(common
, ATH_DBG_ANI
,
52 "level out of range (%u > %u)\n",
54 (unsigned)ARRAY_SIZE(ah
->totalSizeDesired
));
58 REG_RMW_FIELD(ah
, AR_PHY_DESIRED_SZ
,
59 AR_PHY_DESIRED_SZ_TOT_DES
,
60 ah
->totalSizeDesired
[level
]);
61 REG_RMW_FIELD(ah
, AR_PHY_AGC_CTL1
,
62 AR_PHY_AGC_CTL1_COARSE_LOW
,
63 ah
->coarse_low
[level
]);
64 REG_RMW_FIELD(ah
, AR_PHY_AGC_CTL1
,
65 AR_PHY_AGC_CTL1_COARSE_HIGH
,
66 ah
->coarse_high
[level
]);
67 REG_RMW_FIELD(ah
, AR_PHY_FIND_SIG
,
68 AR_PHY_FIND_SIG_FIRPWR
,
71 if (level
> aniState
->noiseImmunityLevel
)
72 ah
->stats
.ast_ani_niup
++;
73 else if (level
< aniState
->noiseImmunityLevel
)
74 ah
->stats
.ast_ani_nidown
++;
75 aniState
->noiseImmunityLevel
= level
;
78 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
:{
79 const int m1ThreshLow
[] = { 127, 50 };
80 const int m2ThreshLow
[] = { 127, 40 };
81 const int m1Thresh
[] = { 127, 0x4d };
82 const int m2Thresh
[] = { 127, 0x40 };
83 const int m2CountThr
[] = { 31, 16 };
84 const int m2CountThrLow
[] = { 63, 48 };
85 u32 on
= param
? 1 : 0;
87 REG_RMW_FIELD(ah
, AR_PHY_SFCORR_LOW
,
88 AR_PHY_SFCORR_LOW_M1_THRESH_LOW
,
90 REG_RMW_FIELD(ah
, AR_PHY_SFCORR_LOW
,
91 AR_PHY_SFCORR_LOW_M2_THRESH_LOW
,
93 REG_RMW_FIELD(ah
, AR_PHY_SFCORR
,
94 AR_PHY_SFCORR_M1_THRESH
,
96 REG_RMW_FIELD(ah
, AR_PHY_SFCORR
,
97 AR_PHY_SFCORR_M2_THRESH
,
99 REG_RMW_FIELD(ah
, AR_PHY_SFCORR
,
100 AR_PHY_SFCORR_M2COUNT_THR
,
102 REG_RMW_FIELD(ah
, AR_PHY_SFCORR_LOW
,
103 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW
,
106 REG_RMW_FIELD(ah
, AR_PHY_SFCORR_EXT
,
107 AR_PHY_SFCORR_EXT_M1_THRESH_LOW
,
109 REG_RMW_FIELD(ah
, AR_PHY_SFCORR_EXT
,
110 AR_PHY_SFCORR_EXT_M2_THRESH_LOW
,
112 REG_RMW_FIELD(ah
, AR_PHY_SFCORR_EXT
,
113 AR_PHY_SFCORR_EXT_M1_THRESH
,
115 REG_RMW_FIELD(ah
, AR_PHY_SFCORR_EXT
,
116 AR_PHY_SFCORR_EXT_M2_THRESH
,
120 REG_SET_BIT(ah
, AR_PHY_SFCORR_LOW
,
121 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW
);
123 REG_CLR_BIT(ah
, AR_PHY_SFCORR_LOW
,
124 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW
);
126 if (!on
!= aniState
->ofdmWeakSigDetectOff
) {
128 ah
->stats
.ast_ani_ofdmon
++;
130 ah
->stats
.ast_ani_ofdmoff
++;
131 aniState
->ofdmWeakSigDetectOff
= !on
;
135 case ATH9K_ANI_CCK_WEAK_SIGNAL_THR
:{
136 const int weakSigThrCck
[] = { 8, 6 };
137 u32 high
= param
? 1 : 0;
139 REG_RMW_FIELD(ah
, AR_PHY_CCK_DETECT
,
140 AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK
,
141 weakSigThrCck
[high
]);
142 if (high
!= aniState
->cckWeakSigThreshold
) {
144 ah
->stats
.ast_ani_cckhigh
++;
146 ah
->stats
.ast_ani_ccklow
++;
147 aniState
->cckWeakSigThreshold
= high
;
151 case ATH9K_ANI_FIRSTEP_LEVEL
:{
152 const int firstep
[] = { 0, 4, 8 };
155 if (level
>= ARRAY_SIZE(firstep
)) {
156 ath_print(common
, ATH_DBG_ANI
,
157 "level out of range (%u > %u)\n",
159 (unsigned) ARRAY_SIZE(firstep
));
162 REG_RMW_FIELD(ah
, AR_PHY_FIND_SIG
,
163 AR_PHY_FIND_SIG_FIRSTEP
,
165 if (level
> aniState
->firstepLevel
)
166 ah
->stats
.ast_ani_stepup
++;
167 else if (level
< aniState
->firstepLevel
)
168 ah
->stats
.ast_ani_stepdown
++;
169 aniState
->firstepLevel
= level
;
172 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL
:{
173 const int cycpwrThr1
[] =
174 { 2, 4, 6, 8, 10, 12, 14, 16 };
177 if (level
>= ARRAY_SIZE(cycpwrThr1
)) {
178 ath_print(common
, ATH_DBG_ANI
,
179 "level out of range (%u > %u)\n",
181 (unsigned) ARRAY_SIZE(cycpwrThr1
));
184 REG_RMW_FIELD(ah
, AR_PHY_TIMING5
,
185 AR_PHY_TIMING5_CYCPWR_THR1
,
187 if (level
> aniState
->spurImmunityLevel
)
188 ah
->stats
.ast_ani_spurup
++;
189 else if (level
< aniState
->spurImmunityLevel
)
190 ah
->stats
.ast_ani_spurdown
++;
191 aniState
->spurImmunityLevel
= level
;
194 case ATH9K_ANI_PRESENT
:
197 ath_print(common
, ATH_DBG_ANI
,
198 "invalid cmd %u\n", cmd
);
202 ath_print(common
, ATH_DBG_ANI
, "ANI parameters:\n");
203 ath_print(common
, ATH_DBG_ANI
,
204 "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
205 "ofdmWeakSigDetectOff=%d\n",
206 aniState
->noiseImmunityLevel
,
207 aniState
->spurImmunityLevel
,
208 !aniState
->ofdmWeakSigDetectOff
);
209 ath_print(common
, ATH_DBG_ANI
,
210 "cckWeakSigThreshold=%d, "
211 "firstepLevel=%d, listenTime=%d\n",
212 aniState
->cckWeakSigThreshold
,
213 aniState
->firstepLevel
,
214 aniState
->listenTime
);
215 ath_print(common
, ATH_DBG_ANI
,
216 "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
217 aniState
->cycleCount
,
218 aniState
->ofdmPhyErrCount
,
219 aniState
->cckPhyErrCount
);
224 static void ath9k_hw_update_mibstats(struct ath_hw
*ah
,
225 struct ath9k_mib_stats
*stats
)
227 stats
->ackrcv_bad
+= REG_READ(ah
, AR_ACK_FAIL
);
228 stats
->rts_bad
+= REG_READ(ah
, AR_RTS_FAIL
);
229 stats
->fcs_bad
+= REG_READ(ah
, AR_FCS_FAIL
);
230 stats
->rts_good
+= REG_READ(ah
, AR_RTS_OK
);
231 stats
->beacons
+= REG_READ(ah
, AR_BEACON_CNT
);
234 static void ath9k_ani_restart(struct ath_hw
*ah
)
236 struct ar5416AniState
*aniState
;
237 struct ath_common
*common
= ath9k_hw_common(ah
);
242 aniState
= ah
->curani
;
243 aniState
->listenTime
= 0;
245 if (aniState
->ofdmTrigHigh
> AR_PHY_COUNTMAX
) {
246 aniState
->ofdmPhyErrBase
= 0;
247 ath_print(common
, ATH_DBG_ANI
,
248 "OFDM Trigger is too high for hw counters\n");
250 aniState
->ofdmPhyErrBase
=
251 AR_PHY_COUNTMAX
- aniState
->ofdmTrigHigh
;
253 if (aniState
->cckTrigHigh
> AR_PHY_COUNTMAX
) {
254 aniState
->cckPhyErrBase
= 0;
255 ath_print(common
, ATH_DBG_ANI
,
256 "CCK Trigger is too high for hw counters\n");
258 aniState
->cckPhyErrBase
=
259 AR_PHY_COUNTMAX
- aniState
->cckTrigHigh
;
261 ath_print(common
, ATH_DBG_ANI
,
262 "Writing ofdmbase=%u cckbase=%u\n",
263 aniState
->ofdmPhyErrBase
,
264 aniState
->cckPhyErrBase
);
265 REG_WRITE(ah
, AR_PHY_ERR_1
, aniState
->ofdmPhyErrBase
);
266 REG_WRITE(ah
, AR_PHY_ERR_2
, aniState
->cckPhyErrBase
);
267 REG_WRITE(ah
, AR_PHY_ERR_MASK_1
, AR_PHY_ERR_OFDM_TIMING
);
268 REG_WRITE(ah
, AR_PHY_ERR_MASK_2
, AR_PHY_ERR_CCK_TIMING
);
270 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
272 aniState
->ofdmPhyErrCount
= 0;
273 aniState
->cckPhyErrCount
= 0;
276 static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw
*ah
)
278 struct ieee80211_conf
*conf
= &ath9k_hw_common(ah
)->hw
->conf
;
279 struct ar5416AniState
*aniState
;
285 aniState
= ah
->curani
;
287 if (aniState
->noiseImmunityLevel
< HAL_NOISE_IMMUNE_MAX
) {
288 if (ath9k_hw_ani_control(ah
, ATH9K_ANI_NOISE_IMMUNITY_LEVEL
,
289 aniState
->noiseImmunityLevel
+ 1)) {
294 if (aniState
->spurImmunityLevel
< HAL_SPUR_IMMUNE_MAX
) {
295 if (ath9k_hw_ani_control(ah
, ATH9K_ANI_SPUR_IMMUNITY_LEVEL
,
296 aniState
->spurImmunityLevel
+ 1)) {
301 if (ah
->opmode
== NL80211_IFTYPE_AP
) {
302 if (aniState
->firstepLevel
< HAL_FIRST_STEP_MAX
) {
303 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
304 aniState
->firstepLevel
+ 1);
308 rssi
= BEACON_RSSI(ah
);
309 if (rssi
> aniState
->rssiThrHigh
) {
310 if (!aniState
->ofdmWeakSigDetectOff
) {
311 if (ath9k_hw_ani_control(ah
,
312 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
314 ath9k_hw_ani_control(ah
,
315 ATH9K_ANI_SPUR_IMMUNITY_LEVEL
, 0);
319 if (aniState
->firstepLevel
< HAL_FIRST_STEP_MAX
) {
320 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
321 aniState
->firstepLevel
+ 1);
324 } else if (rssi
> aniState
->rssiThrLow
) {
325 if (aniState
->ofdmWeakSigDetectOff
)
326 ath9k_hw_ani_control(ah
,
327 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
329 if (aniState
->firstepLevel
< HAL_FIRST_STEP_MAX
)
330 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
331 aniState
->firstepLevel
+ 1);
334 if ((conf
->channel
->band
== IEEE80211_BAND_2GHZ
) &&
336 if (!aniState
->ofdmWeakSigDetectOff
)
337 ath9k_hw_ani_control(ah
,
338 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
340 if (aniState
->firstepLevel
> 0)
341 ath9k_hw_ani_control(ah
,
342 ATH9K_ANI_FIRSTEP_LEVEL
, 0);
348 static void ath9k_hw_ani_cck_err_trigger(struct ath_hw
*ah
)
350 struct ieee80211_conf
*conf
= &ath9k_hw_common(ah
)->hw
->conf
;
351 struct ar5416AniState
*aniState
;
357 aniState
= ah
->curani
;
358 if (aniState
->noiseImmunityLevel
< HAL_NOISE_IMMUNE_MAX
) {
359 if (ath9k_hw_ani_control(ah
, ATH9K_ANI_NOISE_IMMUNITY_LEVEL
,
360 aniState
->noiseImmunityLevel
+ 1)) {
364 if (ah
->opmode
== NL80211_IFTYPE_AP
) {
365 if (aniState
->firstepLevel
< HAL_FIRST_STEP_MAX
) {
366 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
367 aniState
->firstepLevel
+ 1);
371 rssi
= BEACON_RSSI(ah
);
372 if (rssi
> aniState
->rssiThrLow
) {
373 if (aniState
->firstepLevel
< HAL_FIRST_STEP_MAX
)
374 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
375 aniState
->firstepLevel
+ 1);
377 if ((conf
->channel
->band
== IEEE80211_BAND_2GHZ
) &&
379 if (aniState
->firstepLevel
> 0)
380 ath9k_hw_ani_control(ah
,
381 ATH9K_ANI_FIRSTEP_LEVEL
, 0);
386 static void ath9k_hw_ani_lower_immunity(struct ath_hw
*ah
)
388 struct ar5416AniState
*aniState
;
391 aniState
= ah
->curani
;
393 if (ah
->opmode
== NL80211_IFTYPE_AP
) {
394 if (aniState
->firstepLevel
> 0) {
395 if (ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
396 aniState
->firstepLevel
- 1))
400 rssi
= BEACON_RSSI(ah
);
401 if (rssi
> aniState
->rssiThrHigh
) {
403 } else if (rssi
> aniState
->rssiThrLow
) {
404 if (aniState
->ofdmWeakSigDetectOff
) {
405 if (ath9k_hw_ani_control(ah
,
406 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
410 if (aniState
->firstepLevel
> 0) {
411 if (ath9k_hw_ani_control(ah
,
412 ATH9K_ANI_FIRSTEP_LEVEL
,
413 aniState
->firstepLevel
- 1) == true)
417 if (aniState
->firstepLevel
> 0) {
418 if (ath9k_hw_ani_control(ah
,
419 ATH9K_ANI_FIRSTEP_LEVEL
,
420 aniState
->firstepLevel
- 1) == true)
426 if (aniState
->spurImmunityLevel
> 0) {
427 if (ath9k_hw_ani_control(ah
, ATH9K_ANI_SPUR_IMMUNITY_LEVEL
,
428 aniState
->spurImmunityLevel
- 1))
432 if (aniState
->noiseImmunityLevel
> 0) {
433 ath9k_hw_ani_control(ah
, ATH9K_ANI_NOISE_IMMUNITY_LEVEL
,
434 aniState
->noiseImmunityLevel
- 1);
439 static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw
*ah
)
441 struct ar5416AniState
*aniState
;
442 u32 txFrameCount
, rxFrameCount
, cycleCount
;
445 txFrameCount
= REG_READ(ah
, AR_TFCNT
);
446 rxFrameCount
= REG_READ(ah
, AR_RFCNT
);
447 cycleCount
= REG_READ(ah
, AR_CCCNT
);
449 aniState
= ah
->curani
;
450 if (aniState
->cycleCount
== 0 || aniState
->cycleCount
> cycleCount
) {
453 ah
->stats
.ast_ani_lzero
++;
455 int32_t ccdelta
= cycleCount
- aniState
->cycleCount
;
456 int32_t rfdelta
= rxFrameCount
- aniState
->rxFrameCount
;
457 int32_t tfdelta
= txFrameCount
- aniState
->txFrameCount
;
458 listenTime
= (ccdelta
- rfdelta
- tfdelta
) / 44000;
460 aniState
->cycleCount
= cycleCount
;
461 aniState
->txFrameCount
= txFrameCount
;
462 aniState
->rxFrameCount
= rxFrameCount
;
467 void ath9k_ani_reset(struct ath_hw
*ah
)
469 struct ar5416AniState
*aniState
;
470 struct ath9k_channel
*chan
= ah
->curchan
;
471 struct ath_common
*common
= ath9k_hw_common(ah
);
477 index
= ath9k_hw_get_ani_channel_idx(ah
, chan
);
478 aniState
= &ah
->ani
[index
];
479 ah
->curani
= aniState
;
481 if (DO_ANI(ah
) && ah
->opmode
!= NL80211_IFTYPE_STATION
482 && ah
->opmode
!= NL80211_IFTYPE_ADHOC
) {
483 ath_print(common
, ATH_DBG_ANI
,
484 "Reset ANI state opmode %u\n", ah
->opmode
);
485 ah
->stats
.ast_ani_reset
++;
487 if (ah
->opmode
== NL80211_IFTYPE_AP
) {
489 * ath9k_hw_ani_control() will only process items set on
492 if (IS_CHAN_2GHZ(chan
))
493 ah
->ani_function
= (ATH9K_ANI_SPUR_IMMUNITY_LEVEL
|
494 ATH9K_ANI_FIRSTEP_LEVEL
);
496 ah
->ani_function
= 0;
499 ath9k_hw_ani_control(ah
, ATH9K_ANI_NOISE_IMMUNITY_LEVEL
, 0);
500 ath9k_hw_ani_control(ah
, ATH9K_ANI_SPUR_IMMUNITY_LEVEL
, 0);
501 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
, 0);
502 ath9k_hw_ani_control(ah
, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
503 !ATH9K_ANI_USE_OFDM_WEAK_SIG
);
504 ath9k_hw_ani_control(ah
, ATH9K_ANI_CCK_WEAK_SIGNAL_THR
,
505 ATH9K_ANI_CCK_WEAK_SIG_THR
);
507 ath9k_hw_setrxfilter(ah
, ath9k_hw_getrxfilter(ah
) |
508 ATH9K_RX_FILTER_PHYERR
);
510 if (ah
->opmode
== NL80211_IFTYPE_AP
) {
511 ah
->curani
->ofdmTrigHigh
=
512 ah
->config
.ofdm_trig_high
;
513 ah
->curani
->ofdmTrigLow
=
514 ah
->config
.ofdm_trig_low
;
515 ah
->curani
->cckTrigHigh
=
516 ah
->config
.cck_trig_high
;
517 ah
->curani
->cckTrigLow
=
518 ah
->config
.cck_trig_low
;
520 ath9k_ani_restart(ah
);
524 if (aniState
->noiseImmunityLevel
!= 0)
525 ath9k_hw_ani_control(ah
, ATH9K_ANI_NOISE_IMMUNITY_LEVEL
,
526 aniState
->noiseImmunityLevel
);
527 if (aniState
->spurImmunityLevel
!= 0)
528 ath9k_hw_ani_control(ah
, ATH9K_ANI_SPUR_IMMUNITY_LEVEL
,
529 aniState
->spurImmunityLevel
);
530 if (aniState
->ofdmWeakSigDetectOff
)
531 ath9k_hw_ani_control(ah
, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION
,
532 !aniState
->ofdmWeakSigDetectOff
);
533 if (aniState
->cckWeakSigThreshold
)
534 ath9k_hw_ani_control(ah
, ATH9K_ANI_CCK_WEAK_SIGNAL_THR
,
535 aniState
->cckWeakSigThreshold
);
536 if (aniState
->firstepLevel
!= 0)
537 ath9k_hw_ani_control(ah
, ATH9K_ANI_FIRSTEP_LEVEL
,
538 aniState
->firstepLevel
);
540 ath9k_hw_setrxfilter(ah
, ath9k_hw_getrxfilter(ah
) &
541 ~ATH9K_RX_FILTER_PHYERR
);
542 ath9k_ani_restart(ah
);
543 REG_WRITE(ah
, AR_PHY_ERR_MASK_1
, AR_PHY_ERR_OFDM_TIMING
);
544 REG_WRITE(ah
, AR_PHY_ERR_MASK_2
, AR_PHY_ERR_CCK_TIMING
);
547 void ath9k_hw_ani_monitor(struct ath_hw
*ah
,
548 struct ath9k_channel
*chan
)
550 struct ar5416AniState
*aniState
;
551 struct ath_common
*common
= ath9k_hw_common(ah
);
553 u32 phyCnt1
, phyCnt2
;
554 u32 ofdmPhyErrCnt
, cckPhyErrCnt
;
559 aniState
= ah
->curani
;
561 listenTime
= ath9k_hw_ani_get_listen_time(ah
);
562 if (listenTime
< 0) {
563 ah
->stats
.ast_ani_lneg
++;
564 ath9k_ani_restart(ah
);
568 aniState
->listenTime
+= listenTime
;
570 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
572 phyCnt1
= REG_READ(ah
, AR_PHY_ERR_1
);
573 phyCnt2
= REG_READ(ah
, AR_PHY_ERR_2
);
575 if (phyCnt1
< aniState
->ofdmPhyErrBase
||
576 phyCnt2
< aniState
->cckPhyErrBase
) {
577 if (phyCnt1
< aniState
->ofdmPhyErrBase
) {
578 ath_print(common
, ATH_DBG_ANI
,
579 "phyCnt1 0x%x, resetting "
580 "counter value to 0x%x\n",
582 aniState
->ofdmPhyErrBase
);
583 REG_WRITE(ah
, AR_PHY_ERR_1
,
584 aniState
->ofdmPhyErrBase
);
585 REG_WRITE(ah
, AR_PHY_ERR_MASK_1
,
586 AR_PHY_ERR_OFDM_TIMING
);
588 if (phyCnt2
< aniState
->cckPhyErrBase
) {
589 ath_print(common
, ATH_DBG_ANI
,
590 "phyCnt2 0x%x, resetting "
591 "counter value to 0x%x\n",
593 aniState
->cckPhyErrBase
);
594 REG_WRITE(ah
, AR_PHY_ERR_2
,
595 aniState
->cckPhyErrBase
);
596 REG_WRITE(ah
, AR_PHY_ERR_MASK_2
,
597 AR_PHY_ERR_CCK_TIMING
);
602 ofdmPhyErrCnt
= phyCnt1
- aniState
->ofdmPhyErrBase
;
603 ah
->stats
.ast_ani_ofdmerrs
+=
604 ofdmPhyErrCnt
- aniState
->ofdmPhyErrCount
;
605 aniState
->ofdmPhyErrCount
= ofdmPhyErrCnt
;
607 cckPhyErrCnt
= phyCnt2
- aniState
->cckPhyErrBase
;
608 ah
->stats
.ast_ani_cckerrs
+=
609 cckPhyErrCnt
- aniState
->cckPhyErrCount
;
610 aniState
->cckPhyErrCount
= cckPhyErrCnt
;
612 if (aniState
->listenTime
> 5 * ah
->aniperiod
) {
613 if (aniState
->ofdmPhyErrCount
<= aniState
->listenTime
*
614 aniState
->ofdmTrigLow
/ 1000 &&
615 aniState
->cckPhyErrCount
<= aniState
->listenTime
*
616 aniState
->cckTrigLow
/ 1000)
617 ath9k_hw_ani_lower_immunity(ah
);
618 ath9k_ani_restart(ah
);
619 } else if (aniState
->listenTime
> ah
->aniperiod
) {
620 if (aniState
->ofdmPhyErrCount
> aniState
->listenTime
*
621 aniState
->ofdmTrigHigh
/ 1000) {
622 ath9k_hw_ani_ofdm_err_trigger(ah
);
623 ath9k_ani_restart(ah
);
624 } else if (aniState
->cckPhyErrCount
>
625 aniState
->listenTime
* aniState
->cckTrigHigh
/
627 ath9k_hw_ani_cck_err_trigger(ah
);
628 ath9k_ani_restart(ah
);
632 EXPORT_SYMBOL(ath9k_hw_ani_monitor
);
634 void ath9k_enable_mib_counters(struct ath_hw
*ah
)
636 struct ath_common
*common
= ath9k_hw_common(ah
);
638 ath_print(common
, ATH_DBG_ANI
, "Enable MIB counters\n");
640 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
642 REG_WRITE(ah
, AR_FILT_OFDM
, 0);
643 REG_WRITE(ah
, AR_FILT_CCK
, 0);
644 REG_WRITE(ah
, AR_MIBC
,
645 ~(AR_MIBC_COW
| AR_MIBC_FMC
| AR_MIBC_CMC
| AR_MIBC_MCS
)
647 REG_WRITE(ah
, AR_PHY_ERR_MASK_1
, AR_PHY_ERR_OFDM_TIMING
);
648 REG_WRITE(ah
, AR_PHY_ERR_MASK_2
, AR_PHY_ERR_CCK_TIMING
);
651 /* Freeze the MIB counters, get the stats and then clear them */
652 void ath9k_hw_disable_mib_counters(struct ath_hw
*ah
)
654 struct ath_common
*common
= ath9k_hw_common(ah
);
656 ath_print(common
, ATH_DBG_ANI
, "Disable MIB counters\n");
658 REG_WRITE(ah
, AR_MIBC
, AR_MIBC_FMC
);
659 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
660 REG_WRITE(ah
, AR_MIBC
, AR_MIBC_CMC
);
661 REG_WRITE(ah
, AR_FILT_OFDM
, 0);
662 REG_WRITE(ah
, AR_FILT_CCK
, 0);
665 u32
ath9k_hw_GetMibCycleCountsPct(struct ath_hw
*ah
,
670 struct ath_common
*common
= ath9k_hw_common(ah
);
671 static u32 cycles
, rx_clear
, rx_frame
, tx_frame
;
674 u32 rc
= REG_READ(ah
, AR_RCCNT
);
675 u32 rf
= REG_READ(ah
, AR_RFCNT
);
676 u32 tf
= REG_READ(ah
, AR_TFCNT
);
677 u32 cc
= REG_READ(ah
, AR_CCCNT
);
679 if (cycles
== 0 || cycles
> cc
) {
680 ath_print(common
, ATH_DBG_ANI
,
681 "cycle counter wrap. ExtBusy = 0\n");
684 u32 cc_d
= cc
- cycles
;
685 u32 rc_d
= rc
- rx_clear
;
686 u32 rf_d
= rf
- rx_frame
;
687 u32 tf_d
= tf
- tx_frame
;
690 *rxc_pcnt
= rc_d
* 100 / cc_d
;
691 *rxf_pcnt
= rf_d
* 100 / cc_d
;
692 *txf_pcnt
= tf_d
* 100 / cc_d
;
707 * Process a MIB interrupt. We may potentially be invoked because
708 * any of the MIB counters overflow/trigger so don't assume we're
709 * here because a PHY error counter triggered.
711 void ath9k_hw_procmibevent(struct ath_hw
*ah
)
713 u32 phyCnt1
, phyCnt2
;
715 /* Reset these counters regardless */
716 REG_WRITE(ah
, AR_FILT_OFDM
, 0);
717 REG_WRITE(ah
, AR_FILT_CCK
, 0);
718 if (!(REG_READ(ah
, AR_SLP_MIB_CTRL
) & AR_SLP_MIB_PENDING
))
719 REG_WRITE(ah
, AR_SLP_MIB_CTRL
, AR_SLP_MIB_CLEAR
);
721 /* Clear the mib counters and save them in the stats */
722 ath9k_hw_update_mibstats(ah
, &ah
->ah_mibStats
);
727 /* NB: these are not reset-on-read */
728 phyCnt1
= REG_READ(ah
, AR_PHY_ERR_1
);
729 phyCnt2
= REG_READ(ah
, AR_PHY_ERR_2
);
730 if (((phyCnt1
& AR_MIBCNT_INTRMASK
) == AR_MIBCNT_INTRMASK
) ||
731 ((phyCnt2
& AR_MIBCNT_INTRMASK
) == AR_MIBCNT_INTRMASK
)) {
732 struct ar5416AniState
*aniState
= ah
->curani
;
733 u32 ofdmPhyErrCnt
, cckPhyErrCnt
;
735 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
736 ofdmPhyErrCnt
= phyCnt1
- aniState
->ofdmPhyErrBase
;
737 ah
->stats
.ast_ani_ofdmerrs
+=
738 ofdmPhyErrCnt
- aniState
->ofdmPhyErrCount
;
739 aniState
->ofdmPhyErrCount
= ofdmPhyErrCnt
;
741 cckPhyErrCnt
= phyCnt2
- aniState
->cckPhyErrBase
;
742 ah
->stats
.ast_ani_cckerrs
+=
743 cckPhyErrCnt
- aniState
->cckPhyErrCount
;
744 aniState
->cckPhyErrCount
= cckPhyErrCnt
;
747 * NB: figure out which counter triggered. If both
748 * trigger we'll only deal with one as the processing
749 * clobbers the error counter so the trigger threshold
750 * check will never be true.
752 if (aniState
->ofdmPhyErrCount
> aniState
->ofdmTrigHigh
)
753 ath9k_hw_ani_ofdm_err_trigger(ah
);
754 if (aniState
->cckPhyErrCount
> aniState
->cckTrigHigh
)
755 ath9k_hw_ani_cck_err_trigger(ah
);
756 /* NB: always restart to insure the h/w counters are reset */
757 ath9k_ani_restart(ah
);
760 EXPORT_SYMBOL(ath9k_hw_procmibevent
);
762 void ath9k_hw_ani_setup(struct ath_hw
*ah
)
766 const int totalSizeDesired
[] = { -55, -55, -55, -55, -62 };
767 const int coarseHigh
[] = { -14, -14, -14, -14, -12 };
768 const int coarseLow
[] = { -64, -64, -64, -64, -70 };
769 const int firpwr
[] = { -78, -78, -78, -78, -80 };
771 for (i
= 0; i
< 5; i
++) {
772 ah
->totalSizeDesired
[i
] = totalSizeDesired
[i
];
773 ah
->coarse_high
[i
] = coarseHigh
[i
];
774 ah
->coarse_low
[i
] = coarseLow
[i
];
775 ah
->firpwr
[i
] = firpwr
[i
];
779 void ath9k_hw_ani_init(struct ath_hw
*ah
)
781 struct ath_common
*common
= ath9k_hw_common(ah
);
784 ath_print(common
, ATH_DBG_ANI
, "Initialize ANI\n");
786 memset(ah
->ani
, 0, sizeof(ah
->ani
));
787 for (i
= 0; i
< ARRAY_SIZE(ah
->ani
); i
++) {
788 ah
->ani
[i
].ofdmTrigHigh
= ATH9K_ANI_OFDM_TRIG_HIGH
;
789 ah
->ani
[i
].ofdmTrigLow
= ATH9K_ANI_OFDM_TRIG_LOW
;
790 ah
->ani
[i
].cckTrigHigh
= ATH9K_ANI_CCK_TRIG_HIGH
;
791 ah
->ani
[i
].cckTrigLow
= ATH9K_ANI_CCK_TRIG_LOW
;
792 ah
->ani
[i
].rssiThrHigh
= ATH9K_ANI_RSSI_THR_HIGH
;
793 ah
->ani
[i
].rssiThrLow
= ATH9K_ANI_RSSI_THR_LOW
;
794 ah
->ani
[i
].ofdmWeakSigDetectOff
=
795 !ATH9K_ANI_USE_OFDM_WEAK_SIG
;
796 ah
->ani
[i
].cckWeakSigThreshold
=
797 ATH9K_ANI_CCK_WEAK_SIG_THR
;
798 ah
->ani
[i
].spurImmunityLevel
= ATH9K_ANI_SPUR_IMMUNE_LVL
;
799 ah
->ani
[i
].firstepLevel
= ATH9K_ANI_FIRSTEP_LVL
;
800 ah
->ani
[i
].ofdmPhyErrBase
=
801 AR_PHY_COUNTMAX
- ATH9K_ANI_OFDM_TRIG_HIGH
;
802 ah
->ani
[i
].cckPhyErrBase
=
803 AR_PHY_COUNTMAX
- ATH9K_ANI_CCK_TRIG_HIGH
;
806 ath_print(common
, ATH_DBG_ANI
,
807 "Setting OfdmErrBase = 0x%08x\n",
808 ah
->ani
[0].ofdmPhyErrBase
);
809 ath_print(common
, ATH_DBG_ANI
, "Setting cckErrBase = 0x%08x\n",
810 ah
->ani
[0].cckPhyErrBase
);
812 REG_WRITE(ah
, AR_PHY_ERR_1
, ah
->ani
[0].ofdmPhyErrBase
);
813 REG_WRITE(ah
, AR_PHY_ERR_2
, ah
->ani
[0].cckPhyErrBase
);
814 ath9k_enable_mib_counters(ah
);
816 ah
->aniperiod
= ATH9K_ANI_PERIOD
;
817 if (ah
->config
.enable_ani
)
818 ah
->proc_phyerr
|= HAL_PROCESS_ANI
;
821 void ath9k_hw_ani_disable(struct ath_hw
*ah
)
823 ath_print(ath9k_hw_common(ah
), ATH_DBG_ANI
, "Disabling ANI\n");
825 ath9k_hw_disable_mib_counters(ah
);
826 REG_WRITE(ah
, AR_PHY_ERR_1
, 0);
827 REG_WRITE(ah
, AR_PHY_ERR_2
, 0);