blob: 9856a1b0ca2dbcfe7090bc88ad1daec8c2a45798 [file] [log] [blame]
Sujithf1dc5602008-10-29 10:16:30 +05301/*
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04002 * Copyright (c) 2008-2010 Atheros Communications Inc.
Sujithf1dc5602008-10-29 10:16:30 +05303 *
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
Nikitas Angelinasbbce80e2010-09-08 22:25:42 +010017#include <linux/kernel.h>
Luis R. Rodriguezcfe8cba2009-09-13 23:39:31 -070018#include "hw.h"
Felix Fietkauc16fcb42010-04-15 17:38:39 -040019#include "hw-ops.h"
Sujithf1dc5602008-10-29 10:16:30 +053020
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -040021struct ani_ofdm_level_entry {
22 int spur_immunity_level;
23 int fir_step_level;
24 int ofdm_weak_signal_on;
25};
26
27/* values here are relative to the INI */
28
29/*
30 * Legend:
31 *
32 * SI: Spur immunity
33 * FS: FIR Step
34 * WS: OFDM / CCK Weak Signal detection
35 * MRC-CCK: Maximal Ratio Combining for CCK
36 */
37
38static const struct ani_ofdm_level_entry ofdm_level_table[] = {
39 /* SI FS WS */
40 { 0, 0, 1 }, /* lvl 0 */
41 { 1, 1, 1 }, /* lvl 1 */
42 { 2, 2, 1 }, /* lvl 2 */
43 { 3, 2, 1 }, /* lvl 3 (default) */
44 { 4, 3, 1 }, /* lvl 4 */
45 { 5, 4, 1 }, /* lvl 5 */
46 { 6, 5, 1 }, /* lvl 6 */
47 { 7, 6, 1 }, /* lvl 7 */
48 { 7, 7, 1 }, /* lvl 8 */
49 { 7, 8, 0 } /* lvl 9 */
50};
51#define ATH9K_ANI_OFDM_NUM_LEVEL \
Nikitas Angelinasbbce80e2010-09-08 22:25:42 +010052 ARRAY_SIZE(ofdm_level_table)
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -040053#define ATH9K_ANI_OFDM_MAX_LEVEL \
54 (ATH9K_ANI_OFDM_NUM_LEVEL-1)
55#define ATH9K_ANI_OFDM_DEF_LEVEL \
56 3 /* default level - matches the INI settings */
57
58/*
59 * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
60 * With OFDM for single stream you just add up all antenna inputs, you're
61 * only interested in what you get after FFT. Signal aligment is also not
62 * required for OFDM because any phase difference adds up in the frequency
63 * domain.
64 *
65 * MRC requires extra work for use with CCK. You need to align the antenna
66 * signals from the different antenna before you can add the signals together.
67 * You need aligment of signals as CCK is in time domain, so addition can cancel
68 * your signal completely if phase is 180 degrees (think of adding sine waves).
69 * You also need to remove noise before the addition and this is where ANI
70 * MRC CCK comes into play. One of the antenna inputs may be stronger but
71 * lower SNR, so just adding after alignment can be dangerous.
72 *
73 * Regardless of alignment in time, the antenna signals add constructively after
74 * FFT and improve your reception. For more information:
75 *
76 * http://en.wikipedia.org/wiki/Maximal-ratio_combining
77 */
78
79struct ani_cck_level_entry {
80 int fir_step_level;
81 int mrc_cck_on;
82};
83
84static const struct ani_cck_level_entry cck_level_table[] = {
85 /* FS MRC-CCK */
86 { 0, 1 }, /* lvl 0 */
87 { 1, 1 }, /* lvl 1 */
88 { 2, 1 }, /* lvl 2 (default) */
89 { 3, 1 }, /* lvl 3 */
90 { 4, 0 }, /* lvl 4 */
91 { 5, 0 }, /* lvl 5 */
92 { 6, 0 }, /* lvl 6 */
93 { 7, 0 }, /* lvl 7 (only for high rssi) */
94 { 8, 0 } /* lvl 8 (only for high rssi) */
95};
96
97#define ATH9K_ANI_CCK_NUM_LEVEL \
Nikitas Angelinasbbce80e2010-09-08 22:25:42 +010098 ARRAY_SIZE(cck_level_table)
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -040099#define ATH9K_ANI_CCK_MAX_LEVEL \
100 (ATH9K_ANI_CCK_NUM_LEVEL-1)
101#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
102 (ATH9K_ANI_CCK_NUM_LEVEL-3)
103#define ATH9K_ANI_CCK_DEF_LEVEL \
104 2 /* default level - matches the INI settings */
105
Luis R. Rodriguezac0bb762010-06-12 00:33:42 -0400106/* Private to ani.c */
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400107static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
Luis R. Rodriguezac0bb762010-06-12 00:33:42 -0400108{
109 ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
110}
111
Felix Fietkau71ea4202010-10-04 20:09:46 +0200112static bool use_new_ani(struct ath_hw *ah)
113{
114 return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
115}
116
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400117int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
118 struct ath9k_channel *chan)
Sujithf1dc5602008-10-29 10:16:30 +0530119{
Sujithf1dc5602008-10-29 10:16:30 +0530120 int i;
121
Sujith2660b812009-02-09 13:27:26 +0530122 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
123 if (ah->ani[i].c &&
124 ah->ani[i].c->channel == chan->channel)
Sujithf1dc5602008-10-29 10:16:30 +0530125 return i;
Sujith2660b812009-02-09 13:27:26 +0530126 if (ah->ani[i].c == NULL) {
127 ah->ani[i].c = chan;
Sujithf1dc5602008-10-29 10:16:30 +0530128 return i;
129 }
130 }
131
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700132 ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
133 "No more channel states left. Using channel 0\n");
Sujithf1dc5602008-10-29 10:16:30 +0530134
135 return 0;
136}
137
Sujithcbe61d82009-02-09 13:27:12 +0530138static void ath9k_hw_update_mibstats(struct ath_hw *ah,
Sujithf1dc5602008-10-29 10:16:30 +0530139 struct ath9k_mib_stats *stats)
140{
141 stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
142 stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
143 stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
144 stats->rts_good += REG_READ(ah, AR_RTS_OK);
145 stats->beacons += REG_READ(ah, AR_BEACON_CNT);
146}
147
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400148static void ath9k_ani_restart_old(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530149{
Sujithf1dc5602008-10-29 10:16:30 +0530150 struct ar5416AniState *aniState;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700151 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530152
153 if (!DO_ANI(ah))
154 return;
155
Sujith2660b812009-02-09 13:27:26 +0530156 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530157 aniState->listenTime = 0;
Sujithf1dc5602008-10-29 10:16:30 +0530158
Sujith1aa8e842009-08-13 09:34:25 +0530159 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
160 aniState->ofdmPhyErrBase = 0;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700161 ath_print(common, ATH_DBG_ANI,
162 "OFDM Trigger is too high for hw counters\n");
Sujith1aa8e842009-08-13 09:34:25 +0530163 } else {
164 aniState->ofdmPhyErrBase =
165 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
Sujithf1dc5602008-10-29 10:16:30 +0530166 }
Sujith1aa8e842009-08-13 09:34:25 +0530167 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
168 aniState->cckPhyErrBase = 0;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700169 ath_print(common, ATH_DBG_ANI,
170 "CCK Trigger is too high for hw counters\n");
Sujith1aa8e842009-08-13 09:34:25 +0530171 } else {
172 aniState->cckPhyErrBase =
173 AR_PHY_COUNTMAX - aniState->cckTrigHigh;
174 }
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700175 ath_print(common, ATH_DBG_ANI,
176 "Writing ofdmbase=%u cckbase=%u\n",
177 aniState->ofdmPhyErrBase,
178 aniState->cckPhyErrBase);
Sujith7d0d0df2010-04-16 11:53:57 +0530179
180 ENABLE_REGWRITE_BUFFER(ah);
181
Sujith1aa8e842009-08-13 09:34:25 +0530182 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
183 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
184 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
185 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
186
Sujith7d0d0df2010-04-16 11:53:57 +0530187 REGWRITE_BUFFER_FLUSH(ah);
Sujith7d0d0df2010-04-16 11:53:57 +0530188
Sujith1aa8e842009-08-13 09:34:25 +0530189 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
190
Sujithf1dc5602008-10-29 10:16:30 +0530191 aniState->ofdmPhyErrCount = 0;
192 aniState->cckPhyErrCount = 0;
193}
194
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400195static void ath9k_ani_restart_new(struct ath_hw *ah)
196{
197 struct ar5416AniState *aniState;
198 struct ath_common *common = ath9k_hw_common(ah);
199
200 if (!DO_ANI(ah))
201 return;
202
203 aniState = ah->curani;
204 aniState->listenTime = 0;
205
206 aniState->ofdmPhyErrBase = 0;
207 aniState->cckPhyErrBase = 0;
208
209 ath_print(common, ATH_DBG_ANI,
210 "Writing ofdmbase=%08x cckbase=%08x\n",
211 aniState->ofdmPhyErrBase,
212 aniState->cckPhyErrBase);
213
214 ENABLE_REGWRITE_BUFFER(ah);
215
216 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
217 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
218 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
219 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
220
221 REGWRITE_BUFFER_FLUSH(ah);
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400222
223 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
224
225 aniState->ofdmPhyErrCount = 0;
226 aniState->cckPhyErrCount = 0;
227}
228
229static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530230{
Luis R. Rodriguezb002a4a2009-09-13 00:03:27 -0700231 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
Sujithf1dc5602008-10-29 10:16:30 +0530232 struct ar5416AniState *aniState;
Sujithf1dc5602008-10-29 10:16:30 +0530233 int32_t rssi;
234
235 if (!DO_ANI(ah))
236 return;
237
Sujith2660b812009-02-09 13:27:26 +0530238 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530239
240 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
241 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
242 aniState->noiseImmunityLevel + 1)) {
243 return;
244 }
245 }
246
247 if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
248 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
249 aniState->spurImmunityLevel + 1)) {
250 return;
251 }
252 }
253
Sujith2660b812009-02-09 13:27:26 +0530254 if (ah->opmode == NL80211_IFTYPE_AP) {
Sujithf1dc5602008-10-29 10:16:30 +0530255 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
256 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
257 aniState->firstepLevel + 1);
258 }
259 return;
260 }
Sujithcbe61d82009-02-09 13:27:12 +0530261 rssi = BEACON_RSSI(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530262 if (rssi > aniState->rssiThrHigh) {
263 if (!aniState->ofdmWeakSigDetectOff) {
264 if (ath9k_hw_ani_control(ah,
265 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
266 false)) {
267 ath9k_hw_ani_control(ah,
268 ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
269 return;
270 }
271 }
272 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
273 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
274 aniState->firstepLevel + 1);
275 return;
276 }
277 } else if (rssi > aniState->rssiThrLow) {
278 if (aniState->ofdmWeakSigDetectOff)
279 ath9k_hw_ani_control(ah,
280 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
281 true);
282 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
283 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
284 aniState->firstepLevel + 1);
285 return;
286 } else {
Sujithd37b7da2009-09-11 08:30:03 +0530287 if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
288 !conf_is_ht(conf)) {
Sujithf1dc5602008-10-29 10:16:30 +0530289 if (!aniState->ofdmWeakSigDetectOff)
290 ath9k_hw_ani_control(ah,
291 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
292 false);
293 if (aniState->firstepLevel > 0)
294 ath9k_hw_ani_control(ah,
295 ATH9K_ANI_FIRSTEP_LEVEL, 0);
296 return;
297 }
298 }
299}
300
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400301static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530302{
Luis R. Rodriguezb002a4a2009-09-13 00:03:27 -0700303 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
Sujithf1dc5602008-10-29 10:16:30 +0530304 struct ar5416AniState *aniState;
Sujithf1dc5602008-10-29 10:16:30 +0530305 int32_t rssi;
306
307 if (!DO_ANI(ah))
308 return;
309
Sujith2660b812009-02-09 13:27:26 +0530310 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530311 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
312 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
313 aniState->noiseImmunityLevel + 1)) {
314 return;
315 }
316 }
Sujith2660b812009-02-09 13:27:26 +0530317 if (ah->opmode == NL80211_IFTYPE_AP) {
Sujithf1dc5602008-10-29 10:16:30 +0530318 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
319 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
320 aniState->firstepLevel + 1);
321 }
322 return;
323 }
Sujithcbe61d82009-02-09 13:27:12 +0530324 rssi = BEACON_RSSI(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530325 if (rssi > aniState->rssiThrLow) {
326 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
327 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
328 aniState->firstepLevel + 1);
329 } else {
Sujithd37b7da2009-09-11 08:30:03 +0530330 if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
331 !conf_is_ht(conf)) {
Sujithf1dc5602008-10-29 10:16:30 +0530332 if (aniState->firstepLevel > 0)
333 ath9k_hw_ani_control(ah,
334 ATH9K_ANI_FIRSTEP_LEVEL, 0);
335 }
336 }
337}
338
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400339/* Adjust the OFDM Noise Immunity Level */
340static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
341{
342 struct ar5416AniState *aniState = ah->curani;
343 struct ath_common *common = ath9k_hw_common(ah);
344 const struct ani_ofdm_level_entry *entry_ofdm;
345 const struct ani_cck_level_entry *entry_cck;
346
347 aniState->noiseFloor = BEACON_RSSI(ah);
348
349 ath_print(common, ATH_DBG_ANI,
350 "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
351 aniState->ofdmNoiseImmunityLevel,
352 immunityLevel, aniState->noiseFloor,
353 aniState->rssiThrLow, aniState->rssiThrHigh);
354
355 aniState->ofdmNoiseImmunityLevel = immunityLevel;
356
357 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
358 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
359
360 if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
361 ath9k_hw_ani_control(ah,
362 ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
363 entry_ofdm->spur_immunity_level);
364
365 if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
366 entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
367 ath9k_hw_ani_control(ah,
368 ATH9K_ANI_FIRSTEP_LEVEL,
369 entry_ofdm->fir_step_level);
370
371 if ((ah->opmode != NL80211_IFTYPE_STATION &&
372 ah->opmode != NL80211_IFTYPE_ADHOC) ||
373 aniState->noiseFloor <= aniState->rssiThrHigh) {
374 if (aniState->ofdmWeakSigDetectOff)
375 /* force on ofdm weak sig detect */
376 ath9k_hw_ani_control(ah,
377 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
378 true);
379 else if (aniState->ofdmWeakSigDetectOff ==
380 entry_ofdm->ofdm_weak_signal_on)
381 ath9k_hw_ani_control(ah,
382 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
383 entry_ofdm->ofdm_weak_signal_on);
384 }
385}
386
387static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
388{
389 struct ar5416AniState *aniState;
390
391 if (!DO_ANI(ah))
392 return;
393
394 aniState = ah->curani;
395
396 if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
397 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
398}
399
400/*
401 * Set the ANI settings to match an CCK level.
402 */
403static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
404{
405 struct ar5416AniState *aniState = ah->curani;
406 struct ath_common *common = ath9k_hw_common(ah);
407 const struct ani_ofdm_level_entry *entry_ofdm;
408 const struct ani_cck_level_entry *entry_cck;
409
410 aniState->noiseFloor = BEACON_RSSI(ah);
411 ath_print(common, ATH_DBG_ANI,
412 "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
413 aniState->cckNoiseImmunityLevel, immunityLevel,
414 aniState->noiseFloor, aniState->rssiThrLow,
415 aniState->rssiThrHigh);
416
417 if ((ah->opmode == NL80211_IFTYPE_STATION ||
418 ah->opmode == NL80211_IFTYPE_ADHOC) &&
419 aniState->noiseFloor <= aniState->rssiThrLow &&
420 immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
421 immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
422
423 aniState->cckNoiseImmunityLevel = immunityLevel;
424
425 entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
426 entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
427
428 if (aniState->firstepLevel != entry_cck->fir_step_level &&
429 entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
430 ath9k_hw_ani_control(ah,
431 ATH9K_ANI_FIRSTEP_LEVEL,
432 entry_cck->fir_step_level);
433
434 /* Skip MRC CCK for pre AR9003 families */
435 if (!AR_SREV_9300_20_OR_LATER(ah))
436 return;
437
438 if (aniState->mrcCCKOff == entry_cck->mrc_cck_on)
439 ath9k_hw_ani_control(ah,
440 ATH9K_ANI_MRC_CCK,
441 entry_cck->mrc_cck_on);
442}
443
444static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
445{
446 struct ar5416AniState *aniState;
447
448 if (!DO_ANI(ah))
449 return;
450
451 aniState = ah->curani;
452
453 if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
454 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
455}
456
Luis R. Rodriguezac0bb762010-06-12 00:33:42 -0400457static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530458{
Sujithf1dc5602008-10-29 10:16:30 +0530459 struct ar5416AniState *aniState;
460 int32_t rssi;
461
Sujith2660b812009-02-09 13:27:26 +0530462 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530463
Sujith2660b812009-02-09 13:27:26 +0530464 if (ah->opmode == NL80211_IFTYPE_AP) {
Sujithf1dc5602008-10-29 10:16:30 +0530465 if (aniState->firstepLevel > 0) {
466 if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
467 aniState->firstepLevel - 1))
468 return;
469 }
470 } else {
Sujithcbe61d82009-02-09 13:27:12 +0530471 rssi = BEACON_RSSI(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530472 if (rssi > aniState->rssiThrHigh) {
473 /* XXX: Handle me */
474 } else if (rssi > aniState->rssiThrLow) {
475 if (aniState->ofdmWeakSigDetectOff) {
476 if (ath9k_hw_ani_control(ah,
477 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
478 true) == true)
479 return;
480 }
481 if (aniState->firstepLevel > 0) {
482 if (ath9k_hw_ani_control(ah,
483 ATH9K_ANI_FIRSTEP_LEVEL,
484 aniState->firstepLevel - 1) == true)
485 return;
486 }
487 } else {
488 if (aniState->firstepLevel > 0) {
489 if (ath9k_hw_ani_control(ah,
490 ATH9K_ANI_FIRSTEP_LEVEL,
491 aniState->firstepLevel - 1) == true)
492 return;
493 }
494 }
495 }
496
497 if (aniState->spurImmunityLevel > 0) {
498 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
499 aniState->spurImmunityLevel - 1))
500 return;
501 }
502
503 if (aniState->noiseImmunityLevel > 0) {
504 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
505 aniState->noiseImmunityLevel - 1);
506 return;
507 }
508}
509
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400510/*
511 * only lower either OFDM or CCK errors per turn
512 * we lower the other one next time
513 */
514static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
515{
516 struct ar5416AniState *aniState;
517
518 aniState = ah->curani;
519
520 /* lower OFDM noise immunity */
521 if (aniState->ofdmNoiseImmunityLevel > 0 &&
522 (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
523 ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1);
524 return;
525 }
526
527 /* lower CCK noise immunity */
528 if (aniState->cckNoiseImmunityLevel > 0)
529 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
530}
531
Luis R. Rodriguez37e5bf62010-06-12 00:33:40 -0400532static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
533{
534 struct ath9k_channel *chan = ah->curchan;
535 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
536 u8 clockrate; /* in MHz */
537
538 if (!ah->curchan) /* should really check for CCK instead */
539 clockrate = ATH9K_CLOCK_RATE_CCK;
540 else if (conf->channel->band == IEEE80211_BAND_2GHZ)
541 clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
542 else if (IS_CHAN_A_FAST_CLOCK(ah, chan))
543 clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
544 else
545 clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
546
547 if (conf_is_ht40(conf))
548 return clockrate * 2;
549
Felix Fietkau918df622010-10-03 19:07:19 +0200550 return clockrate;
Luis R. Rodriguez37e5bf62010-06-12 00:33:40 -0400551}
552
Sujithcbe61d82009-02-09 13:27:12 +0530553static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530554{
Felix Fietkau9dbebc72010-10-03 19:07:17 +0200555 int32_t listen_time;
556 int32_t clock_rate;
Sujithf1dc5602008-10-29 10:16:30 +0530557
Felix Fietkau9dbebc72010-10-03 19:07:17 +0200558 ath9k_hw_update_cycle_counters(ah);
559 clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;
560 listen_time = ah->listen_time / clock_rate;
561 ah->listen_time = 0;
Sujithf1dc5602008-10-29 10:16:30 +0530562
Felix Fietkau9dbebc72010-10-03 19:07:17 +0200563 return listen_time;
Sujithf1dc5602008-10-29 10:16:30 +0530564}
565
Luis R. Rodriguez40346b62010-06-12 00:33:44 -0400566static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
Sujithf1dc5602008-10-29 10:16:30 +0530567{
Sujithf1dc5602008-10-29 10:16:30 +0530568 struct ar5416AniState *aniState;
Sujith2660b812009-02-09 13:27:26 +0530569 struct ath9k_channel *chan = ah->curchan;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700570 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530571 int index;
572
573 if (!DO_ANI(ah))
574 return;
575
576 index = ath9k_hw_get_ani_channel_idx(ah, chan);
Sujith2660b812009-02-09 13:27:26 +0530577 aniState = &ah->ani[index];
578 ah->curani = aniState;
Sujithf1dc5602008-10-29 10:16:30 +0530579
Sujith2660b812009-02-09 13:27:26 +0530580 if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
581 && ah->opmode != NL80211_IFTYPE_ADHOC) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700582 ath_print(common, ATH_DBG_ANI,
583 "Reset ANI state opmode %u\n", ah->opmode);
Sujith2660b812009-02-09 13:27:26 +0530584 ah->stats.ast_ani_reset++;
Sujithf1dc5602008-10-29 10:16:30 +0530585
Luis R. Rodriguezc66284f2009-07-16 10:17:35 -0700586 if (ah->opmode == NL80211_IFTYPE_AP) {
587 /*
588 * ath9k_hw_ani_control() will only process items set on
589 * ah->ani_function
590 */
591 if (IS_CHAN_2GHZ(chan))
592 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
593 ATH9K_ANI_FIRSTEP_LEVEL);
594 else
595 ah->ani_function = 0;
596 }
597
Sujithf1dc5602008-10-29 10:16:30 +0530598 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
599 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
600 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
601 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
602 !ATH9K_ANI_USE_OFDM_WEAK_SIG);
603 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
604 ATH9K_ANI_CCK_WEAK_SIG_THR);
605
606 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
607 ATH9K_RX_FILTER_PHYERR);
608
Sujith2660b812009-02-09 13:27:26 +0530609 if (ah->opmode == NL80211_IFTYPE_AP) {
610 ah->curani->ofdmTrigHigh =
611 ah->config.ofdm_trig_high;
612 ah->curani->ofdmTrigLow =
613 ah->config.ofdm_trig_low;
614 ah->curani->cckTrigHigh =
615 ah->config.cck_trig_high;
616 ah->curani->cckTrigLow =
617 ah->config.cck_trig_low;
Sujithf1dc5602008-10-29 10:16:30 +0530618 }
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400619 ath9k_ani_restart_old(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530620 return;
621 }
622
623 if (aniState->noiseImmunityLevel != 0)
624 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
625 aniState->noiseImmunityLevel);
626 if (aniState->spurImmunityLevel != 0)
627 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
628 aniState->spurImmunityLevel);
629 if (aniState->ofdmWeakSigDetectOff)
630 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
631 !aniState->ofdmWeakSigDetectOff);
632 if (aniState->cckWeakSigThreshold)
633 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
634 aniState->cckWeakSigThreshold);
635 if (aniState->firstepLevel != 0)
636 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
637 aniState->firstepLevel);
Sujithf1dc5602008-10-29 10:16:30 +0530638
Sujith1aa8e842009-08-13 09:34:25 +0530639 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
640 ~ATH9K_RX_FILTER_PHYERR);
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400641 ath9k_ani_restart_old(ah);
642
643 ENABLE_REGWRITE_BUFFER(ah);
644
645 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
646 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
647
648 REGWRITE_BUFFER_FLUSH(ah);
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400649}
650
651/*
652 * Restore the ANI parameters in the HAL and reset the statistics.
653 * This routine should be called for every hardware reset and for
654 * every channel change.
655 */
656static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
657{
658 struct ar5416AniState *aniState = ah->curani;
659 struct ath9k_channel *chan = ah->curchan;
660 struct ath_common *common = ath9k_hw_common(ah);
661
662 if (!DO_ANI(ah))
663 return;
664
665 BUG_ON(aniState == NULL);
666 ah->stats.ast_ani_reset++;
667
668 /* only allow a subset of functions in AP mode */
669 if (ah->opmode == NL80211_IFTYPE_AP) {
670 if (IS_CHAN_2GHZ(chan)) {
671 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
672 ATH9K_ANI_FIRSTEP_LEVEL);
673 if (AR_SREV_9300_20_OR_LATER(ah))
674 ah->ani_function |= ATH9K_ANI_MRC_CCK;
675 } else
676 ah->ani_function = 0;
677 }
678
679 /* always allow mode (on/off) to be controlled */
680 ah->ani_function |= ATH9K_ANI_MODE;
681
682 if (is_scanning ||
683 (ah->opmode != NL80211_IFTYPE_STATION &&
684 ah->opmode != NL80211_IFTYPE_ADHOC)) {
685 /*
686 * If we're scanning or in AP mode, the defaults (ini)
687 * should be in place. For an AP we assume the historical
688 * levels for this channel are probably outdated so start
689 * from defaults instead.
690 */
691 if (aniState->ofdmNoiseImmunityLevel !=
692 ATH9K_ANI_OFDM_DEF_LEVEL ||
693 aniState->cckNoiseImmunityLevel !=
694 ATH9K_ANI_CCK_DEF_LEVEL) {
695 ath_print(common, ATH_DBG_ANI,
696 "Restore defaults: opmode %u "
697 "chan %d Mhz/0x%x is_scanning=%d "
698 "ofdm:%d cck:%d\n",
699 ah->opmode,
700 chan->channel,
701 chan->channelFlags,
702 is_scanning,
703 aniState->ofdmNoiseImmunityLevel,
704 aniState->cckNoiseImmunityLevel);
705
706 ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
707 ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
708 }
709 } else {
710 /*
711 * restore historical levels for this channel
712 */
713 ath_print(common, ATH_DBG_ANI,
714 "Restore history: opmode %u "
715 "chan %d Mhz/0x%x is_scanning=%d "
716 "ofdm:%d cck:%d\n",
717 ah->opmode,
718 chan->channel,
719 chan->channelFlags,
720 is_scanning,
721 aniState->ofdmNoiseImmunityLevel,
722 aniState->cckNoiseImmunityLevel);
723
724 ath9k_hw_set_ofdm_nil(ah,
725 aniState->ofdmNoiseImmunityLevel);
726 ath9k_hw_set_cck_nil(ah,
727 aniState->cckNoiseImmunityLevel);
728 }
729
730 /*
731 * enable phy counters if hw supports or if not, enable phy
732 * interrupts (so we can count each one)
733 */
734 ath9k_ani_restart_new(ah);
Sujith7d0d0df2010-04-16 11:53:57 +0530735
736 ENABLE_REGWRITE_BUFFER(ah);
737
Sujith1aa8e842009-08-13 09:34:25 +0530738 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
739 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
Sujith7d0d0df2010-04-16 11:53:57 +0530740
741 REGWRITE_BUFFER_FLUSH(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530742}
743
Luis R. Rodriguezac0bb762010-06-12 00:33:42 -0400744static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
745 struct ath9k_channel *chan)
Sujithf1dc5602008-10-29 10:16:30 +0530746{
Sujithf1dc5602008-10-29 10:16:30 +0530747 struct ar5416AniState *aniState;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700748 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530749 int32_t listenTime;
Sujith1aa8e842009-08-13 09:34:25 +0530750 u32 phyCnt1, phyCnt2;
751 u32 ofdmPhyErrCnt, cckPhyErrCnt;
Sujithf1dc5602008-10-29 10:16:30 +0530752
Gabor Juhos99506882009-01-14 20:17:11 +0100753 if (!DO_ANI(ah))
754 return;
755
Sujith2660b812009-02-09 13:27:26 +0530756 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530757
758 listenTime = ath9k_hw_ani_get_listen_time(ah);
759 if (listenTime < 0) {
Sujith2660b812009-02-09 13:27:26 +0530760 ah->stats.ast_ani_lneg++;
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400761 ath9k_ani_restart_old(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530762 return;
763 }
764
765 aniState->listenTime += listenTime;
766
Sujith1aa8e842009-08-13 09:34:25 +0530767 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
Sujithf1dc5602008-10-29 10:16:30 +0530768
Sujith1aa8e842009-08-13 09:34:25 +0530769 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
770 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
Sujithf1dc5602008-10-29 10:16:30 +0530771
Sujith1aa8e842009-08-13 09:34:25 +0530772 if (phyCnt1 < aniState->ofdmPhyErrBase ||
773 phyCnt2 < aniState->cckPhyErrBase) {
774 if (phyCnt1 < aniState->ofdmPhyErrBase) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700775 ath_print(common, ATH_DBG_ANI,
776 "phyCnt1 0x%x, resetting "
777 "counter value to 0x%x\n",
778 phyCnt1,
779 aniState->ofdmPhyErrBase);
Sujith1aa8e842009-08-13 09:34:25 +0530780 REG_WRITE(ah, AR_PHY_ERR_1,
781 aniState->ofdmPhyErrBase);
782 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
783 AR_PHY_ERR_OFDM_TIMING);
Sujithf1dc5602008-10-29 10:16:30 +0530784 }
Sujith1aa8e842009-08-13 09:34:25 +0530785 if (phyCnt2 < aniState->cckPhyErrBase) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700786 ath_print(common, ATH_DBG_ANI,
787 "phyCnt2 0x%x, resetting "
788 "counter value to 0x%x\n",
789 phyCnt2,
790 aniState->cckPhyErrBase);
Sujith1aa8e842009-08-13 09:34:25 +0530791 REG_WRITE(ah, AR_PHY_ERR_2,
792 aniState->cckPhyErrBase);
793 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
794 AR_PHY_ERR_CCK_TIMING);
795 }
796 return;
Sujithf1dc5602008-10-29 10:16:30 +0530797 }
798
Sujith1aa8e842009-08-13 09:34:25 +0530799 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
800 ah->stats.ast_ani_ofdmerrs +=
801 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
802 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
803
804 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
805 ah->stats.ast_ani_cckerrs +=
806 cckPhyErrCnt - aniState->cckPhyErrCount;
807 aniState->cckPhyErrCount = cckPhyErrCnt;
808
Sujith2660b812009-02-09 13:27:26 +0530809 if (aniState->listenTime > 5 * ah->aniperiod) {
Sujithf1dc5602008-10-29 10:16:30 +0530810 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
811 aniState->ofdmTrigLow / 1000 &&
812 aniState->cckPhyErrCount <= aniState->listenTime *
813 aniState->cckTrigLow / 1000)
814 ath9k_hw_ani_lower_immunity(ah);
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400815 ath9k_ani_restart_old(ah);
Sujith2660b812009-02-09 13:27:26 +0530816 } else if (aniState->listenTime > ah->aniperiod) {
Sujithf1dc5602008-10-29 10:16:30 +0530817 if (aniState->ofdmPhyErrCount > aniState->listenTime *
818 aniState->ofdmTrigHigh / 1000) {
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400819 ath9k_hw_ani_ofdm_err_trigger_old(ah);
820 ath9k_ani_restart_old(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530821 } else if (aniState->cckPhyErrCount >
822 aniState->listenTime * aniState->cckTrigHigh /
823 1000) {
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -0400824 ath9k_hw_ani_cck_err_trigger_old(ah);
825 ath9k_ani_restart_old(ah);
826 }
827 }
828}
829
830static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
831 struct ath9k_channel *chan)
832{
833 struct ar5416AniState *aniState;
834 struct ath_common *common = ath9k_hw_common(ah);
835 int32_t listenTime;
836 u32 phyCnt1, phyCnt2;
837 u32 ofdmPhyErrCnt, cckPhyErrCnt;
838 u32 ofdmPhyErrRate, cckPhyErrRate;
839
840 if (!DO_ANI(ah))
841 return;
842
843 aniState = ah->curani;
844 if (WARN_ON(!aniState))
845 return;
846
847 listenTime = ath9k_hw_ani_get_listen_time(ah);
848 if (listenTime <= 0) {
849 ah->stats.ast_ani_lneg++;
850 /* restart ANI period if listenTime is invalid */
851 ath_print(common, ATH_DBG_ANI,
852 "listenTime=%d - on new ani monitor\n",
853 listenTime);
854 ath9k_ani_restart_new(ah);
855 return;
856 }
857
858 aniState->listenTime += listenTime;
859
860 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
861
862 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
863 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
864
865 if (phyCnt1 < aniState->ofdmPhyErrBase ||
866 phyCnt2 < aniState->cckPhyErrBase) {
867 if (phyCnt1 < aniState->ofdmPhyErrBase) {
868 ath_print(common, ATH_DBG_ANI,
869 "phyCnt1 0x%x, resetting "
870 "counter value to 0x%x\n",
871 phyCnt1,
872 aniState->ofdmPhyErrBase);
873 REG_WRITE(ah, AR_PHY_ERR_1,
874 aniState->ofdmPhyErrBase);
875 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
876 AR_PHY_ERR_OFDM_TIMING);
877 }
878 if (phyCnt2 < aniState->cckPhyErrBase) {
879 ath_print(common, ATH_DBG_ANI,
880 "phyCnt2 0x%x, resetting "
881 "counter value to 0x%x\n",
882 phyCnt2,
883 aniState->cckPhyErrBase);
884 REG_WRITE(ah, AR_PHY_ERR_2,
885 aniState->cckPhyErrBase);
886 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
887 AR_PHY_ERR_CCK_TIMING);
888 }
889 return;
890 }
891
892 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
893 ah->stats.ast_ani_ofdmerrs +=
894 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
895 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
896
897 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
898 ah->stats.ast_ani_cckerrs +=
899 cckPhyErrCnt - aniState->cckPhyErrCount;
900 aniState->cckPhyErrCount = cckPhyErrCnt;
901
902 ath_print(common, ATH_DBG_ANI,
903 "Errors: OFDM=0x%08x-0x%08x=%d "
904 "CCK=0x%08x-0x%08x=%d\n",
905 phyCnt1,
906 aniState->ofdmPhyErrBase,
907 ofdmPhyErrCnt,
908 phyCnt2,
909 aniState->cckPhyErrBase,
910 cckPhyErrCnt);
911
912 ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
913 aniState->listenTime;
914 cckPhyErrRate = aniState->cckPhyErrCount * 1000 /
915 aniState->listenTime;
916
917 ath_print(common, ATH_DBG_ANI,
918 "listenTime=%d OFDM:%d errs=%d/s CCK:%d "
919 "errs=%d/s ofdm_turn=%d\n",
920 listenTime, aniState->ofdmNoiseImmunityLevel,
921 ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
922 cckPhyErrRate, aniState->ofdmsTurn);
923
924 if (aniState->listenTime > 5 * ah->aniperiod) {
925 if (ofdmPhyErrRate <= aniState->ofdmTrigLow &&
926 cckPhyErrRate <= aniState->cckTrigLow) {
927 ath_print(common, ATH_DBG_ANI,
928 "1. listenTime=%d OFDM:%d errs=%d/s(<%d) "
929 "CCK:%d errs=%d/s(<%d) -> "
930 "ath9k_hw_ani_lower_immunity()\n",
931 aniState->listenTime,
932 aniState->ofdmNoiseImmunityLevel,
933 ofdmPhyErrRate,
934 aniState->ofdmTrigLow,
935 aniState->cckNoiseImmunityLevel,
936 cckPhyErrRate,
937 aniState->cckTrigLow);
938 ath9k_hw_ani_lower_immunity(ah);
939 aniState->ofdmsTurn = !aniState->ofdmsTurn;
940 }
941 ath_print(common, ATH_DBG_ANI,
942 "1 listenTime=%d ofdm=%d/s cck=%d/s - "
943 "calling ath9k_ani_restart_new()\n",
944 aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate);
945 ath9k_ani_restart_new(ah);
946 } else if (aniState->listenTime > ah->aniperiod) {
947 /* check to see if need to raise immunity */
948 if (ofdmPhyErrRate > aniState->ofdmTrigHigh &&
949 (cckPhyErrRate <= aniState->cckTrigHigh ||
950 aniState->ofdmsTurn)) {
951 ath_print(common, ATH_DBG_ANI,
952 "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> "
953 "ath9k_hw_ani_ofdm_err_trigger_new()\n",
954 aniState->listenTime,
955 aniState->ofdmNoiseImmunityLevel,
956 ofdmPhyErrRate,
957 aniState->ofdmTrigHigh);
958 ath9k_hw_ani_ofdm_err_trigger_new(ah);
959 ath9k_ani_restart_new(ah);
960 aniState->ofdmsTurn = false;
961 } else if (cckPhyErrRate > aniState->cckTrigHigh) {
962 ath_print(common, ATH_DBG_ANI,
963 "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> "
964 "ath9k_hw_ani_cck_err_trigger_new()\n",
965 aniState->listenTime,
966 aniState->cckNoiseImmunityLevel,
967 cckPhyErrRate,
968 aniState->cckTrigHigh);
969 ath9k_hw_ani_cck_err_trigger_new(ah);
970 ath9k_ani_restart_new(ah);
971 aniState->ofdmsTurn = true;
Sujithf1dc5602008-10-29 10:16:30 +0530972 }
973 }
974}
975
Sujithcbe61d82009-02-09 13:27:12 +0530976void ath9k_enable_mib_counters(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530977{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700978 struct ath_common *common = ath9k_hw_common(ah);
979
980 ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
Sujithf1dc5602008-10-29 10:16:30 +0530981
Sujithcbe61d82009-02-09 13:27:12 +0530982 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
Sujithf1dc5602008-10-29 10:16:30 +0530983
Sujith7d0d0df2010-04-16 11:53:57 +0530984 ENABLE_REGWRITE_BUFFER(ah);
985
Sujithf1dc5602008-10-29 10:16:30 +0530986 REG_WRITE(ah, AR_FILT_OFDM, 0);
987 REG_WRITE(ah, AR_FILT_CCK, 0);
988 REG_WRITE(ah, AR_MIBC,
989 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
990 & 0x0f);
991 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
992 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
Sujith7d0d0df2010-04-16 11:53:57 +0530993
994 REGWRITE_BUFFER_FLUSH(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530995}
996
Sujith0fd06c92009-02-12 10:06:51 +0530997/* Freeze the MIB counters, get the stats and then clear them */
Sujithcbe61d82009-02-09 13:27:12 +0530998void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530999{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001000 struct ath_common *common = ath9k_hw_common(ah);
1001
1002 ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
1003
Sujith0fd06c92009-02-12 10:06:51 +05301004 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
Sujithcbe61d82009-02-09 13:27:12 +05301005 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
Sujith0fd06c92009-02-12 10:06:51 +05301006 REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
Sujithf1dc5602008-10-29 10:16:30 +05301007 REG_WRITE(ah, AR_FILT_OFDM, 0);
1008 REG_WRITE(ah, AR_FILT_CCK, 0);
1009}
Sujith21d51302010-06-01 15:14:18 +05301010EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
Sujithf1dc5602008-10-29 10:16:30 +05301011
Felix Fietkau9dbebc72010-10-03 19:07:17 +02001012void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +05301013{
Felix Fietkau9dbebc72010-10-03 19:07:17 +02001014 struct ath_cycle_counters cc;
1015 bool clear;
Sujithf1dc5602008-10-29 10:16:30 +05301016
Felix Fietkau9dbebc72010-10-03 19:07:17 +02001017 memcpy(&cc, &ah->cc, sizeof(cc));
Sujithf1dc5602008-10-29 10:16:30 +05301018
Felix Fietkau9dbebc72010-10-03 19:07:17 +02001019 /* freeze counters */
1020 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
Sujithf1dc5602008-10-29 10:16:30 +05301021
Felix Fietkau9dbebc72010-10-03 19:07:17 +02001022 ah->cc.cycles = REG_READ(ah, AR_CCCNT);
1023 if (ah->cc.cycles < cc.cycles) {
1024 clear = true;
1025 goto skip;
Sujithf1dc5602008-10-29 10:16:30 +05301026 }
1027
Felix Fietkau9dbebc72010-10-03 19:07:17 +02001028 ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
1029 ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
1030 ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
Sujithf1dc5602008-10-29 10:16:30 +05301031
Felix Fietkau9dbebc72010-10-03 19:07:17 +02001032 /* prevent wraparound */
1033 if (ah->cc.cycles & BIT(31))
1034 clear = true;
1035
1036#define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
1037 CC_DELTA(cycles, AR_CCCNT);
1038 CC_DELTA(rx_frame, AR_RFCNT);
1039 CC_DELTA(rx_clear, AR_RCCNT);
1040 CC_DELTA(tx_frame, AR_TFCNT);
1041#undef CC_DELTA
1042
1043 ah->listen_time += (ah->cc.cycles - cc.cycles) -
1044 ((ah->cc.rx_frame - cc.rx_frame) +
1045 (ah->cc.tx_frame - cc.tx_frame));
1046
1047skip:
1048 if (clear) {
1049 REG_WRITE(ah, AR_CCCNT, 0);
1050 REG_WRITE(ah, AR_RFCNT, 0);
1051 REG_WRITE(ah, AR_RCCNT, 0);
1052 REG_WRITE(ah, AR_TFCNT, 0);
1053 memset(&ah->cc, 0, sizeof(ah->cc));
1054 }
1055
1056 /* unfreeze counters */
1057 REG_WRITE(ah, AR_MIBC, 0);
Sujithf1dc5602008-10-29 10:16:30 +05301058}
1059
1060/*
1061 * Process a MIB interrupt. We may potentially be invoked because
1062 * any of the MIB counters overflow/trigger so don't assume we're
1063 * here because a PHY error counter triggered.
1064 */
Luis R. Rodriguezac0bb762010-06-12 00:33:42 -04001065static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +05301066{
Sujithf1dc5602008-10-29 10:16:30 +05301067 u32 phyCnt1, phyCnt2;
1068
1069 /* Reset these counters regardless */
1070 REG_WRITE(ah, AR_FILT_OFDM, 0);
1071 REG_WRITE(ah, AR_FILT_CCK, 0);
1072 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
1073 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
1074
1075 /* Clear the mib counters and save them in the stats */
Sujithcbe61d82009-02-09 13:27:12 +05301076 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
Sujithf1dc5602008-10-29 10:16:30 +05301077
Luis R. Rodriguez6e97f0f2010-06-12 00:33:41 -04001078 if (!DO_ANI(ah)) {
1079 /*
1080 * We must always clear the interrupt cause by
1081 * resetting the phy error regs.
1082 */
1083 REG_WRITE(ah, AR_PHY_ERR_1, 0);
1084 REG_WRITE(ah, AR_PHY_ERR_2, 0);
Sujithf1dc5602008-10-29 10:16:30 +05301085 return;
Luis R. Rodriguez6e97f0f2010-06-12 00:33:41 -04001086 }
Sujithf1dc5602008-10-29 10:16:30 +05301087
1088 /* NB: these are not reset-on-read */
1089 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
1090 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
1091 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
1092 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
Sujith2660b812009-02-09 13:27:26 +05301093 struct ar5416AniState *aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +05301094 u32 ofdmPhyErrCnt, cckPhyErrCnt;
1095
1096 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
1097 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
Sujith2660b812009-02-09 13:27:26 +05301098 ah->stats.ast_ani_ofdmerrs +=
Sujithf1dc5602008-10-29 10:16:30 +05301099 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
1100 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
1101
1102 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
Sujith2660b812009-02-09 13:27:26 +05301103 ah->stats.ast_ani_cckerrs +=
Sujithf1dc5602008-10-29 10:16:30 +05301104 cckPhyErrCnt - aniState->cckPhyErrCount;
1105 aniState->cckPhyErrCount = cckPhyErrCnt;
1106
1107 /*
1108 * NB: figure out which counter triggered. If both
1109 * trigger we'll only deal with one as the processing
1110 * clobbers the error counter so the trigger threshold
1111 * check will never be true.
1112 */
1113 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04001114 ath9k_hw_ani_ofdm_err_trigger_new(ah);
Sujithf1dc5602008-10-29 10:16:30 +05301115 if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04001116 ath9k_hw_ani_cck_err_trigger_old(ah);
Sujithf1dc5602008-10-29 10:16:30 +05301117 /* NB: always restart to insure the h/w counters are reset */
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04001118 ath9k_ani_restart_old(ah);
Sujithf1dc5602008-10-29 10:16:30 +05301119 }
1120}
1121
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04001122/*
1123 * Process a MIB interrupt. We may potentially be invoked because
1124 * any of the MIB counters overflow/trigger so don't assume we're
1125 * here because a PHY error counter triggered.
1126 */
1127static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
1128{
1129 u32 phyCnt1, phyCnt2;
1130
1131 /* Reset these counters regardless */
1132 REG_WRITE(ah, AR_FILT_OFDM, 0);
1133 REG_WRITE(ah, AR_FILT_CCK, 0);
1134 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
1135 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
1136
1137 /* Clear the mib counters and save them in the stats */
1138 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
1139
1140 if (!DO_ANI(ah)) {
1141 /*
1142 * We must always clear the interrupt cause by
1143 * resetting the phy error regs.
1144 */
1145 REG_WRITE(ah, AR_PHY_ERR_1, 0);
1146 REG_WRITE(ah, AR_PHY_ERR_2, 0);
1147 return;
1148 }
1149
1150 /* NB: these are not reset-on-read */
1151 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
1152 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
1153
1154 /* NB: always restart to insure the h/w counters are reset */
1155 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
1156 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK))
1157 ath9k_ani_restart_new(ah);
1158}
1159
Sujithcbe61d82009-02-09 13:27:12 +05301160void ath9k_hw_ani_setup(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +05301161{
Sujithf1dc5602008-10-29 10:16:30 +05301162 int i;
1163
1164 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
1165 const int coarseHigh[] = { -14, -14, -14, -14, -12 };
1166 const int coarseLow[] = { -64, -64, -64, -64, -70 };
1167 const int firpwr[] = { -78, -78, -78, -78, -80 };
1168
1169 for (i = 0; i < 5; i++) {
Sujith2660b812009-02-09 13:27:26 +05301170 ah->totalSizeDesired[i] = totalSizeDesired[i];
1171 ah->coarse_high[i] = coarseHigh[i];
1172 ah->coarse_low[i] = coarseLow[i];
1173 ah->firpwr[i] = firpwr[i];
Sujithf1dc5602008-10-29 10:16:30 +05301174 }
1175}
1176
Luis R. Rodriguezf637cfd2009-08-03 12:24:46 -07001177void ath9k_hw_ani_init(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +05301178{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001179 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +05301180 int i;
1181
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001182 ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
Sujithf1dc5602008-10-29 10:16:30 +05301183
Sujith2660b812009-02-09 13:27:26 +05301184 memset(ah->ani, 0, sizeof(ah->ani));
1185 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
Felix Fietkau71ea4202010-10-04 20:09:46 +02001186 if (use_new_ani(ah)) {
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04001187 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
1188 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
1189
1190 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
1191 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW;
1192
1193 ah->ani[i].spurImmunityLevel =
1194 ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
1195
1196 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
1197
1198 ah->ani[i].ofdmPhyErrBase = 0;
1199 ah->ani[i].cckPhyErrBase = 0;
1200
1201 if (AR_SREV_9300_20_OR_LATER(ah))
1202 ah->ani[i].mrcCCKOff =
1203 !ATH9K_ANI_ENABLE_MRC_CCK;
1204 else
1205 ah->ani[i].mrcCCKOff = true;
1206
1207 ah->ani[i].ofdmsTurn = true;
1208 } else {
1209 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1210 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
1211
1212 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1213 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD;
1214
1215 ah->ani[i].spurImmunityLevel =
1216 ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
1217 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
1218
1219 ah->ani[i].ofdmPhyErrBase =
1220 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
1221 ah->ani[i].cckPhyErrBase =
1222 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD;
1223 ah->ani[i].cckWeakSigThreshold =
1224 ATH9K_ANI_CCK_WEAK_SIG_THR;
1225 }
1226
Sujith2660b812009-02-09 13:27:26 +05301227 ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
1228 ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
1229 ah->ani[i].ofdmWeakSigDetectOff =
Sujithf1dc5602008-10-29 10:16:30 +05301230 !ATH9K_ANI_USE_OFDM_WEAK_SIG;
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04001231 ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
1232 }
1233
1234 /*
1235 * since we expect some ongoing maintenance on the tables, let's sanity
1236 * check here default level should not modify INI setting.
1237 */
Felix Fietkau71ea4202010-10-04 20:09:46 +02001238 if (use_new_ani(ah)) {
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04001239 const struct ani_ofdm_level_entry *entry_ofdm;
1240 const struct ani_cck_level_entry *entry_cck;
1241
1242 entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL];
1243 entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL];
1244
1245 ah->aniperiod = ATH9K_ANI_PERIOD_NEW;
1246 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW;
1247 } else {
1248 ah->aniperiod = ATH9K_ANI_PERIOD_OLD;
1249 ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
Sujithf1dc5602008-10-29 10:16:30 +05301250 }
Sujithf1dc5602008-10-29 10:16:30 +05301251
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -07001252 ath_print(common, ATH_DBG_ANI,
1253 "Setting OfdmErrBase = 0x%08x\n",
1254 ah->ani[0].ofdmPhyErrBase);
1255 ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
1256 ah->ani[0].cckPhyErrBase);
Sujith1aa8e842009-08-13 09:34:25 +05301257
Sujith7d0d0df2010-04-16 11:53:57 +05301258 ENABLE_REGWRITE_BUFFER(ah);
1259
Sujith1aa8e842009-08-13 09:34:25 +05301260 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
1261 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
Sujith7d0d0df2010-04-16 11:53:57 +05301262
1263 REGWRITE_BUFFER_FLUSH(ah);
Sujith7d0d0df2010-04-16 11:53:57 +05301264
Sujith1aa8e842009-08-13 09:34:25 +05301265 ath9k_enable_mib_counters(ah);
1266
Sujith2660b812009-02-09 13:27:26 +05301267 if (ah->config.enable_ani)
1268 ah->proc_phyerr |= HAL_PROCESS_ANI;
Sujithf1dc5602008-10-29 10:16:30 +05301269}
Luis R. Rodriguezac0bb762010-06-12 00:33:42 -04001270
1271void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
1272{
1273 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1274 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1275
1276 priv_ops->ani_reset = ath9k_ani_reset_old;
1277 priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old;
1278
1279 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
1280 ops->ani_monitor = ath9k_hw_ani_monitor_old;
Luis R. Rodrigueze36b27a2010-06-12 00:33:45 -04001281
1282 ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
1283}
1284
1285void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
1286{
1287 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
1288 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
1289
1290 priv_ops->ani_reset = ath9k_ani_reset_new;
1291 priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
1292
1293 ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
1294 ops->ani_monitor = ath9k_hw_ani_monitor_new;
1295
1296 ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");
Luis R. Rodriguezac0bb762010-06-12 00:33:42 -04001297}