blob: 031802c8c1250b934b9505c1dcbf883fd520b768 [file] [log] [blame]
Sujithf1dc5602008-10-29 10:16:30 +05301/*
Sujithcee075a2009-03-13 09:07:23 +05302 * Copyright (c) 2008-2009 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
Luis R. Rodriguezcfe8cba2009-09-13 23:39:31 -070017#include "hw.h"
Luis R. Rodriguez8fe65362010-04-15 17:38:14 -040018#include "ar9002_phy.h"
Sujithf1dc5602008-10-29 10:16:30 +053019
Sujithcbe61d82009-02-09 13:27:12 +053020static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
Sujithf1dc5602008-10-29 10:16:30 +053021 struct ath9k_channel *chan)
22{
Sujithf1dc5602008-10-29 10:16:30 +053023 int i;
24
Sujith2660b812009-02-09 13:27:26 +053025 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
26 if (ah->ani[i].c &&
27 ah->ani[i].c->channel == chan->channel)
Sujithf1dc5602008-10-29 10:16:30 +053028 return i;
Sujith2660b812009-02-09 13:27:26 +053029 if (ah->ani[i].c == NULL) {
30 ah->ani[i].c = chan;
Sujithf1dc5602008-10-29 10:16:30 +053031 return i;
32 }
33 }
34
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070035 ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
36 "No more channel states left. Using channel 0\n");
Sujithf1dc5602008-10-29 10:16:30 +053037
38 return 0;
39}
40
Sujithcbe61d82009-02-09 13:27:12 +053041static bool ath9k_hw_ani_control(struct ath_hw *ah,
Sujithf1dc5602008-10-29 10:16:30 +053042 enum ath9k_ani_cmd cmd, int param)
43{
Sujith2660b812009-02-09 13:27:26 +053044 struct ar5416AniState *aniState = ah->curani;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070045 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +053046
Sujith2660b812009-02-09 13:27:26 +053047 switch (cmd & ah->ani_function) {
Sujithf1dc5602008-10-29 10:16:30 +053048 case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
49 u32 level = param;
50
Sujith2660b812009-02-09 13:27:26 +053051 if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -070052 ath_print(common, ATH_DBG_ANI,
53 "level out of range (%u > %u)\n",
54 level,
55 (unsigned)ARRAY_SIZE(ah->totalSizeDesired));
Sujithf1dc5602008-10-29 10:16:30 +053056 return false;
57 }
58
59 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
60 AR_PHY_DESIRED_SZ_TOT_DES,
Sujith2660b812009-02-09 13:27:26 +053061 ah->totalSizeDesired[level]);
Sujithf1dc5602008-10-29 10:16:30 +053062 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
63 AR_PHY_AGC_CTL1_COARSE_LOW,
Sujith2660b812009-02-09 13:27:26 +053064 ah->coarse_low[level]);
Sujithf1dc5602008-10-29 10:16:30 +053065 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
66 AR_PHY_AGC_CTL1_COARSE_HIGH,
Sujith2660b812009-02-09 13:27:26 +053067 ah->coarse_high[level]);
Sujithf1dc5602008-10-29 10:16:30 +053068 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
69 AR_PHY_FIND_SIG_FIRPWR,
Sujith2660b812009-02-09 13:27:26 +053070 ah->firpwr[level]);
Sujithf1dc5602008-10-29 10:16:30 +053071
72 if (level > aniState->noiseImmunityLevel)
Sujith2660b812009-02-09 13:27:26 +053073 ah->stats.ast_ani_niup++;
Sujithf1dc5602008-10-29 10:16:30 +053074 else if (level < aniState->noiseImmunityLevel)
Sujith2660b812009-02-09 13:27:26 +053075 ah->stats.ast_ani_nidown++;
Sujithf1dc5602008-10-29 10:16:30 +053076 aniState->noiseImmunityLevel = level;
77 break;
78 }
79 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
80 const int m1ThreshLow[] = { 127, 50 };
81 const int m2ThreshLow[] = { 127, 40 };
82 const int m1Thresh[] = { 127, 0x4d };
83 const int m2Thresh[] = { 127, 0x40 };
84 const int m2CountThr[] = { 31, 16 };
85 const int m2CountThrLow[] = { 63, 48 };
86 u32 on = param ? 1 : 0;
87
88 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
89 AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
90 m1ThreshLow[on]);
91 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
92 AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
93 m2ThreshLow[on]);
94 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
95 AR_PHY_SFCORR_M1_THRESH,
96 m1Thresh[on]);
97 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
98 AR_PHY_SFCORR_M2_THRESH,
99 m2Thresh[on]);
100 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
101 AR_PHY_SFCORR_M2COUNT_THR,
102 m2CountThr[on]);
103 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
104 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
105 m2CountThrLow[on]);
106
107 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
108 AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
109 m1ThreshLow[on]);
110 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
111 AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
112 m2ThreshLow[on]);
113 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
114 AR_PHY_SFCORR_EXT_M1_THRESH,
115 m1Thresh[on]);
116 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
117 AR_PHY_SFCORR_EXT_M2_THRESH,
118 m2Thresh[on]);
119
120 if (on)
121 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
122 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
123 else
124 REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
125 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
126
127 if (!on != aniState->ofdmWeakSigDetectOff) {
128 if (on)
Sujith2660b812009-02-09 13:27:26 +0530129 ah->stats.ast_ani_ofdmon++;
Sujithf1dc5602008-10-29 10:16:30 +0530130 else
Sujith2660b812009-02-09 13:27:26 +0530131 ah->stats.ast_ani_ofdmoff++;
Sujithf1dc5602008-10-29 10:16:30 +0530132 aniState->ofdmWeakSigDetectOff = !on;
133 }
134 break;
135 }
136 case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
137 const int weakSigThrCck[] = { 8, 6 };
138 u32 high = param ? 1 : 0;
139
140 REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
141 AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
142 weakSigThrCck[high]);
143 if (high != aniState->cckWeakSigThreshold) {
144 if (high)
Sujith2660b812009-02-09 13:27:26 +0530145 ah->stats.ast_ani_cckhigh++;
Sujithf1dc5602008-10-29 10:16:30 +0530146 else
Sujith2660b812009-02-09 13:27:26 +0530147 ah->stats.ast_ani_ccklow++;
Sujithf1dc5602008-10-29 10:16:30 +0530148 aniState->cckWeakSigThreshold = high;
149 }
150 break;
151 }
152 case ATH9K_ANI_FIRSTEP_LEVEL:{
153 const int firstep[] = { 0, 4, 8 };
154 u32 level = param;
155
156 if (level >= ARRAY_SIZE(firstep)) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700157 ath_print(common, ATH_DBG_ANI,
158 "level out of range (%u > %u)\n",
159 level,
160 (unsigned) ARRAY_SIZE(firstep));
Sujithf1dc5602008-10-29 10:16:30 +0530161 return false;
162 }
163 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
164 AR_PHY_FIND_SIG_FIRSTEP,
165 firstep[level]);
166 if (level > aniState->firstepLevel)
Sujith2660b812009-02-09 13:27:26 +0530167 ah->stats.ast_ani_stepup++;
Sujithf1dc5602008-10-29 10:16:30 +0530168 else if (level < aniState->firstepLevel)
Sujith2660b812009-02-09 13:27:26 +0530169 ah->stats.ast_ani_stepdown++;
Sujithf1dc5602008-10-29 10:16:30 +0530170 aniState->firstepLevel = level;
171 break;
172 }
173 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
174 const int cycpwrThr1[] =
175 { 2, 4, 6, 8, 10, 12, 14, 16 };
176 u32 level = param;
177
178 if (level >= ARRAY_SIZE(cycpwrThr1)) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700179 ath_print(common, ATH_DBG_ANI,
180 "level out of range (%u > %u)\n",
181 level,
182 (unsigned) ARRAY_SIZE(cycpwrThr1));
Sujithf1dc5602008-10-29 10:16:30 +0530183 return false;
184 }
185 REG_RMW_FIELD(ah, AR_PHY_TIMING5,
186 AR_PHY_TIMING5_CYCPWR_THR1,
187 cycpwrThr1[level]);
188 if (level > aniState->spurImmunityLevel)
Sujith2660b812009-02-09 13:27:26 +0530189 ah->stats.ast_ani_spurup++;
Sujithf1dc5602008-10-29 10:16:30 +0530190 else if (level < aniState->spurImmunityLevel)
Sujith2660b812009-02-09 13:27:26 +0530191 ah->stats.ast_ani_spurdown++;
Sujithf1dc5602008-10-29 10:16:30 +0530192 aniState->spurImmunityLevel = level;
193 break;
194 }
195 case ATH9K_ANI_PRESENT:
196 break;
197 default:
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700198 ath_print(common, ATH_DBG_ANI,
199 "invalid cmd %u\n", cmd);
Sujithf1dc5602008-10-29 10:16:30 +0530200 return false;
201 }
202
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700203 ath_print(common, ATH_DBG_ANI, "ANI parameters:\n");
204 ath_print(common, ATH_DBG_ANI,
205 "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
206 "ofdmWeakSigDetectOff=%d\n",
207 aniState->noiseImmunityLevel,
208 aniState->spurImmunityLevel,
209 !aniState->ofdmWeakSigDetectOff);
210 ath_print(common, ATH_DBG_ANI,
211 "cckWeakSigThreshold=%d, "
212 "firstepLevel=%d, listenTime=%d\n",
213 aniState->cckWeakSigThreshold,
214 aniState->firstepLevel,
215 aniState->listenTime);
216 ath_print(common, ATH_DBG_ANI,
Sujithf1dc5602008-10-29 10:16:30 +0530217 "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700218 aniState->cycleCount,
219 aniState->ofdmPhyErrCount,
Sujithf1dc5602008-10-29 10:16:30 +0530220 aniState->cckPhyErrCount);
221
222 return true;
223}
224
Sujithcbe61d82009-02-09 13:27:12 +0530225static void ath9k_hw_update_mibstats(struct ath_hw *ah,
Sujithf1dc5602008-10-29 10:16:30 +0530226 struct ath9k_mib_stats *stats)
227{
228 stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
229 stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
230 stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
231 stats->rts_good += REG_READ(ah, AR_RTS_OK);
232 stats->beacons += REG_READ(ah, AR_BEACON_CNT);
233}
234
Sujithcbe61d82009-02-09 13:27:12 +0530235static void ath9k_ani_restart(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530236{
Sujithf1dc5602008-10-29 10:16:30 +0530237 struct ar5416AniState *aniState;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700238 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530239
240 if (!DO_ANI(ah))
241 return;
242
Sujith2660b812009-02-09 13:27:26 +0530243 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530244 aniState->listenTime = 0;
Sujithf1dc5602008-10-29 10:16:30 +0530245
Sujith1aa8e842009-08-13 09:34:25 +0530246 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
247 aniState->ofdmPhyErrBase = 0;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700248 ath_print(common, ATH_DBG_ANI,
249 "OFDM Trigger is too high for hw counters\n");
Sujith1aa8e842009-08-13 09:34:25 +0530250 } else {
251 aniState->ofdmPhyErrBase =
252 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
Sujithf1dc5602008-10-29 10:16:30 +0530253 }
Sujith1aa8e842009-08-13 09:34:25 +0530254 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
255 aniState->cckPhyErrBase = 0;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700256 ath_print(common, ATH_DBG_ANI,
257 "CCK Trigger is too high for hw counters\n");
Sujith1aa8e842009-08-13 09:34:25 +0530258 } else {
259 aniState->cckPhyErrBase =
260 AR_PHY_COUNTMAX - aniState->cckTrigHigh;
261 }
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700262 ath_print(common, ATH_DBG_ANI,
263 "Writing ofdmbase=%u cckbase=%u\n",
264 aniState->ofdmPhyErrBase,
265 aniState->cckPhyErrBase);
Sujith1aa8e842009-08-13 09:34:25 +0530266 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
267 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
268 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
269 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
270
271 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
272
Sujithf1dc5602008-10-29 10:16:30 +0530273 aniState->ofdmPhyErrCount = 0;
274 aniState->cckPhyErrCount = 0;
275}
276
Sujithcbe61d82009-02-09 13:27:12 +0530277static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530278{
Luis R. Rodriguezb002a4a2009-09-13 00:03:27 -0700279 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
Sujithf1dc5602008-10-29 10:16:30 +0530280 struct ar5416AniState *aniState;
Sujithf1dc5602008-10-29 10:16:30 +0530281 int32_t rssi;
282
283 if (!DO_ANI(ah))
284 return;
285
Sujith2660b812009-02-09 13:27:26 +0530286 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530287
288 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
289 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
290 aniState->noiseImmunityLevel + 1)) {
291 return;
292 }
293 }
294
295 if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
296 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
297 aniState->spurImmunityLevel + 1)) {
298 return;
299 }
300 }
301
Sujith2660b812009-02-09 13:27:26 +0530302 if (ah->opmode == NL80211_IFTYPE_AP) {
Sujithf1dc5602008-10-29 10:16:30 +0530303 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
304 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
305 aniState->firstepLevel + 1);
306 }
307 return;
308 }
Sujithcbe61d82009-02-09 13:27:12 +0530309 rssi = BEACON_RSSI(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530310 if (rssi > aniState->rssiThrHigh) {
311 if (!aniState->ofdmWeakSigDetectOff) {
312 if (ath9k_hw_ani_control(ah,
313 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
314 false)) {
315 ath9k_hw_ani_control(ah,
316 ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
317 return;
318 }
319 }
320 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
321 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
322 aniState->firstepLevel + 1);
323 return;
324 }
325 } else if (rssi > aniState->rssiThrLow) {
326 if (aniState->ofdmWeakSigDetectOff)
327 ath9k_hw_ani_control(ah,
328 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
329 true);
330 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
331 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
332 aniState->firstepLevel + 1);
333 return;
334 } else {
Sujithd37b7da2009-09-11 08:30:03 +0530335 if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
336 !conf_is_ht(conf)) {
Sujithf1dc5602008-10-29 10:16:30 +0530337 if (!aniState->ofdmWeakSigDetectOff)
338 ath9k_hw_ani_control(ah,
339 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
340 false);
341 if (aniState->firstepLevel > 0)
342 ath9k_hw_ani_control(ah,
343 ATH9K_ANI_FIRSTEP_LEVEL, 0);
344 return;
345 }
346 }
347}
348
Sujithcbe61d82009-02-09 13:27:12 +0530349static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530350{
Luis R. Rodriguezb002a4a2009-09-13 00:03:27 -0700351 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
Sujithf1dc5602008-10-29 10:16:30 +0530352 struct ar5416AniState *aniState;
Sujithf1dc5602008-10-29 10:16:30 +0530353 int32_t rssi;
354
355 if (!DO_ANI(ah))
356 return;
357
Sujith2660b812009-02-09 13:27:26 +0530358 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530359 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
360 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
361 aniState->noiseImmunityLevel + 1)) {
362 return;
363 }
364 }
Sujith2660b812009-02-09 13:27:26 +0530365 if (ah->opmode == NL80211_IFTYPE_AP) {
Sujithf1dc5602008-10-29 10:16:30 +0530366 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
367 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
368 aniState->firstepLevel + 1);
369 }
370 return;
371 }
Sujithcbe61d82009-02-09 13:27:12 +0530372 rssi = BEACON_RSSI(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530373 if (rssi > aniState->rssiThrLow) {
374 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
375 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
376 aniState->firstepLevel + 1);
377 } else {
Sujithd37b7da2009-09-11 08:30:03 +0530378 if ((conf->channel->band == IEEE80211_BAND_2GHZ) &&
379 !conf_is_ht(conf)) {
Sujithf1dc5602008-10-29 10:16:30 +0530380 if (aniState->firstepLevel > 0)
381 ath9k_hw_ani_control(ah,
382 ATH9K_ANI_FIRSTEP_LEVEL, 0);
383 }
384 }
385}
386
Sujithcbe61d82009-02-09 13:27:12 +0530387static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530388{
Sujithf1dc5602008-10-29 10:16:30 +0530389 struct ar5416AniState *aniState;
390 int32_t rssi;
391
Sujith2660b812009-02-09 13:27:26 +0530392 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530393
Sujith2660b812009-02-09 13:27:26 +0530394 if (ah->opmode == NL80211_IFTYPE_AP) {
Sujithf1dc5602008-10-29 10:16:30 +0530395 if (aniState->firstepLevel > 0) {
396 if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
397 aniState->firstepLevel - 1))
398 return;
399 }
400 } else {
Sujithcbe61d82009-02-09 13:27:12 +0530401 rssi = BEACON_RSSI(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530402 if (rssi > aniState->rssiThrHigh) {
403 /* XXX: Handle me */
404 } else if (rssi > aniState->rssiThrLow) {
405 if (aniState->ofdmWeakSigDetectOff) {
406 if (ath9k_hw_ani_control(ah,
407 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
408 true) == true)
409 return;
410 }
411 if (aniState->firstepLevel > 0) {
412 if (ath9k_hw_ani_control(ah,
413 ATH9K_ANI_FIRSTEP_LEVEL,
414 aniState->firstepLevel - 1) == true)
415 return;
416 }
417 } else {
418 if (aniState->firstepLevel > 0) {
419 if (ath9k_hw_ani_control(ah,
420 ATH9K_ANI_FIRSTEP_LEVEL,
421 aniState->firstepLevel - 1) == true)
422 return;
423 }
424 }
425 }
426
427 if (aniState->spurImmunityLevel > 0) {
428 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
429 aniState->spurImmunityLevel - 1))
430 return;
431 }
432
433 if (aniState->noiseImmunityLevel > 0) {
434 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
435 aniState->noiseImmunityLevel - 1);
436 return;
437 }
438}
439
Sujithcbe61d82009-02-09 13:27:12 +0530440static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530441{
Sujithf1dc5602008-10-29 10:16:30 +0530442 struct ar5416AniState *aniState;
443 u32 txFrameCount, rxFrameCount, cycleCount;
444 int32_t listenTime;
445
446 txFrameCount = REG_READ(ah, AR_TFCNT);
447 rxFrameCount = REG_READ(ah, AR_RFCNT);
448 cycleCount = REG_READ(ah, AR_CCCNT);
449
Sujith2660b812009-02-09 13:27:26 +0530450 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530451 if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
452
453 listenTime = 0;
Sujith2660b812009-02-09 13:27:26 +0530454 ah->stats.ast_ani_lzero++;
Sujithf1dc5602008-10-29 10:16:30 +0530455 } else {
456 int32_t ccdelta = cycleCount - aniState->cycleCount;
457 int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
458 int32_t tfdelta = txFrameCount - aniState->txFrameCount;
459 listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
460 }
461 aniState->cycleCount = cycleCount;
462 aniState->txFrameCount = txFrameCount;
463 aniState->rxFrameCount = rxFrameCount;
464
465 return listenTime;
466}
467
Sujithcbe61d82009-02-09 13:27:12 +0530468void ath9k_ani_reset(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530469{
Sujithf1dc5602008-10-29 10:16:30 +0530470 struct ar5416AniState *aniState;
Sujith2660b812009-02-09 13:27:26 +0530471 struct ath9k_channel *chan = ah->curchan;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700472 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530473 int index;
474
475 if (!DO_ANI(ah))
476 return;
477
478 index = ath9k_hw_get_ani_channel_idx(ah, chan);
Sujith2660b812009-02-09 13:27:26 +0530479 aniState = &ah->ani[index];
480 ah->curani = aniState;
Sujithf1dc5602008-10-29 10:16:30 +0530481
Sujith2660b812009-02-09 13:27:26 +0530482 if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
483 && ah->opmode != NL80211_IFTYPE_ADHOC) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700484 ath_print(common, ATH_DBG_ANI,
485 "Reset ANI state opmode %u\n", ah->opmode);
Sujith2660b812009-02-09 13:27:26 +0530486 ah->stats.ast_ani_reset++;
Sujithf1dc5602008-10-29 10:16:30 +0530487
Luis R. Rodriguezc66284f2009-07-16 10:17:35 -0700488 if (ah->opmode == NL80211_IFTYPE_AP) {
489 /*
490 * ath9k_hw_ani_control() will only process items set on
491 * ah->ani_function
492 */
493 if (IS_CHAN_2GHZ(chan))
494 ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
495 ATH9K_ANI_FIRSTEP_LEVEL);
496 else
497 ah->ani_function = 0;
498 }
499
Sujithf1dc5602008-10-29 10:16:30 +0530500 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
501 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
502 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
503 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
504 !ATH9K_ANI_USE_OFDM_WEAK_SIG);
505 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
506 ATH9K_ANI_CCK_WEAK_SIG_THR);
507
508 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
509 ATH9K_RX_FILTER_PHYERR);
510
Sujith2660b812009-02-09 13:27:26 +0530511 if (ah->opmode == NL80211_IFTYPE_AP) {
512 ah->curani->ofdmTrigHigh =
513 ah->config.ofdm_trig_high;
514 ah->curani->ofdmTrigLow =
515 ah->config.ofdm_trig_low;
516 ah->curani->cckTrigHigh =
517 ah->config.cck_trig_high;
518 ah->curani->cckTrigLow =
519 ah->config.cck_trig_low;
Sujithf1dc5602008-10-29 10:16:30 +0530520 }
521 ath9k_ani_restart(ah);
522 return;
523 }
524
525 if (aniState->noiseImmunityLevel != 0)
526 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
527 aniState->noiseImmunityLevel);
528 if (aniState->spurImmunityLevel != 0)
529 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
530 aniState->spurImmunityLevel);
531 if (aniState->ofdmWeakSigDetectOff)
532 ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
533 !aniState->ofdmWeakSigDetectOff);
534 if (aniState->cckWeakSigThreshold)
535 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
536 aniState->cckWeakSigThreshold);
537 if (aniState->firstepLevel != 0)
538 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
539 aniState->firstepLevel);
Sujithf1dc5602008-10-29 10:16:30 +0530540
Sujith1aa8e842009-08-13 09:34:25 +0530541 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
542 ~ATH9K_RX_FILTER_PHYERR);
543 ath9k_ani_restart(ah);
544 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
545 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
Sujithf1dc5602008-10-29 10:16:30 +0530546}
547
Sujithcbe61d82009-02-09 13:27:12 +0530548void ath9k_hw_ani_monitor(struct ath_hw *ah,
Sujithf1dc5602008-10-29 10:16:30 +0530549 struct ath9k_channel *chan)
550{
Sujithf1dc5602008-10-29 10:16:30 +0530551 struct ar5416AniState *aniState;
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700552 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530553 int32_t listenTime;
Sujith1aa8e842009-08-13 09:34:25 +0530554 u32 phyCnt1, phyCnt2;
555 u32 ofdmPhyErrCnt, cckPhyErrCnt;
Sujithf1dc5602008-10-29 10:16:30 +0530556
Gabor Juhos99506882009-01-14 20:17:11 +0100557 if (!DO_ANI(ah))
558 return;
559
Sujith2660b812009-02-09 13:27:26 +0530560 aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530561
562 listenTime = ath9k_hw_ani_get_listen_time(ah);
563 if (listenTime < 0) {
Sujith2660b812009-02-09 13:27:26 +0530564 ah->stats.ast_ani_lneg++;
Sujithf1dc5602008-10-29 10:16:30 +0530565 ath9k_ani_restart(ah);
566 return;
567 }
568
569 aniState->listenTime += listenTime;
570
Sujith1aa8e842009-08-13 09:34:25 +0530571 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
Sujithf1dc5602008-10-29 10:16:30 +0530572
Sujith1aa8e842009-08-13 09:34:25 +0530573 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
574 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
Sujithf1dc5602008-10-29 10:16:30 +0530575
Sujith1aa8e842009-08-13 09:34:25 +0530576 if (phyCnt1 < aniState->ofdmPhyErrBase ||
577 phyCnt2 < aniState->cckPhyErrBase) {
578 if (phyCnt1 < aniState->ofdmPhyErrBase) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700579 ath_print(common, ATH_DBG_ANI,
580 "phyCnt1 0x%x, resetting "
581 "counter value to 0x%x\n",
582 phyCnt1,
583 aniState->ofdmPhyErrBase);
Sujith1aa8e842009-08-13 09:34:25 +0530584 REG_WRITE(ah, AR_PHY_ERR_1,
585 aniState->ofdmPhyErrBase);
586 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
587 AR_PHY_ERR_OFDM_TIMING);
Sujithf1dc5602008-10-29 10:16:30 +0530588 }
Sujith1aa8e842009-08-13 09:34:25 +0530589 if (phyCnt2 < aniState->cckPhyErrBase) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700590 ath_print(common, ATH_DBG_ANI,
591 "phyCnt2 0x%x, resetting "
592 "counter value to 0x%x\n",
593 phyCnt2,
594 aniState->cckPhyErrBase);
Sujith1aa8e842009-08-13 09:34:25 +0530595 REG_WRITE(ah, AR_PHY_ERR_2,
596 aniState->cckPhyErrBase);
597 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
598 AR_PHY_ERR_CCK_TIMING);
599 }
600 return;
Sujithf1dc5602008-10-29 10:16:30 +0530601 }
602
Sujith1aa8e842009-08-13 09:34:25 +0530603 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
604 ah->stats.ast_ani_ofdmerrs +=
605 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
606 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
607
608 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
609 ah->stats.ast_ani_cckerrs +=
610 cckPhyErrCnt - aniState->cckPhyErrCount;
611 aniState->cckPhyErrCount = cckPhyErrCnt;
612
Sujith2660b812009-02-09 13:27:26 +0530613 if (aniState->listenTime > 5 * ah->aniperiod) {
Sujithf1dc5602008-10-29 10:16:30 +0530614 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
615 aniState->ofdmTrigLow / 1000 &&
616 aniState->cckPhyErrCount <= aniState->listenTime *
617 aniState->cckTrigLow / 1000)
618 ath9k_hw_ani_lower_immunity(ah);
619 ath9k_ani_restart(ah);
Sujith2660b812009-02-09 13:27:26 +0530620 } else if (aniState->listenTime > ah->aniperiod) {
Sujithf1dc5602008-10-29 10:16:30 +0530621 if (aniState->ofdmPhyErrCount > aniState->listenTime *
622 aniState->ofdmTrigHigh / 1000) {
623 ath9k_hw_ani_ofdm_err_trigger(ah);
624 ath9k_ani_restart(ah);
625 } else if (aniState->cckPhyErrCount >
626 aniState->listenTime * aniState->cckTrigHigh /
627 1000) {
628 ath9k_hw_ani_cck_err_trigger(ah);
629 ath9k_ani_restart(ah);
630 }
631 }
632}
Luis R. Rodriguez7322fd12009-09-23 23:07:00 -0400633EXPORT_SYMBOL(ath9k_hw_ani_monitor);
Sujithf1dc5602008-10-29 10:16:30 +0530634
Sujithcbe61d82009-02-09 13:27:12 +0530635void ath9k_enable_mib_counters(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530636{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700637 struct ath_common *common = ath9k_hw_common(ah);
638
639 ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n");
Sujithf1dc5602008-10-29 10:16:30 +0530640
Sujithcbe61d82009-02-09 13:27:12 +0530641 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
Sujithf1dc5602008-10-29 10:16:30 +0530642
643 REG_WRITE(ah, AR_FILT_OFDM, 0);
644 REG_WRITE(ah, AR_FILT_CCK, 0);
645 REG_WRITE(ah, AR_MIBC,
646 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
647 & 0x0f);
648 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
649 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
650}
651
Sujith0fd06c92009-02-12 10:06:51 +0530652/* Freeze the MIB counters, get the stats and then clear them */
Sujithcbe61d82009-02-09 13:27:12 +0530653void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530654{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700655 struct ath_common *common = ath9k_hw_common(ah);
656
657 ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n");
658
Sujith0fd06c92009-02-12 10:06:51 +0530659 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
Sujithcbe61d82009-02-09 13:27:12 +0530660 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
Sujith0fd06c92009-02-12 10:06:51 +0530661 REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
Sujithf1dc5602008-10-29 10:16:30 +0530662 REG_WRITE(ah, AR_FILT_OFDM, 0);
663 REG_WRITE(ah, AR_FILT_CCK, 0);
664}
665
Sujithcbe61d82009-02-09 13:27:12 +0530666u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
Sujithf1dc5602008-10-29 10:16:30 +0530667 u32 *rxc_pcnt,
668 u32 *rxf_pcnt,
669 u32 *txf_pcnt)
670{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700671 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530672 static u32 cycles, rx_clear, rx_frame, tx_frame;
673 u32 good = 1;
674
675 u32 rc = REG_READ(ah, AR_RCCNT);
676 u32 rf = REG_READ(ah, AR_RFCNT);
677 u32 tf = REG_READ(ah, AR_TFCNT);
678 u32 cc = REG_READ(ah, AR_CCCNT);
679
680 if (cycles == 0 || cycles > cc) {
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700681 ath_print(common, ATH_DBG_ANI,
682 "cycle counter wrap. ExtBusy = 0\n");
Sujithf1dc5602008-10-29 10:16:30 +0530683 good = 0;
684 } else {
685 u32 cc_d = cc - cycles;
686 u32 rc_d = rc - rx_clear;
687 u32 rf_d = rf - rx_frame;
688 u32 tf_d = tf - tx_frame;
689
690 if (cc_d != 0) {
691 *rxc_pcnt = rc_d * 100 / cc_d;
692 *rxf_pcnt = rf_d * 100 / cc_d;
693 *txf_pcnt = tf_d * 100 / cc_d;
694 } else {
695 good = 0;
696 }
697 }
698
699 cycles = cc;
700 rx_frame = rf;
701 rx_clear = rc;
702 tx_frame = tf;
703
704 return good;
705}
706
707/*
708 * Process a MIB interrupt. We may potentially be invoked because
709 * any of the MIB counters overflow/trigger so don't assume we're
710 * here because a PHY error counter triggered.
711 */
Vasanthakumar Thiagarajan22e66a42009-08-19 16:23:40 +0530712void ath9k_hw_procmibevent(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530713{
Sujithf1dc5602008-10-29 10:16:30 +0530714 u32 phyCnt1, phyCnt2;
715
716 /* Reset these counters regardless */
717 REG_WRITE(ah, AR_FILT_OFDM, 0);
718 REG_WRITE(ah, AR_FILT_CCK, 0);
719 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
720 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
721
722 /* Clear the mib counters and save them in the stats */
Sujithcbe61d82009-02-09 13:27:12 +0530723 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
Sujithf1dc5602008-10-29 10:16:30 +0530724
725 if (!DO_ANI(ah))
726 return;
727
728 /* NB: these are not reset-on-read */
729 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
730 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
731 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
732 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
Sujith2660b812009-02-09 13:27:26 +0530733 struct ar5416AniState *aniState = ah->curani;
Sujithf1dc5602008-10-29 10:16:30 +0530734 u32 ofdmPhyErrCnt, cckPhyErrCnt;
735
736 /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
737 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
Sujith2660b812009-02-09 13:27:26 +0530738 ah->stats.ast_ani_ofdmerrs +=
Sujithf1dc5602008-10-29 10:16:30 +0530739 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
740 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
741
742 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
Sujith2660b812009-02-09 13:27:26 +0530743 ah->stats.ast_ani_cckerrs +=
Sujithf1dc5602008-10-29 10:16:30 +0530744 cckPhyErrCnt - aniState->cckPhyErrCount;
745 aniState->cckPhyErrCount = cckPhyErrCnt;
746
747 /*
748 * NB: figure out which counter triggered. If both
749 * trigger we'll only deal with one as the processing
750 * clobbers the error counter so the trigger threshold
751 * check will never be true.
752 */
753 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
754 ath9k_hw_ani_ofdm_err_trigger(ah);
755 if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
756 ath9k_hw_ani_cck_err_trigger(ah);
757 /* NB: always restart to insure the h/w counters are reset */
758 ath9k_ani_restart(ah);
759 }
760}
Luis R. Rodriguez7322fd12009-09-23 23:07:00 -0400761EXPORT_SYMBOL(ath9k_hw_procmibevent);
Sujithf1dc5602008-10-29 10:16:30 +0530762
Sujithcbe61d82009-02-09 13:27:12 +0530763void ath9k_hw_ani_setup(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530764{
Sujithf1dc5602008-10-29 10:16:30 +0530765 int i;
766
767 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
768 const int coarseHigh[] = { -14, -14, -14, -14, -12 };
769 const int coarseLow[] = { -64, -64, -64, -64, -70 };
770 const int firpwr[] = { -78, -78, -78, -78, -80 };
771
772 for (i = 0; i < 5; i++) {
Sujith2660b812009-02-09 13:27:26 +0530773 ah->totalSizeDesired[i] = totalSizeDesired[i];
774 ah->coarse_high[i] = coarseHigh[i];
775 ah->coarse_low[i] = coarseLow[i];
776 ah->firpwr[i] = firpwr[i];
Sujithf1dc5602008-10-29 10:16:30 +0530777 }
778}
779
Luis R. Rodriguezf637cfd2009-08-03 12:24:46 -0700780void ath9k_hw_ani_init(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530781{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700782 struct ath_common *common = ath9k_hw_common(ah);
Sujithf1dc5602008-10-29 10:16:30 +0530783 int i;
784
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700785 ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
Sujithf1dc5602008-10-29 10:16:30 +0530786
Sujith2660b812009-02-09 13:27:26 +0530787 memset(ah->ani, 0, sizeof(ah->ani));
788 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
789 ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
790 ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
791 ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
792 ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
793 ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
794 ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
795 ah->ani[i].ofdmWeakSigDetectOff =
Sujithf1dc5602008-10-29 10:16:30 +0530796 !ATH9K_ANI_USE_OFDM_WEAK_SIG;
Sujith2660b812009-02-09 13:27:26 +0530797 ah->ani[i].cckWeakSigThreshold =
Sujithf1dc5602008-10-29 10:16:30 +0530798 ATH9K_ANI_CCK_WEAK_SIG_THR;
Sujith2660b812009-02-09 13:27:26 +0530799 ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
800 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
Sujith1aa8e842009-08-13 09:34:25 +0530801 ah->ani[i].ofdmPhyErrBase =
802 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
803 ah->ani[i].cckPhyErrBase =
804 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
Sujithf1dc5602008-10-29 10:16:30 +0530805 }
Sujithf1dc5602008-10-29 10:16:30 +0530806
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700807 ath_print(common, ATH_DBG_ANI,
808 "Setting OfdmErrBase = 0x%08x\n",
809 ah->ani[0].ofdmPhyErrBase);
810 ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
811 ah->ani[0].cckPhyErrBase);
Sujith1aa8e842009-08-13 09:34:25 +0530812
813 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
814 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
815 ath9k_enable_mib_counters(ah);
816
Sujith2660b812009-02-09 13:27:26 +0530817 ah->aniperiod = ATH9K_ANI_PERIOD;
818 if (ah->config.enable_ani)
819 ah->proc_phyerr |= HAL_PROCESS_ANI;
Sujithf1dc5602008-10-29 10:16:30 +0530820}
821
Luis R. Rodrigueze70c0cf2009-08-03 12:24:51 -0700822void ath9k_hw_ani_disable(struct ath_hw *ah)
Sujithf1dc5602008-10-29 10:16:30 +0530823{
Luis R. Rodriguezc46917b2009-09-13 02:42:02 -0700824 ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n");
Sujithf1dc5602008-10-29 10:16:30 +0530825
Sujith1aa8e842009-08-13 09:34:25 +0530826 ath9k_hw_disable_mib_counters(ah);
827 REG_WRITE(ah, AR_PHY_ERR_1, 0);
828 REG_WRITE(ah, AR_PHY_ERR_2, 0);
Sujithf1dc5602008-10-29 10:16:30 +0530829}