2 * Copyright (c) 2008 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.
22 static int ath9k_hw_get_ani_channel_idx(struct ath_hal *ah,
23 struct ath9k_channel *chan)
25 struct ath_hal_5416 *ahp = AH5416(ah);
28 for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
29 if (ahp->ah_ani[i].c.channel == chan->channel)
31 if (ahp->ah_ani[i].c.channel == 0) {
32 ahp->ah_ani[i].c.channel = chan->channel;
33 ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
38 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
39 "No more channel states left. Using channel 0\n");
44 static bool ath9k_hw_ani_control(struct ath_hal *ah,
45 enum ath9k_ani_cmd cmd, int param)
47 struct ath_hal_5416 *ahp = AH5416(ah);
48 struct ar5416AniState *aniState = ahp->ah_curani;
50 switch (cmd & ahp->ah_ani_function) {
51 case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
54 if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
55 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
56 "%s: level out of range (%u > %u)\n",
58 (unsigned)ARRAY_SIZE(ahp->ah_totalSizeDesired));
62 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
63 AR_PHY_DESIRED_SZ_TOT_DES,
64 ahp->ah_totalSizeDesired[level]);
65 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
66 AR_PHY_AGC_CTL1_COARSE_LOW,
67 ahp->ah_coarseLow[level]);
68 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
69 AR_PHY_AGC_CTL1_COARSE_HIGH,
70 ahp->ah_coarseHigh[level]);
71 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
72 AR_PHY_FIND_SIG_FIRPWR,
73 ahp->ah_firpwr[level]);
75 if (level > aniState->noiseImmunityLevel)
76 ahp->ah_stats.ast_ani_niup++;
77 else if (level < aniState->noiseImmunityLevel)
78 ahp->ah_stats.ast_ani_nidown++;
79 aniState->noiseImmunityLevel = level;
82 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
83 const int m1ThreshLow[] = { 127, 50 };
84 const int m2ThreshLow[] = { 127, 40 };
85 const int m1Thresh[] = { 127, 0x4d };
86 const int m2Thresh[] = { 127, 0x40 };
87 const int m2CountThr[] = { 31, 16 };
88 const int m2CountThrLow[] = { 63, 48 };
89 u32 on = param ? 1 : 0;
91 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
92 AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
94 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
95 AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
97 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
98 AR_PHY_SFCORR_M1_THRESH,
100 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
101 AR_PHY_SFCORR_M2_THRESH,
103 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
104 AR_PHY_SFCORR_M2COUNT_THR,
106 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
107 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
110 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
111 AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
113 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
114 AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
116 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
117 AR_PHY_SFCORR_EXT_M1_THRESH,
119 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
120 AR_PHY_SFCORR_EXT_M2_THRESH,
124 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
125 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
127 REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
128 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
130 if (!on != aniState->ofdmWeakSigDetectOff) {
132 ahp->ah_stats.ast_ani_ofdmon++;
134 ahp->ah_stats.ast_ani_ofdmoff++;
135 aniState->ofdmWeakSigDetectOff = !on;
139 case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
140 const int weakSigThrCck[] = { 8, 6 };
141 u32 high = param ? 1 : 0;
143 REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
144 AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
145 weakSigThrCck[high]);
146 if (high != aniState->cckWeakSigThreshold) {
148 ahp->ah_stats.ast_ani_cckhigh++;
150 ahp->ah_stats.ast_ani_ccklow++;
151 aniState->cckWeakSigThreshold = high;
155 case ATH9K_ANI_FIRSTEP_LEVEL:{
156 const int firstep[] = { 0, 4, 8 };
159 if (level >= ARRAY_SIZE(firstep)) {
160 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
161 "%s: level out of range (%u > %u)\n",
163 (unsigned) ARRAY_SIZE(firstep));
166 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
167 AR_PHY_FIND_SIG_FIRSTEP,
169 if (level > aniState->firstepLevel)
170 ahp->ah_stats.ast_ani_stepup++;
171 else if (level < aniState->firstepLevel)
172 ahp->ah_stats.ast_ani_stepdown++;
173 aniState->firstepLevel = level;
176 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
177 const int cycpwrThr1[] =
178 { 2, 4, 6, 8, 10, 12, 14, 16 };
181 if (level >= ARRAY_SIZE(cycpwrThr1)) {
182 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
183 "%s: level out of range (%u > %u)\n",
186 ARRAY_SIZE(cycpwrThr1));
189 REG_RMW_FIELD(ah, AR_PHY_TIMING5,
190 AR_PHY_TIMING5_CYCPWR_THR1,
192 if (level > aniState->spurImmunityLevel)
193 ahp->ah_stats.ast_ani_spurup++;
194 else if (level < aniState->spurImmunityLevel)
195 ahp->ah_stats.ast_ani_spurdown++;
196 aniState->spurImmunityLevel = level;
199 case ATH9K_ANI_PRESENT:
202 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
203 "%s: invalid cmd %u\n", __func__, cmd);
207 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "%s: ANI parameters:\n", __func__);
208 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
209 "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
210 "ofdmWeakSigDetectOff=%d\n",
211 aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
212 !aniState->ofdmWeakSigDetectOff);
213 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
214 "cckWeakSigThreshold=%d, "
215 "firstepLevel=%d, listenTime=%d\n",
216 aniState->cckWeakSigThreshold, aniState->firstepLevel,
217 aniState->listenTime);
218 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
219 "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
220 aniState->cycleCount, aniState->ofdmPhyErrCount,
221 aniState->cckPhyErrCount);
226 static void ath9k_hw_update_mibstats(struct ath_hal *ah,
227 struct ath9k_mib_stats *stats)
229 stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
230 stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
231 stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
232 stats->rts_good += REG_READ(ah, AR_RTS_OK);
233 stats->beacons += REG_READ(ah, AR_BEACON_CNT);
236 static void ath9k_ani_restart(struct ath_hal *ah)
238 struct ath_hal_5416 *ahp = AH5416(ah);
239 struct ar5416AniState *aniState;
244 aniState = ahp->ah_curani;
246 aniState->listenTime = 0;
247 if (ahp->ah_hasHwPhyCounters) {
248 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
249 aniState->ofdmPhyErrBase = 0;
250 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
251 "OFDM Trigger is too high for hw counters\n");
253 aniState->ofdmPhyErrBase =
254 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
256 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
257 aniState->cckPhyErrBase = 0;
258 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
259 "CCK Trigger is too high for hw counters\n");
261 aniState->cckPhyErrBase =
262 AR_PHY_COUNTMAX - aniState->cckTrigHigh;
264 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
265 "%s: Writing ofdmbase=%u cckbase=%u\n",
266 __func__, aniState->ofdmPhyErrBase,
267 aniState->cckPhyErrBase);
268 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
269 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
270 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
271 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
273 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
275 aniState->ofdmPhyErrCount = 0;
276 aniState->cckPhyErrCount = 0;
279 static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
281 struct ath_hal_5416 *ahp = AH5416(ah);
282 struct ath9k_channel *chan = ah->ah_curchan;
283 struct ar5416AniState *aniState;
284 enum wireless_mode mode;
290 aniState = ahp->ah_curani;
292 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
293 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
294 aniState->noiseImmunityLevel + 1)) {
299 if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
300 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
301 aniState->spurImmunityLevel + 1)) {
306 if (ah->ah_opmode == ATH9K_M_HOSTAP) {
307 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
308 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
309 aniState->firstepLevel + 1);
313 rssi = BEACON_RSSI(ahp);
314 if (rssi > aniState->rssiThrHigh) {
315 if (!aniState->ofdmWeakSigDetectOff) {
316 if (ath9k_hw_ani_control(ah,
317 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
319 ath9k_hw_ani_control(ah,
320 ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
324 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
325 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
326 aniState->firstepLevel + 1);
329 } else if (rssi > aniState->rssiThrLow) {
330 if (aniState->ofdmWeakSigDetectOff)
331 ath9k_hw_ani_control(ah,
332 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
334 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
335 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
336 aniState->firstepLevel + 1);
339 mode = ath9k_hw_chan2wmode(ah, chan);
340 if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
341 if (!aniState->ofdmWeakSigDetectOff)
342 ath9k_hw_ani_control(ah,
343 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
345 if (aniState->firstepLevel > 0)
346 ath9k_hw_ani_control(ah,
347 ATH9K_ANI_FIRSTEP_LEVEL, 0);
353 static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
355 struct ath_hal_5416 *ahp = AH5416(ah);
356 struct ath9k_channel *chan = ah->ah_curchan;
357 struct ar5416AniState *aniState;
358 enum wireless_mode mode;
364 aniState = ahp->ah_curani;
365 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
366 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
367 aniState->noiseImmunityLevel + 1)) {
371 if (ah->ah_opmode == ATH9K_M_HOSTAP) {
372 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
373 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
374 aniState->firstepLevel + 1);
378 rssi = BEACON_RSSI(ahp);
379 if (rssi > aniState->rssiThrLow) {
380 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
381 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
382 aniState->firstepLevel + 1);
384 mode = ath9k_hw_chan2wmode(ah, chan);
385 if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
386 if (aniState->firstepLevel > 0)
387 ath9k_hw_ani_control(ah,
388 ATH9K_ANI_FIRSTEP_LEVEL, 0);
393 static void ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
395 struct ath_hal_5416 *ahp = AH5416(ah);
396 struct ar5416AniState *aniState;
399 aniState = ahp->ah_curani;
401 if (ah->ah_opmode == ATH9K_M_HOSTAP) {
402 if (aniState->firstepLevel > 0) {
403 if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
404 aniState->firstepLevel - 1))
408 rssi = BEACON_RSSI(ahp);
409 if (rssi > aniState->rssiThrHigh) {
411 } else if (rssi > aniState->rssiThrLow) {
412 if (aniState->ofdmWeakSigDetectOff) {
413 if (ath9k_hw_ani_control(ah,
414 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
418 if (aniState->firstepLevel > 0) {
419 if (ath9k_hw_ani_control(ah,
420 ATH9K_ANI_FIRSTEP_LEVEL,
421 aniState->firstepLevel - 1) == true)
425 if (aniState->firstepLevel > 0) {
426 if (ath9k_hw_ani_control(ah,
427 ATH9K_ANI_FIRSTEP_LEVEL,
428 aniState->firstepLevel - 1) == true)
434 if (aniState->spurImmunityLevel > 0) {
435 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
436 aniState->spurImmunityLevel - 1))
440 if (aniState->noiseImmunityLevel > 0) {
441 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
442 aniState->noiseImmunityLevel - 1);
447 static int32_t ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
449 struct ath_hal_5416 *ahp = AH5416(ah);
450 struct ar5416AniState *aniState;
451 u32 txFrameCount, rxFrameCount, cycleCount;
454 txFrameCount = REG_READ(ah, AR_TFCNT);
455 rxFrameCount = REG_READ(ah, AR_RFCNT);
456 cycleCount = REG_READ(ah, AR_CCCNT);
458 aniState = ahp->ah_curani;
459 if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
462 ahp->ah_stats.ast_ani_lzero++;
464 int32_t ccdelta = cycleCount - aniState->cycleCount;
465 int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
466 int32_t tfdelta = txFrameCount - aniState->txFrameCount;
467 listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
469 aniState->cycleCount = cycleCount;
470 aniState->txFrameCount = txFrameCount;
471 aniState->rxFrameCount = rxFrameCount;
476 void ath9k_ani_reset(struct ath_hal *ah)
478 struct ath_hal_5416 *ahp = AH5416(ah);
479 struct ar5416AniState *aniState;
480 struct ath9k_channel *chan = ah->ah_curchan;
486 index = ath9k_hw_get_ani_channel_idx(ah, chan);
487 aniState = &ahp->ah_ani[index];
488 ahp->ah_curani = aniState;
490 if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA
491 && ah->ah_opmode != ATH9K_M_IBSS) {
492 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
493 "%s: Reset ANI state opmode %u\n", __func__,
495 ahp->ah_stats.ast_ani_reset++;
497 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
498 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
499 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
500 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
501 !ATH9K_ANI_USE_OFDM_WEAK_SIG);
502 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
503 ATH9K_ANI_CCK_WEAK_SIG_THR);
505 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
506 ATH9K_RX_FILTER_PHYERR);
508 if (ah->ah_opmode == ATH9K_M_HOSTAP) {
509 ahp->ah_curani->ofdmTrigHigh =
510 ah->ah_config.ofdm_trig_high;
511 ahp->ah_curani->ofdmTrigLow =
512 ah->ah_config.ofdm_trig_low;
513 ahp->ah_curani->cckTrigHigh =
514 ah->ah_config.cck_trig_high;
515 ahp->ah_curani->cckTrigLow =
516 ah->ah_config.cck_trig_low;
518 ath9k_ani_restart(ah);
522 if (aniState->noiseImmunityLevel != 0)
523 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
524 aniState->noiseImmunityLevel);
525 if (aniState->spurImmunityLevel != 0)
526 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
527 aniState->spurImmunityLevel);
528 if (aniState->ofdmWeakSigDetectOff)
529 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
530 !aniState->ofdmWeakSigDetectOff);
531 if (aniState->cckWeakSigThreshold)
532 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
533 aniState->cckWeakSigThreshold);
534 if (aniState->firstepLevel != 0)
535 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
536 aniState->firstepLevel);
537 if (ahp->ah_hasHwPhyCounters) {
538 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
539 ~ATH9K_RX_FILTER_PHYERR);
540 ath9k_ani_restart(ah);
541 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
542 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
545 ath9k_ani_restart(ah);
546 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
547 ATH9K_RX_FILTER_PHYERR);
551 void ath9k_hw_ani_monitor(struct ath_hal *ah,
552 const struct ath9k_node_stats *stats,
553 struct ath9k_channel *chan)
555 struct ath_hal_5416 *ahp = AH5416(ah);
556 struct ar5416AniState *aniState;
559 aniState = ahp->ah_curani;
560 ahp->ah_stats.ast_nodestats = *stats;
562 listenTime = ath9k_hw_ani_get_listen_time(ah);
563 if (listenTime < 0) {
564 ahp->ah_stats.ast_ani_lneg++;
565 ath9k_ani_restart(ah);
569 aniState->listenTime += listenTime;
571 if (ahp->ah_hasHwPhyCounters) {
572 u32 phyCnt1, phyCnt2;
573 u32 ofdmPhyErrCnt, cckPhyErrCnt;
575 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
577 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
578 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
580 if (phyCnt1 < aniState->ofdmPhyErrBase ||
581 phyCnt2 < aniState->cckPhyErrBase) {
582 if (phyCnt1 < aniState->ofdmPhyErrBase) {
583 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
584 "%s: phyCnt1 0x%x, resetting "
585 "counter value to 0x%x\n",
587 aniState->ofdmPhyErrBase);
588 REG_WRITE(ah, AR_PHY_ERR_1,
589 aniState->ofdmPhyErrBase);
590 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
591 AR_PHY_ERR_OFDM_TIMING);
593 if (phyCnt2 < aniState->cckPhyErrBase) {
594 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
595 "%s: phyCnt2 0x%x, resetting "
596 "counter value to 0x%x\n",
598 aniState->cckPhyErrBase);
599 REG_WRITE(ah, AR_PHY_ERR_2,
600 aniState->cckPhyErrBase);
601 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
602 AR_PHY_ERR_CCK_TIMING);
607 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
608 ahp->ah_stats.ast_ani_ofdmerrs +=
609 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
610 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
612 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
613 ahp->ah_stats.ast_ani_cckerrs +=
614 cckPhyErrCnt - aniState->cckPhyErrCount;
615 aniState->cckPhyErrCount = cckPhyErrCnt;
621 if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
622 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
623 aniState->ofdmTrigLow / 1000 &&
624 aniState->cckPhyErrCount <= aniState->listenTime *
625 aniState->cckTrigLow / 1000)
626 ath9k_hw_ani_lower_immunity(ah);
627 ath9k_ani_restart(ah);
628 } else if (aniState->listenTime > ahp->ah_aniPeriod) {
629 if (aniState->ofdmPhyErrCount > aniState->listenTime *
630 aniState->ofdmTrigHigh / 1000) {
631 ath9k_hw_ani_ofdm_err_trigger(ah);
632 ath9k_ani_restart(ah);
633 } else if (aniState->cckPhyErrCount >
634 aniState->listenTime * aniState->cckTrigHigh /
636 ath9k_hw_ani_cck_err_trigger(ah);
637 ath9k_ani_restart(ah);
642 bool ath9k_hw_phycounters(struct ath_hal *ah)
644 struct ath_hal_5416 *ahp = AH5416(ah);
646 return ahp->ah_hasHwPhyCounters ? true : false;
649 void ath9k_enable_mib_counters(struct ath_hal *ah)
651 struct ath_hal_5416 *ahp = AH5416(ah);
653 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
655 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
657 REG_WRITE(ah, AR_FILT_OFDM, 0);
658 REG_WRITE(ah, AR_FILT_CCK, 0);
659 REG_WRITE(ah, AR_MIBC,
660 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
662 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
663 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
666 void ath9k_hw_disable_mib_counters(struct ath_hal *ah)
668 struct ath_hal_5416 *ahp = AH5416(ah);
670 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
672 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
674 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
676 REG_WRITE(ah, AR_FILT_OFDM, 0);
677 REG_WRITE(ah, AR_FILT_CCK, 0);
680 u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
685 static u32 cycles, rx_clear, rx_frame, tx_frame;
688 u32 rc = REG_READ(ah, AR_RCCNT);
689 u32 rf = REG_READ(ah, AR_RFCNT);
690 u32 tf = REG_READ(ah, AR_TFCNT);
691 u32 cc = REG_READ(ah, AR_CCCNT);
693 if (cycles == 0 || cycles > cc) {
694 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
695 "%s: cycle counter wrap. ExtBusy = 0\n",
699 u32 cc_d = cc - cycles;
700 u32 rc_d = rc - rx_clear;
701 u32 rf_d = rf - rx_frame;
702 u32 tf_d = tf - tx_frame;
705 *rxc_pcnt = rc_d * 100 / cc_d;
706 *rxf_pcnt = rf_d * 100 / cc_d;
707 *txf_pcnt = tf_d * 100 / cc_d;
722 * Process a MIB interrupt. We may potentially be invoked because
723 * any of the MIB counters overflow/trigger so don't assume we're
724 * here because a PHY error counter triggered.
726 void ath9k_hw_procmibevent(struct ath_hal *ah,
727 const struct ath9k_node_stats *stats)
729 struct ath_hal_5416 *ahp = AH5416(ah);
730 u32 phyCnt1, phyCnt2;
732 /* Reset these counters regardless */
733 REG_WRITE(ah, AR_FILT_OFDM, 0);
734 REG_WRITE(ah, AR_FILT_CCK, 0);
735 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
736 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
738 /* Clear the mib counters and save them in the stats */
739 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
740 ahp->ah_stats.ast_nodestats = *stats;
745 /* NB: these are not reset-on-read */
746 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
747 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
748 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
749 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
750 struct ar5416AniState *aniState = ahp->ah_curani;
751 u32 ofdmPhyErrCnt, cckPhyErrCnt;
753 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
754 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
755 ahp->ah_stats.ast_ani_ofdmerrs +=
756 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
757 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
759 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
760 ahp->ah_stats.ast_ani_cckerrs +=
761 cckPhyErrCnt - aniState->cckPhyErrCount;
762 aniState->cckPhyErrCount = cckPhyErrCnt;
765 * NB: figure out which counter triggered. If both
766 * trigger we'll only deal with one as the processing
767 * clobbers the error counter so the trigger threshold
768 * check will never be true.
770 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
771 ath9k_hw_ani_ofdm_err_trigger(ah);
772 if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
773 ath9k_hw_ani_cck_err_trigger(ah);
774 /* NB: always restart to insure the h/w counters are reset */
775 ath9k_ani_restart(ah);
779 void ath9k_hw_ani_setup(struct ath_hal *ah)
781 struct ath_hal_5416 *ahp = AH5416(ah);
784 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
785 const int coarseHigh[] = { -14, -14, -14, -14, -12 };
786 const int coarseLow[] = { -64, -64, -64, -64, -70 };
787 const int firpwr[] = { -78, -78, -78, -78, -80 };
789 for (i = 0; i < 5; i++) {
790 ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
791 ahp->ah_coarseHigh[i] = coarseHigh[i];
792 ahp->ah_coarseLow[i] = coarseLow[i];
793 ahp->ah_firpwr[i] = firpwr[i];
797 void ath9k_hw_ani_attach(struct ath_hal *ah)
799 struct ath_hal_5416 *ahp = AH5416(ah);
802 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
804 ahp->ah_hasHwPhyCounters = 1;
806 memset(ahp->ah_ani, 0, sizeof(ahp->ah_ani));
807 for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
808 ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
809 ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
810 ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
811 ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
812 ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
813 ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
814 ahp->ah_ani[i].ofdmWeakSigDetectOff =
815 !ATH9K_ANI_USE_OFDM_WEAK_SIG;
816 ahp->ah_ani[i].cckWeakSigThreshold =
817 ATH9K_ANI_CCK_WEAK_SIG_THR;
818 ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
819 ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
820 if (ahp->ah_hasHwPhyCounters) {
821 ahp->ah_ani[i].ofdmPhyErrBase =
822 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
823 ahp->ah_ani[i].cckPhyErrBase =
824 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
827 if (ahp->ah_hasHwPhyCounters) {
828 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
829 "Setting OfdmErrBase = 0x%08x\n",
830 ahp->ah_ani[0].ofdmPhyErrBase);
831 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
832 ahp->ah_ani[0].cckPhyErrBase);
834 REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
835 REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
836 ath9k_enable_mib_counters(ah);
838 ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
839 if (ah->ah_config.enable_ani)
840 ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
843 void ath9k_hw_ani_detach(struct ath_hal *ah)
845 struct ath_hal_5416 *ahp = AH5416(ah);
847 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
849 if (ahp->ah_hasHwPhyCounters) {
850 ath9k_hw_disable_mib_counters(ah);
851 REG_WRITE(ah, AR_PHY_ERR_1, 0);
852 REG_WRITE(ah, AR_PHY_ERR_2, 0);