• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/net/wireless/ath/ath9k/
1/*
2 * Copyright (c) 2008-2010 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#include "hw-ops.h"
19
20struct ani_ofdm_level_entry {
21	int spur_immunity_level;
22	int fir_step_level;
23	int ofdm_weak_signal_on;
24};
25
26/* values here are relative to the INI */
27
28/*
29 * Legend:
30 *
31 * SI: Spur immunity
32 * FS: FIR Step
33 * WS: OFDM / CCK Weak Signal detection
34 * MRC-CCK: Maximal Ratio Combining for CCK
35 */
36
37static const struct ani_ofdm_level_entry ofdm_level_table[] = {
38	/* SI  FS  WS */
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 */
49};
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 */
56
57/*
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
62 * domain.
63 *
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.
71 *
72 * Regardless of alignment in time, the antenna signals add constructively after
73 * FFT and improve your reception. For more information:
74 *
75 * http://en.wikipedia.org/wiki/Maximal-ratio_combining
76 */
77
78struct ani_cck_level_entry {
79	int fir_step_level;
80	int mrc_cck_on;
81};
82
83static const struct ani_cck_level_entry cck_level_table[] = {
84	/* FS  MRC-CCK  */
85	{  0,  1  }, /* lvl 0 */
86	{  1,  1  }, /* lvl 1 */
87	{  2,  1  }, /* lvl 2  (default) */
88	{  3,  1  }, /* lvl 3 */
89	{  4,  0  }, /* lvl 4 */
90	{  5,  0  }, /* lvl 5 */
91	{  6,  0  }, /* lvl 6 */
92	{  7,  0  }, /* lvl 7 (only for high rssi) */
93	{  8,  0  }  /* lvl 8 (only for high rssi) */
94};
95
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 */
104
105/* Private to ani.c */
106static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
107{
108	ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
109}
110
111int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
112				 struct ath9k_channel *chan)
113{
114	int i;
115
116	for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
117		if (ah->ani[i].c &&
118		    ah->ani[i].c->channel == chan->channel)
119			return i;
120		if (ah->ani[i].c == NULL) {
121			ah->ani[i].c = chan;
122			return i;
123		}
124	}
125
126	ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
127		  "No more channel states left. Using channel 0\n");
128
129	return 0;
130}
131
132static void ath9k_hw_update_mibstats(struct ath_hw *ah,
133				     struct ath9k_mib_stats *stats)
134{
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);
140}
141
142static void ath9k_ani_restart_old(struct ath_hw *ah)
143{
144	struct ar5416AniState *aniState;
145	struct ath_common *common = ath9k_hw_common(ah);
146
147	if (!DO_ANI(ah))
148		return;
149
150	aniState = ah->curani;
151	aniState->listenTime = 0;
152
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");
157	} else {
158		aniState->ofdmPhyErrBase =
159			AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
160	}
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");
165	} else {
166		aniState->cckPhyErrBase =
167			AR_PHY_COUNTMAX - aniState->cckTrigHigh;
168	}
169	ath_print(common, ATH_DBG_ANI,
170		  "Writing ofdmbase=%u   cckbase=%u\n",
171		  aniState->ofdmPhyErrBase,
172		  aniState->cckPhyErrBase);
173
174	ENABLE_REGWRITE_BUFFER(ah);
175
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);
180
181	REGWRITE_BUFFER_FLUSH(ah);
182	DISABLE_REGWRITE_BUFFER(ah);
183
184	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
185
186	aniState->ofdmPhyErrCount = 0;
187	aniState->cckPhyErrCount = 0;
188}
189
190static void ath9k_ani_restart_new(struct ath_hw *ah)
191{
192	struct ar5416AniState *aniState;
193	struct ath_common *common = ath9k_hw_common(ah);
194
195	if (!DO_ANI(ah))
196		return;
197
198	aniState = ah->curani;
199	aniState->listenTime = 0;
200
201	aniState->ofdmPhyErrBase = 0;
202	aniState->cckPhyErrBase = 0;
203
204	ath_print(common, ATH_DBG_ANI,
205		  "Writing ofdmbase=%08x   cckbase=%08x\n",
206		  aniState->ofdmPhyErrBase,
207		  aniState->cckPhyErrBase);
208
209	ENABLE_REGWRITE_BUFFER(ah);
210
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);
215
216	REGWRITE_BUFFER_FLUSH(ah);
217	DISABLE_REGWRITE_BUFFER(ah);
218
219	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
220
221	aniState->ofdmPhyErrCount = 0;
222	aniState->cckPhyErrCount = 0;
223}
224
225static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
226{
227	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
228	struct ar5416AniState *aniState;
229	int32_t rssi;
230
231	if (!DO_ANI(ah))
232		return;
233
234	aniState = ah->curani;
235
236	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
237		if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
238					 aniState->noiseImmunityLevel + 1)) {
239			return;
240		}
241	}
242
243	if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
244		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
245					 aniState->spurImmunityLevel + 1)) {
246			return;
247		}
248	}
249
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);
254		}
255		return;
256	}
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,
262					 false)) {
263				ath9k_hw_ani_control(ah,
264					ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
265				return;
266			}
267		}
268		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
269			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
270					     aniState->firstepLevel + 1);
271			return;
272		}
273	} else if (rssi > aniState->rssiThrLow) {
274		if (aniState->ofdmWeakSigDetectOff)
275			ath9k_hw_ani_control(ah,
276				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
277				     true);
278		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
279			ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
280					     aniState->firstepLevel + 1);
281		return;
282	} else {
283		if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
284		    !conf_is_ht(conf)) {
285			if (!aniState->ofdmWeakSigDetectOff)
286				ath9k_hw_ani_control(ah,
287				     ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
288				     false);
289			if (aniState->firstepLevel > 0)
290				ath9k_hw_ani_control(ah,
291					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
292			return;
293		}
294	}
295}
296
297static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
298{
299	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
300	struct ar5416AniState *aniState;
301	int32_t rssi;
302
303	if (!DO_ANI(ah))
304		return;
305
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)) {
310			return;
311		}
312	}
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);
317		}
318		return;
319	}
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);
325	} else {
326		if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
327		    !conf_is_ht(conf)) {
328			if (aniState->firstepLevel > 0)
329				ath9k_hw_ani_control(ah,
330					     ATH9K_ANI_FIRSTEP_LEVEL, 0);
331		}
332	}
333}
334
335/* Adjust the OFDM Noise Immunity Level */
336static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
337{
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;
342
343	aniState->noiseFloor = BEACON_RSSI(ah);
344
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);
350
351	aniState->ofdmNoiseImmunityLevel = immunityLevel;
352
353	entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
354	entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
355
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);
360
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);
366
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,
374					     true);
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);
380	}
381}
382
383static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
384{
385	struct ar5416AniState *aniState;
386
387	if (!DO_ANI(ah))
388		return;
389
390	aniState = ah->curani;
391
392	if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
393		ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
394}
395
396/*
397 * Set the ANI settings to match an CCK level.
398 */
399static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
400{
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;
405
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);
412
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;
418
419	aniState->cckNoiseImmunityLevel = immunityLevel;
420
421	entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
422	entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
423
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);
429
430	/* Skip MRC CCK for pre AR9003 families */
431	if (!AR_SREV_9300_20_OR_LATER(ah))
432		return;
433
434	if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
435		ath9k_hw_ani_control(ah,
436				     ATH9K_ANI_MRC_CCK,
437				     entry_cck->mrc_cck_on);
438}
439
440static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
441{
442	struct ar5416AniState *aniState;
443
444	if (!DO_ANI(ah))
445		return;
446
447	aniState = ah->curani;
448
449	if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
450		ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
451}
452
453static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
454{
455	struct ar5416AniState *aniState;
456	int32_t rssi;
457
458	aniState = ah->curani;
459
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))
464				return;
465		}
466	} else {
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,
473					 true) == true)
474					return;
475			}
476			if (aniState->firstepLevel > 0) {
477				if (ath9k_hw_ani_control(ah,
478					 ATH9K_ANI_FIRSTEP_LEVEL,
479					 aniState->firstepLevel - 1) == true)
480					return;
481			}
482		} else {
483			if (aniState->firstepLevel > 0) {
484				if (ath9k_hw_ani_control(ah,
485					 ATH9K_ANI_FIRSTEP_LEVEL,
486					 aniState->firstepLevel - 1) == true)
487					return;
488			}
489		}
490	}
491
492	if (aniState->spurImmunityLevel > 0) {
493		if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
494					 aniState->spurImmunityLevel - 1))
495			return;
496	}
497
498	if (aniState->noiseImmunityLevel > 0) {
499		ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
500				     aniState->noiseImmunityLevel - 1);
501		return;
502	}
503}
504
505/*
506 * only lower either OFDM or CCK errors per turn
507 * we lower the other one next time
508 */
509static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
510{
511	struct ar5416AniState *aniState;
512
513	aniState = ah->curani;
514
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);
519		return;
520	}
521
522	/* lower CCK noise immunity */
523	if (aniState->cckNoiseImmunityLevel > 0)
524		ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
525}
526
527static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
528{
529	struct ath9k_channel *chan = ah->curchan;
530	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
531	u8 clockrate; /* in MHz */
532
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;
539	else
540		clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
541
542	if (conf_is_ht40(conf))
543		return clockrate * 2;
544
545	return clockrate;
546}
547
548static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
549{
550	struct ar5416AniState *aniState;
551	struct ath_common *common = ath9k_hw_common(ah);
552	u32 txFrameCount, rxFrameCount, cycleCount;
553	int32_t listenTime;
554
555	txFrameCount = REG_READ(ah, AR_TFCNT);
556	rxFrameCount = REG_READ(ah, AR_RFCNT);
557	cycleCount = REG_READ(ah, AR_CCCNT);
558
559	aniState = ah->curani;
560	if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
561		listenTime = 0;
562		ah->stats.ast_ani_lzero++;
563		ath_print(common, ATH_DBG_ANI,
564			  "1st call: aniState->cycleCount=%d\n",
565			  aniState->cycleCount);
566	} else {
567		int32_t ccdelta = cycleCount - aniState->cycleCount;
568		int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
569		int32_t tfdelta = txFrameCount - aniState->txFrameCount;
570		int32_t clock_rate;
571
572		/*
573		 * convert HW counter values to ms using mode
574		 * specifix clock rate
575		 */
576		clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;;
577
578		listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate;
579
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);
584	}
585
586	aniState->cycleCount = cycleCount;
587	aniState->txFrameCount = txFrameCount;
588	aniState->rxFrameCount = rxFrameCount;
589
590	return listenTime;
591}
592
593static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
594{
595	struct ar5416AniState *aniState;
596	struct ath9k_channel *chan = ah->curchan;
597	struct ath_common *common = ath9k_hw_common(ah);
598	int index;
599
600	if (!DO_ANI(ah))
601		return;
602
603	index = ath9k_hw_get_ani_channel_idx(ah, chan);
604	aniState = &ah->ani[index];
605	ah->curani = aniState;
606
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++;
612
613		if (ah->opmode == NL80211_IFTYPE_AP) {
614			/*
615			 * ath9k_hw_ani_control() will only process items set on
616			 * ah->ani_function
617			 */
618			if (IS_CHAN_2GHZ(chan))
619				ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
620						    ATH9K_ANI_FIRSTEP_LEVEL);
621			else
622				ah->ani_function = 0;
623		}
624
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);
632
633		ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
634				     ATH9K_RX_FILTER_PHYERR);
635
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;
645		}
646		ath9k_ani_restart_old(ah);
647		return;
648	}
649
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);
665
666	ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
667			     ~ATH9K_RX_FILTER_PHYERR);
668	ath9k_ani_restart_old(ah);
669
670	ENABLE_REGWRITE_BUFFER(ah);
671
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);
674
675	REGWRITE_BUFFER_FLUSH(ah);
676	DISABLE_REGWRITE_BUFFER(ah);
677}
678
679/*
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.
683 */
684static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
685{
686	struct ar5416AniState *aniState = ah->curani;
687	struct ath9k_channel *chan = ah->curchan;
688	struct ath_common *common = ath9k_hw_common(ah);
689
690	if (!DO_ANI(ah))
691		return;
692
693	BUG_ON(aniState == NULL);
694	ah->stats.ast_ani_reset++;
695
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;
703		} else
704			ah->ani_function = 0;
705	}
706
707	/* always allow mode (on/off) to be controlled */
708	ah->ani_function |= ATH9K_ANI_MODE;
709
710	if (is_scanning ||
711	    (ah->opmode != NL80211_IFTYPE_STATION &&
712	     ah->opmode != NL80211_IFTYPE_ADHOC)) {
713		/*
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.
718		 */
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 "
726				  "ofdm:%d cck:%d\n",
727				  ah->opmode,
728				  chan->channel,
729				  chan->channelFlags,
730				  is_scanning,
731				  aniState->ofdmNoiseImmunityLevel,
732				  aniState->cckNoiseImmunityLevel);
733
734			ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
735			ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
736		}
737	} else {
738		/*
739		 * restore historical levels for this channel
740		 */
741		ath_print(common, ATH_DBG_ANI,
742			  "Restore history: opmode %u "
743			  "chan %d Mhz/0x%x is_scanning=%d "
744			  "ofdm:%d cck:%d\n",
745			  ah->opmode,
746			  chan->channel,
747			  chan->channelFlags,
748			  is_scanning,
749			  aniState->ofdmNoiseImmunityLevel,
750			  aniState->cckNoiseImmunityLevel);
751
752			ath9k_hw_set_ofdm_nil(ah,
753					      aniState->ofdmNoiseImmunityLevel);
754			ath9k_hw_set_cck_nil(ah,
755					     aniState->cckNoiseImmunityLevel);
756	}
757
758	/*
759	 * enable phy counters if hw supports or if not, enable phy
760	 * interrupts (so we can count each one)
761	 */
762	ath9k_ani_restart_new(ah);
763
764	ENABLE_REGWRITE_BUFFER(ah);
765
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);
768
769	REGWRITE_BUFFER_FLUSH(ah);
770	DISABLE_REGWRITE_BUFFER(ah);
771}
772
773static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
774				     struct ath9k_channel *chan)
775{
776	struct ar5416AniState *aniState;
777	struct ath_common *common = ath9k_hw_common(ah);
778	int32_t listenTime;
779	u32 phyCnt1, phyCnt2;
780	u32 ofdmPhyErrCnt, cckPhyErrCnt;
781
782	if (!DO_ANI(ah))
783		return;
784
785	aniState = ah->curani;
786
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);
791		return;
792	}
793
794	aniState->listenTime += listenTime;
795
796	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
797
798	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
799	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
800
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",
807				  phyCnt1,
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);
813		}
814		if (phyCnt2 < aniState->cckPhyErrBase) {
815			ath_print(common, ATH_DBG_ANI,
816				  "phyCnt2 0x%x, resetting "
817				  "counter value to 0x%x\n",
818				  phyCnt2,
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);
824		}
825		return;
826	}
827
828	ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
829	ah->stats.ast_ani_ofdmerrs +=
830		ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
831	aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
832
833	cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
834	ah->stats.ast_ani_cckerrs +=
835		cckPhyErrCnt - aniState->cckPhyErrCount;
836	aniState->cckPhyErrCount = cckPhyErrCnt;
837
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 /
852			   1000) {
853			ath9k_hw_ani_cck_err_trigger_old(ah);
854			ath9k_ani_restart_old(ah);
855		}
856	}
857}
858
859static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
860				     struct ath9k_channel *chan)
861{
862	struct ar5416AniState *aniState;
863	struct ath_common *common = ath9k_hw_common(ah);
864	int32_t listenTime;
865	u32 phyCnt1, phyCnt2;
866	u32 ofdmPhyErrCnt, cckPhyErrCnt;
867	u32 ofdmPhyErrRate, cckPhyErrRate;
868
869	if (!DO_ANI(ah))
870		return;
871
872	aniState = ah->curani;
873	if (WARN_ON(!aniState))
874		return;
875
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",
882			  listenTime);
883		ath9k_ani_restart_new(ah);
884		return;
885	}
886
887	aniState->listenTime += listenTime;
888
889	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
890
891	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
892	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
893
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",
900				  phyCnt1,
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);
906		}
907		if (phyCnt2 < aniState->cckPhyErrBase) {
908			ath_print(common, ATH_DBG_ANI,
909				  "phyCnt2 0x%x, resetting "
910				  "counter value to 0x%x\n",
911				  phyCnt2,
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);
917		}
918		return;
919	}
920
921	ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
922	ah->stats.ast_ani_ofdmerrs +=
923		ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
924	aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
925
926	cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
927	ah->stats.ast_ani_cckerrs +=
928		cckPhyErrCnt - aniState->cckPhyErrCount;
929	aniState->cckPhyErrCount = cckPhyErrCnt;
930
931	ath_print(common, ATH_DBG_ANI,
932		  "Errors: OFDM=0x%08x-0x%08x=%d   "
933		  "CCK=0x%08x-0x%08x=%d\n",
934		  phyCnt1,
935		  aniState->ofdmPhyErrBase,
936		  ofdmPhyErrCnt,
937		  phyCnt2,
938		  aniState->cckPhyErrBase,
939		  cckPhyErrCnt);
940
941	ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
942			 aniState->listenTime;
943	cckPhyErrRate =  aniState->cckPhyErrCount * 1000 /
944			 aniState->listenTime;
945
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);
952
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,
962				  ofdmPhyErrRate,
963				  aniState->ofdmTrigLow,
964				  aniState->cckNoiseImmunityLevel,
965				  cckPhyErrRate,
966				  aniState->cckTrigLow);
967			ath9k_hw_ani_lower_immunity(ah);
968			aniState->ofdmsTurn = !aniState->ofdmsTurn;
969		}
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,
985				  ofdmPhyErrRate,
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,
996				 cckPhyErrRate,
997				 aniState->cckTrigHigh);
998			ath9k_hw_ani_cck_err_trigger_new(ah);
999			ath9k_ani_restart_new(ah);
1000			aniState->ofdmsTurn = true;
1001		}
1002	}
1003}
1004
1005void ath9k_enable_mib_counters(struct ath_hw *ah)
1006{
1007	struct ath_common *common = ath9k_hw_common(ah);
1008
1009	ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
1010
1011	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1012
1013	ENABLE_REGWRITE_BUFFER(ah);
1014
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)
1019		  & 0x0f);
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);
1022
1023	REGWRITE_BUFFER_FLUSH(ah);
1024	DISABLE_REGWRITE_BUFFER(ah);
1025}
1026
1027/* Freeze the MIB counters, get the stats and then clear them */
1028void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
1029{
1030	struct ath_common *common = ath9k_hw_common(ah);
1031
1032	ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
1033
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);
1039}
1040EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
1041
1042u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
1043				  u32 *rxc_pcnt,
1044				  u32 *rxf_pcnt,
1045				  u32 *txf_pcnt)
1046{
1047	struct ath_common *common = ath9k_hw_common(ah);
1048	static u32 cycles, rx_clear, rx_frame, tx_frame;
1049	u32 good = 1;
1050
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);
1055
1056	if (cycles == 0 || cycles > cc) {
1057		ath_print(common, ATH_DBG_ANI,
1058			  "cycle counter wrap. ExtBusy = 0\n");
1059		good = 0;
1060	} else {
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;
1065
1066		if (cc_d != 0) {
1067			*rxc_pcnt = rc_d * 100 / cc_d;
1068			*rxf_pcnt = rf_d * 100 / cc_d;
1069			*txf_pcnt = tf_d * 100 / cc_d;
1070		} else {
1071			good = 0;
1072		}
1073	}
1074
1075	cycles = cc;
1076	rx_frame = rf;
1077	rx_clear = rc;
1078	tx_frame = tf;
1079
1080	return good;
1081}
1082
1083/*
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.
1087 */
1088static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
1089{
1090	u32 phyCnt1, phyCnt2;
1091
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);
1097
1098	/* Clear the mib counters and save them in the stats */
1099	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1100
1101	if (!DO_ANI(ah)) {
1102		/*
1103		 * We must always clear the interrupt cause by
1104		 * resetting the phy error regs.
1105		 */
1106		REG_WRITE(ah, AR_PHY_ERR_1, 0);
1107		REG_WRITE(ah, AR_PHY_ERR_2, 0);
1108		return;
1109	}
1110
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;
1118
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;
1124
1125		cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
1126		ah->stats.ast_ani_cckerrs +=
1127			cckPhyErrCnt - aniState->cckPhyErrCount;
1128		aniState->cckPhyErrCount = cckPhyErrCnt;
1129
1130		/*
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.
1135		 */
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);
1142	}
1143}
1144
1145/*
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.
1149 */
1150static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
1151{
1152	u32 phyCnt1, phyCnt2;
1153
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);
1159
1160	/* Clear the mib counters and save them in the stats */
1161	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1162
1163	if (!DO_ANI(ah)) {
1164		/*
1165		 * We must always clear the interrupt cause by
1166		 * resetting the phy error regs.
1167		 */
1168		REG_WRITE(ah, AR_PHY_ERR_1, 0);
1169		REG_WRITE(ah, AR_PHY_ERR_2, 0);
1170		return;
1171	}
1172
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);
1176
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);
1181}
1182
1183void ath9k_hw_ani_setup(struct ath_hw *ah)
1184{
1185	int i;
1186
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 };
1191
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];
1197	}
1198}
1199
1200void ath9k_hw_ani_init(struct ath_hw *ah)
1201{
1202	struct ath_common *common = ath9k_hw_common(ah);
1203	int i;
1204
1205	ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
1206
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;
1212
1213			ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
1214			ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW;
1215
1216			ah->ani[i].spurImmunityLevel =
1217				ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
1218
1219			ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
1220
1221			ah->ani[i].ofdmPhyErrBase = 0;
1222			ah->ani[i].cckPhyErrBase = 0;
1223
1224			if (AR_SREV_9300_20_OR_LATER(ah))
1225				ah->ani[i].mrcCCKOff =
1226					!ATH9K_ANI_ENABLE_MRC_CCK;
1227			else
1228				ah->ani[i].mrcCCKOff = true;
1229
1230			ah->ani[i].ofdmsTurn = true;
1231		} else {
1232			ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1233			ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
1234
1235			ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1236			ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD;
1237
1238			ah->ani[i].spurImmunityLevel =
1239				ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
1240			ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
1241
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;
1248		}
1249
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;
1255	}
1256
1257	/*
1258	 * since we expect some ongoing maintenance on the tables, let's sanity
1259	 * check here default level should not modify INI setting.
1260	 */
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;
1264
1265		entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL];
1266		entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL];
1267
1268		ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
1269		ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
1270	} else {
1271		ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
1272		ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
1273	}
1274
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);
1280
1281	ENABLE_REGWRITE_BUFFER(ah);
1282
1283	REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
1284	REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
1285
1286	REGWRITE_BUFFER_FLUSH(ah);
1287	DISABLE_REGWRITE_BUFFER(ah);
1288
1289	ath9k_enable_mib_counters(ah);
1290
1291	if (ah->config.enable_ani)
1292		ah->proc_phyerr |= HAL_PROCESS_ANI;
1293}
1294
1295void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
1296{
1297	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1298	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1299
1300	priv_ops->ani_reset = ath9k_ani_reset_old;
1301	priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old;
1302
1303	ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
1304	ops->ani_monitor = ath9k_hw_ani_monitor_old;
1305
1306	ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
1307}
1308
1309void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
1310{
1311	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1312	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1313
1314	priv_ops->ani_reset = ath9k_ani_reset_new;
1315	priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
1316
1317	ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
1318	ops->ani_monitor = ath9k_hw_ani_monitor_new;
1319
1320	ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");
1321}
1322