xref: /openbmc/linux/drivers/net/wireless/ath/ath9k/ani.c (revision 7dd65feb)
1 /*
2  * Copyright (c) 2008-2009 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include "hw.h"
18 
19 static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
20 					struct ath9k_channel *chan)
21 {
22 	int i;
23 
24 	for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
25 		if (ah->ani[i].c &&
26 		    ah->ani[i].c->channel == chan->channel)
27 			return i;
28 		if (ah->ani[i].c == NULL) {
29 			ah->ani[i].c = chan;
30 			return i;
31 		}
32 	}
33 
34 	ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
35 		  "No more channel states left. Using channel 0\n");
36 
37 	return 0;
38 }
39 
40 static bool ath9k_hw_ani_control(struct ath_hw *ah,
41 				 enum ath9k_ani_cmd cmd, int param)
42 {
43 	struct ar5416AniState *aniState = ah->curani;
44 	struct ath_common *common = ath9k_hw_common(ah);
45 
46 	switch (cmd & ah->ani_function) {
47 	case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
48 		u32 level = param;
49 
50 		if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
51 			ath_print(common, ATH_DBG_ANI,
52 				  "level out of range (%u > %u)\n",
53 				  level,
54 				  (unsigned)ARRAY_SIZE(ah->totalSizeDesired));
55 			return false;
56 		}
57 
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,
69 			      ah->firpwr[level]);
70 
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;
76 		break;
77 	}
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;
86 
87 		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
88 			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
89 			      m1ThreshLow[on]);
90 		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
91 			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
92 			      m2ThreshLow[on]);
93 		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
94 			      AR_PHY_SFCORR_M1_THRESH,
95 			      m1Thresh[on]);
96 		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
97 			      AR_PHY_SFCORR_M2_THRESH,
98 			      m2Thresh[on]);
99 		REG_RMW_FIELD(ah, AR_PHY_SFCORR,
100 			      AR_PHY_SFCORR_M2COUNT_THR,
101 			      m2CountThr[on]);
102 		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
103 			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
104 			      m2CountThrLow[on]);
105 
106 		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
107 			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
108 			      m1ThreshLow[on]);
109 		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
110 			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
111 			      m2ThreshLow[on]);
112 		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
113 			      AR_PHY_SFCORR_EXT_M1_THRESH,
114 			      m1Thresh[on]);
115 		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
116 			      AR_PHY_SFCORR_EXT_M2_THRESH,
117 			      m2Thresh[on]);
118 
119 		if (on)
120 			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
121 				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
122 		else
123 			REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
124 				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
125 
126 		if (!on != aniState->ofdmWeakSigDetectOff) {
127 			if (on)
128 				ah->stats.ast_ani_ofdmon++;
129 			else
130 				ah->stats.ast_ani_ofdmoff++;
131 			aniState->ofdmWeakSigDetectOff = !on;
132 		}
133 		break;
134 	}
135 	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
136 		const int weakSigThrCck[] = { 8, 6 };
137 		u32 high = param ? 1 : 0;
138 
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) {
143 			if (high)
144 				ah->stats.ast_ani_cckhigh++;
145 			else
146 				ah->stats.ast_ani_ccklow++;
147 			aniState->cckWeakSigThreshold = high;
148 		}
149 		break;
150 	}
151 	case ATH9K_ANI_FIRSTEP_LEVEL:{
152 		const int firstep[] = { 0, 4, 8 };
153 		u32 level = param;
154 
155 		if (level >= ARRAY_SIZE(firstep)) {
156 			ath_print(common, ATH_DBG_ANI,
157 				  "level out of range (%u > %u)\n",
158 				  level,
159 				  (unsigned) ARRAY_SIZE(firstep));
160 			return false;
161 		}
162 		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
163 			      AR_PHY_FIND_SIG_FIRSTEP,
164 			      firstep[level]);
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;
170 		break;
171 	}
172 	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
173 		const int cycpwrThr1[] =
174 			{ 2, 4, 6, 8, 10, 12, 14, 16 };
175 		u32 level = param;
176 
177 		if (level >= ARRAY_SIZE(cycpwrThr1)) {
178 			ath_print(common, ATH_DBG_ANI,
179 				  "level out of range (%u > %u)\n",
180 				  level,
181 				  (unsigned) ARRAY_SIZE(cycpwrThr1));
182 			return false;
183 		}
184 		REG_RMW_FIELD(ah, AR_PHY_TIMING5,
185 			      AR_PHY_TIMING5_CYCPWR_THR1,
186 			      cycpwrThr1[level]);
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;
192 		break;
193 	}
194 	case ATH9K_ANI_PRESENT:
195 		break;
196 	default:
197 		ath_print(common, ATH_DBG_ANI,
198 			  "invalid cmd %u\n", cmd);
199 		return false;
200 	}
201 
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);
220 
221 	return true;
222 }
223 
224 static void ath9k_hw_update_mibstats(struct ath_hw *ah,
225 				     struct ath9k_mib_stats *stats)
226 {
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);
232 }
233 
234 static void ath9k_ani_restart(struct ath_hw *ah)
235 {
236 	struct ar5416AniState *aniState;
237 	struct ath_common *common = ath9k_hw_common(ah);
238 
239 	if (!DO_ANI(ah))
240 		return;
241 
242 	aniState = ah->curani;
243 	aniState->listenTime = 0;
244 
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");
249 	} else {
250 		aniState->ofdmPhyErrBase =
251 			AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
252 	}
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");
257 	} else {
258 		aniState->cckPhyErrBase =
259 			AR_PHY_COUNTMAX - aniState->cckTrigHigh;
260 	}
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);
269 
270 	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
271 
272 	aniState->ofdmPhyErrCount = 0;
273 	aniState->cckPhyErrCount = 0;
274 }
275 
276 static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
277 {
278 	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
279 	struct ar5416AniState *aniState;
280 	int32_t rssi;
281 
282 	if (!DO_ANI(ah))
283 		return;
284 
285 	aniState = ah->curani;
286 
287 	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
288 		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
289 					 aniState->noiseImmunityLevel + 1)) {
290 			return;
291 		}
292 	}
293 
294 	if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
295 		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
296 					 aniState->spurImmunityLevel + 1)) {
297 			return;
298 		}
299 	}
300 
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);
305 		}
306 		return;
307 	}
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,
313 					 false)) {
314 				ath9k_hw_ani_control(ah,
315 					ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
316 				return;
317 			}
318 		}
319 		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
320 			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
321 					     aniState->firstepLevel + 1);
322 			return;
323 		}
324 	} else if (rssi > aniState->rssiThrLow) {
325 		if (aniState->ofdmWeakSigDetectOff)
326 			ath9k_hw_ani_control(ah,
327 				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
328 				     true);
329 		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
330 			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
331 					     aniState->firstepLevel + 1);
332 		return;
333 	} else {
334 		if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
335 		    !conf_is_ht(conf)) {
336 			if (!aniState->ofdmWeakSigDetectOff)
337 				ath9k_hw_ani_control(ah,
338 				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
339 				     false);
340 			if (aniState->firstepLevel > 0)
341 				ath9k_hw_ani_control(ah,
342 					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
343 			return;
344 		}
345 	}
346 }
347 
348 static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
349 {
350 	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
351 	struct ar5416AniState *aniState;
352 	int32_t rssi;
353 
354 	if (!DO_ANI(ah))
355 		return;
356 
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)) {
361 			return;
362 		}
363 	}
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);
368 		}
369 		return;
370 	}
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);
376 	} else {
377 		if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
378 		    !conf_is_ht(conf)) {
379 			if (aniState->firstepLevel > 0)
380 				ath9k_hw_ani_control(ah,
381 					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
382 		}
383 	}
384 }
385 
386 static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
387 {
388 	struct ar5416AniState *aniState;
389 	int32_t rssi;
390 
391 	aniState = ah->curani;
392 
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))
397 				return;
398 		}
399 	} else {
400 		rssi = BEACON_RSSI(ah);
401 		if (rssi > aniState->rssiThrHigh) {
402 			/* XXX: Handle me */
403 		} else if (rssi > aniState->rssiThrLow) {
404 			if (aniState->ofdmWeakSigDetectOff) {
405 				if (ath9k_hw_ani_control(ah,
406 					 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
407 					 true) == true)
408 					return;
409 			}
410 			if (aniState->firstepLevel > 0) {
411 				if (ath9k_hw_ani_control(ah,
412 					 ATH9K_ANI_FIRSTEP_LEVEL,
413 					 aniState->firstepLevel - 1) == true)
414 					return;
415 			}
416 		} else {
417 			if (aniState->firstepLevel > 0) {
418 				if (ath9k_hw_ani_control(ah,
419 					 ATH9K_ANI_FIRSTEP_LEVEL,
420 					 aniState->firstepLevel - 1) == true)
421 					return;
422 			}
423 		}
424 	}
425 
426 	if (aniState->spurImmunityLevel > 0) {
427 		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
428 					 aniState->spurImmunityLevel - 1))
429 			return;
430 	}
431 
432 	if (aniState->noiseImmunityLevel > 0) {
433 		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
434 				     aniState->noiseImmunityLevel - 1);
435 		return;
436 	}
437 }
438 
439 static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
440 {
441 	struct ar5416AniState *aniState;
442 	u32 txFrameCount, rxFrameCount, cycleCount;
443 	int32_t listenTime;
444 
445 	txFrameCount = REG_READ(ah, AR_TFCNT);
446 	rxFrameCount = REG_READ(ah, AR_RFCNT);
447 	cycleCount = REG_READ(ah, AR_CCCNT);
448 
449 	aniState = ah->curani;
450 	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
451 
452 		listenTime = 0;
453 		ah->stats.ast_ani_lzero++;
454 	} else {
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;
459 	}
460 	aniState->cycleCount = cycleCount;
461 	aniState->txFrameCount = txFrameCount;
462 	aniState->rxFrameCount = rxFrameCount;
463 
464 	return listenTime;
465 }
466 
467 void ath9k_ani_reset(struct ath_hw *ah)
468 {
469 	struct ar5416AniState *aniState;
470 	struct ath9k_channel *chan = ah->curchan;
471 	struct ath_common *common = ath9k_hw_common(ah);
472 	int index;
473 
474 	if (!DO_ANI(ah))
475 		return;
476 
477 	index = ath9k_hw_get_ani_channel_idx(ah, chan);
478 	aniState = &ah->ani[index];
479 	ah->curani = aniState;
480 
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++;
486 
487 		if (ah->opmode == NL80211_IFTYPE_AP) {
488 			/*
489 			 * ath9k_hw_ani_control() will only process items set on
490 			 * ah->ani_function
491 			 */
492 			if (IS_CHAN_2GHZ(chan))
493 				ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
494 						    ATH9K_ANI_FIRSTEP_LEVEL);
495 			else
496 				ah->ani_function = 0;
497 		}
498 
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);
506 
507 		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
508 				     ATH9K_RX_FILTER_PHYERR);
509 
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;
519 		}
520 		ath9k_ani_restart(ah);
521 		return;
522 	}
523 
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);
539 
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);
545 }
546 
547 void ath9k_hw_ani_monitor(struct ath_hw *ah,
548 			  struct ath9k_channel *chan)
549 {
550 	struct ar5416AniState *aniState;
551 	struct ath_common *common = ath9k_hw_common(ah);
552 	int32_t listenTime;
553 	u32 phyCnt1, phyCnt2;
554 	u32 ofdmPhyErrCnt, cckPhyErrCnt;
555 
556 	if (!DO_ANI(ah))
557 		return;
558 
559 	aniState = ah->curani;
560 
561 	listenTime = ath9k_hw_ani_get_listen_time(ah);
562 	if (listenTime < 0) {
563 		ah->stats.ast_ani_lneg++;
564 		ath9k_ani_restart(ah);
565 		return;
566 	}
567 
568 	aniState->listenTime += listenTime;
569 
570 	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
571 
572 	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
573 	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
574 
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",
581 				  phyCnt1,
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);
587 		}
588 		if (phyCnt2 < aniState->cckPhyErrBase) {
589 			ath_print(common, ATH_DBG_ANI,
590 				  "phyCnt2 0x%x, resetting "
591 				  "counter value to 0x%x\n",
592 				  phyCnt2,
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);
598 		}
599 		return;
600 	}
601 
602 	ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
603 	ah->stats.ast_ani_ofdmerrs +=
604 		ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
605 	aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
606 
607 	cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
608 	ah->stats.ast_ani_cckerrs +=
609 		cckPhyErrCnt - aniState->cckPhyErrCount;
610 	aniState->cckPhyErrCount = cckPhyErrCnt;
611 
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 /
626 			   1000) {
627 			ath9k_hw_ani_cck_err_trigger(ah);
628 			ath9k_ani_restart(ah);
629 		}
630 	}
631 }
632 EXPORT_SYMBOL(ath9k_hw_ani_monitor);
633 
634 void ath9k_enable_mib_counters(struct ath_hw *ah)
635 {
636 	struct ath_common *common = ath9k_hw_common(ah);
637 
638 	ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
639 
640 	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
641 
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)
646 		  & 0x0f);
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);
649 }
650 
651 /* Freeze the MIB counters, get the stats and then clear them */
652 void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
653 {
654 	struct ath_common *common = ath9k_hw_common(ah);
655 
656 	ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
657 
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);
663 }
664 
665 u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
666 				  u32 *rxc_pcnt,
667 				  u32 *rxf_pcnt,
668 				  u32 *txf_pcnt)
669 {
670 	struct ath_common *common = ath9k_hw_common(ah);
671 	static u32 cycles, rx_clear, rx_frame, tx_frame;
672 	u32 good = 1;
673 
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);
678 
679 	if (cycles == 0 || cycles > cc) {
680 		ath_print(common, ATH_DBG_ANI,
681 			  "cycle counter wrap. ExtBusy = 0\n");
682 		good = 0;
683 	} else {
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;
688 
689 		if (cc_d != 0) {
690 			*rxc_pcnt = rc_d * 100 / cc_d;
691 			*rxf_pcnt = rf_d * 100 / cc_d;
692 			*txf_pcnt = tf_d * 100 / cc_d;
693 		} else {
694 			good = 0;
695 		}
696 	}
697 
698 	cycles = cc;
699 	rx_frame = rf;
700 	rx_clear = rc;
701 	tx_frame = tf;
702 
703 	return good;
704 }
705 
706 /*
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.
710  */
711 void ath9k_hw_procmibevent(struct ath_hw *ah)
712 {
713 	u32 phyCnt1, phyCnt2;
714 
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);
720 
721 	/* Clear the mib counters and save them in the stats */
722 	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
723 
724 	if (!DO_ANI(ah))
725 		return;
726 
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;
734 
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;
740 
741 		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
742 		ah->stats.ast_ani_cckerrs +=
743 			cckPhyErrCnt - aniState->cckPhyErrCount;
744 		aniState->cckPhyErrCount = cckPhyErrCnt;
745 
746 		/*
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.
751 		 */
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);
758 	}
759 }
760 EXPORT_SYMBOL(ath9k_hw_procmibevent);
761 
762 void ath9k_hw_ani_setup(struct ath_hw *ah)
763 {
764 	int i;
765 
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 };
770 
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];
776 	}
777 }
778 
779 void ath9k_hw_ani_init(struct ath_hw *ah)
780 {
781 	struct ath_common *common = ath9k_hw_common(ah);
782 	int i;
783 
784 	ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
785 
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;
804 	}
805 
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);
811 
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);
815 
816 	ah->aniperiod = ATH9K_ANI_PERIOD;
817 	if (ah->config.enable_ani)
818 		ah->proc_phyerr |= HAL_PROCESS_ANI;
819 }
820 
821 void ath9k_hw_ani_disable(struct ath_hw *ah)
822 {
823 	ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n");
824 
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);
828 }
829