ani.c 15.4 KB
Newer Older
S
Sujith 已提交
1
/*
2
 * Copyright (c) 2008-2011 Atheros Communications Inc.
S
Sujith 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

17
#include <linux/kernel.h>
18
#include <linux/export.h>
19
#include "hw.h"
20
#include "hw-ops.h"
S
Sujith 已提交
21

22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
struct ani_ofdm_level_entry {
	int spur_immunity_level;
	int fir_step_level;
	int ofdm_weak_signal_on;
};

/* values here are relative to the INI */

/*
 * Legend:
 *
 * SI: Spur immunity
 * FS: FIR Step
 * WS: OFDM / CCK Weak Signal detection
 * MRC-CCK: Maximal Ratio Combining for CCK
 */

static const struct ani_ofdm_level_entry ofdm_level_table[] = {
	/* SI  FS  WS */
	{  0,  0,  1  }, /* lvl 0 */
	{  1,  1,  1  }, /* lvl 1 */
	{  2,  2,  1  }, /* lvl 2 */
	{  3,  2,  1  }, /* lvl 3  (default) */
	{  4,  3,  1  }, /* lvl 4 */
	{  5,  4,  1  }, /* lvl 5 */
	{  6,  5,  1  }, /* lvl 6 */
	{  7,  6,  1  }, /* lvl 7 */
49 50
	{  7,  6,  0  }, /* lvl 8 */
	{  7,  7,  0  }  /* lvl 9 */
51 52
};
#define ATH9K_ANI_OFDM_NUM_LEVEL \
53
	ARRAY_SIZE(ofdm_level_table)
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#define ATH9K_ANI_OFDM_MAX_LEVEL \
	(ATH9K_ANI_OFDM_NUM_LEVEL-1)
#define ATH9K_ANI_OFDM_DEF_LEVEL \
	3 /* default level - matches the INI settings */

/*
 * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm.
 * With OFDM for single stream you just add up all antenna inputs, you're
 * only interested in what you get after FFT. Signal aligment is also not
 * required for OFDM because any phase difference adds up in the frequency
 * domain.
 *
 * MRC requires extra work for use with CCK. You need to align the antenna
 * signals from the different antenna before you can add the signals together.
 * You need aligment of signals as CCK is in time domain, so addition can cancel
 * your signal completely if phase is 180 degrees (think of adding sine waves).
 * You also need to remove noise before the addition and this is where ANI
 * MRC CCK comes into play. One of the antenna inputs may be stronger but
 * lower SNR, so just adding after alignment can be dangerous.
 *
 * Regardless of alignment in time, the antenna signals add constructively after
 * FFT and improve your reception. For more information:
 *
 * http://en.wikipedia.org/wiki/Maximal-ratio_combining
 */

struct ani_cck_level_entry {
	int fir_step_level;
	int mrc_cck_on;
};

static const struct ani_cck_level_entry cck_level_table[] = {
	/* FS  MRC-CCK  */
	{  0,  1  }, /* lvl 0 */
	{  1,  1  }, /* lvl 1 */
	{  2,  1  }, /* lvl 2  (default) */
	{  3,  1  }, /* lvl 3 */
	{  4,  0  }, /* lvl 4 */
	{  5,  0  }, /* lvl 5 */
	{  6,  0  }, /* lvl 6 */
94 95
	{  6,  0  }, /* lvl 7 (only for high rssi) */
	{  7,  0  }  /* lvl 8 (only for high rssi) */
96 97 98
};

#define ATH9K_ANI_CCK_NUM_LEVEL \
99
	ARRAY_SIZE(cck_level_table)
100 101 102 103 104 105 106
#define ATH9K_ANI_CCK_MAX_LEVEL \
	(ATH9K_ANI_CCK_NUM_LEVEL-1)
#define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \
	(ATH9K_ANI_CCK_NUM_LEVEL-3)
#define ATH9K_ANI_CCK_DEF_LEVEL \
	2 /* default level - matches the INI settings */

107
static void ath9k_hw_update_mibstats(struct ath_hw *ah,
S
Sujith 已提交
108 109 110 111 112 113 114 115 116
				     struct ath9k_mib_stats *stats)
{
	stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
	stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
	stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
	stats->rts_good += REG_READ(ah, AR_RTS_OK);
	stats->beacons += REG_READ(ah, AR_BEACON_CNT);
}

117
static void ath9k_ani_restart(struct ath_hw *ah)
S
Sujith 已提交
118 119 120 121 122 123
{
	struct ar5416AniState *aniState;

	if (!DO_ANI(ah))
		return;

124
	aniState = &ah->curchan->ani;
S
Sujith 已提交
125
	aniState->listenTime = 0;
S
Sujith 已提交
126

127 128
	ENABLE_REGWRITE_BUFFER(ah);

129 130
	REG_WRITE(ah, AR_PHY_ERR_1, 0);
	REG_WRITE(ah, AR_PHY_ERR_2, 0);
131 132 133 134 135 136 137 138 139 140 141 142
	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);

	REGWRITE_BUFFER_FLUSH(ah);

	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);

	aniState->ofdmPhyErrCount = 0;
	aniState->cckPhyErrCount = 0;
}

/* Adjust the OFDM Noise Immunity Level */
143 144
static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
				  bool scan)
145
{
146
	struct ar5416AniState *aniState = &ah->curchan->ani;
147 148 149
	struct ath_common *common = ath9k_hw_common(ah);
	const struct ani_ofdm_level_entry *entry_ofdm;
	const struct ani_cck_level_entry *entry_cck;
150
	bool weak_sig;
151

152
	ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
J
Joe Perches 已提交
153
		aniState->ofdmNoiseImmunityLevel,
154
		immunityLevel, BEACON_RSSI(ah),
155 156
		ATH9K_ANI_RSSI_THR_LOW,
		ATH9K_ANI_RSSI_THR_HIGH);
157

158
	if (!scan)
159
		aniState->ofdmNoiseImmunityLevel = immunityLevel;
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

	entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
	entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];

	if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level)
		ath9k_hw_ani_control(ah,
				     ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
				     entry_ofdm->spur_immunity_level);

	if (aniState->firstepLevel != entry_ofdm->fir_step_level &&
	    entry_ofdm->fir_step_level >= entry_cck->fir_step_level)
		ath9k_hw_ani_control(ah,
				     ATH9K_ANI_FIRSTEP_LEVEL,
				     entry_ofdm->fir_step_level);

175 176
	weak_sig = entry_ofdm->ofdm_weak_signal_on;
	if (ah->opmode == NL80211_IFTYPE_STATION &&
177
	    BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH)
178 179
		weak_sig = true;

180
	if (aniState->ofdmWeakSigDetect != weak_sig)
181 182 183
			ath9k_hw_ani_control(ah,
				ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
				entry_ofdm->ofdm_weak_signal_on);
184 185 186 187 188 189 190 191

	if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
		ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
		ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI;
	} else {
		ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI;
		ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
	}
192 193
}

194
static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
195 196 197 198 199 200
{
	struct ar5416AniState *aniState;

	if (!DO_ANI(ah))
		return;

201
	aniState = &ah->curchan->ani;
202 203

	if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
204
		ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false);
205 206 207 208 209
}

/*
 * Set the ANI settings to match an CCK level.
 */
210 211
static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
				 bool scan)
212
{
213
	struct ar5416AniState *aniState = &ah->curchan->ani;
214 215 216 217
	struct ath_common *common = ath9k_hw_common(ah);
	const struct ani_ofdm_level_entry *entry_ofdm;
	const struct ani_cck_level_entry *entry_cck;

218
	ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
J
Joe Perches 已提交
219
		aniState->cckNoiseImmunityLevel, immunityLevel,
220 221
		BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
		ATH9K_ANI_RSSI_THR_HIGH);
222

223
	if (ah->opmode == NL80211_IFTYPE_STATION &&
224
	    BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
225 226 227
	    immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
		immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;

228
	if (!scan)
229
		aniState->cckNoiseImmunityLevel = immunityLevel;
230 231 232 233 234 235 236 237 238 239 240

	entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
	entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];

	if (aniState->firstepLevel != entry_cck->fir_step_level &&
	    entry_cck->fir_step_level >= entry_ofdm->fir_step_level)
		ath9k_hw_ani_control(ah,
				     ATH9K_ANI_FIRSTEP_LEVEL,
				     entry_cck->fir_step_level);

	/* Skip MRC CCK for pre AR9003 families */
241
	if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah))
242 243
		return;

244
	if (aniState->mrcCCK != entry_cck->mrc_cck_on)
245 246 247 248 249
		ath9k_hw_ani_control(ah,
				     ATH9K_ANI_MRC_CCK,
				     entry_cck->mrc_cck_on);
}

250
static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
251 252 253 254 255 256
{
	struct ar5416AniState *aniState;

	if (!DO_ANI(ah))
		return;

257
	aniState = &ah->curchan->ani;
258 259

	if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
260 261
		ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1,
				     false);
262 263 264 265 266 267
}

/*
 * only lower either OFDM or CCK errors per turn
 * we lower the other one next time
 */
268
static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
269 270 271
{
	struct ar5416AniState *aniState;

272
	aniState = &ah->curchan->ani;
273 274 275 276

	/* lower OFDM noise immunity */
	if (aniState->ofdmNoiseImmunityLevel > 0 &&
	    (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) {
277 278
		ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1,
				      false);
279 280 281 282 283
		return;
	}

	/* lower CCK noise immunity */
	if (aniState->cckNoiseImmunityLevel > 0)
284 285
		ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1,
				     false);
286 287 288 289 290 291 292
}

/*
 * Restore the ANI parameters in the HAL and reset the statistics.
 * This routine should be called for every hardware reset and for
 * every channel change.
 */
293
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
294
{
295
	struct ar5416AniState *aniState = &ah->curchan->ani;
296 297
	struct ath9k_channel *chan = ah->curchan;
	struct ath_common *common = ath9k_hw_common(ah);
298
	int ofdm_nil, cck_nil;
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319

	if (!DO_ANI(ah))
		return;

	BUG_ON(aniState == NULL);
	ah->stats.ast_ani_reset++;

	/* only allow a subset of functions in AP mode */
	if (ah->opmode == NL80211_IFTYPE_AP) {
		if (IS_CHAN_2GHZ(chan)) {
			ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
					    ATH9K_ANI_FIRSTEP_LEVEL);
			if (AR_SREV_9300_20_OR_LATER(ah))
				ah->ani_function |= ATH9K_ANI_MRC_CCK;
		} else
			ah->ani_function = 0;
	}

	/* always allow mode (on/off) to be controlled */
	ah->ani_function |= ATH9K_ANI_MODE;

320 321 322 323 324
	ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
			 aniState->ofdmNoiseImmunityLevel);
	cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
			 aniState->cckNoiseImmunityLevel);

325 326 327 328 329 330 331 332 333 334 335 336 337
	if (is_scanning ||
	    (ah->opmode != NL80211_IFTYPE_STATION &&
	     ah->opmode != NL80211_IFTYPE_ADHOC)) {
		/*
		 * If we're scanning or in AP mode, the defaults (ini)
		 * should be in place. For an AP we assume the historical
		 * levels for this channel are probably outdated so start
		 * from defaults instead.
		 */
		if (aniState->ofdmNoiseImmunityLevel !=
		    ATH9K_ANI_OFDM_DEF_LEVEL ||
		    aniState->cckNoiseImmunityLevel !=
		    ATH9K_ANI_CCK_DEF_LEVEL) {
338
			ath_dbg(common, ANI,
J
Joe Perches 已提交
339 340 341 342 343 344 345
				"Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
				ah->opmode,
				chan->channel,
				chan->channelFlags,
				is_scanning,
				aniState->ofdmNoiseImmunityLevel,
				aniState->cckNoiseImmunityLevel);
346

347 348
			ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
			cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
349 350 351 352 353
		}
	} else {
		/*
		 * restore historical levels for this channel
		 */
354
		ath_dbg(common, ANI,
J
Joe Perches 已提交
355 356 357 358 359 360 361
			"Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n",
			ah->opmode,
			chan->channel,
			chan->channelFlags,
			is_scanning,
			aniState->ofdmNoiseImmunityLevel,
			aniState->cckNoiseImmunityLevel);
362
	}
363 364
	ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning);
	ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning);
365 366 367 368 369

	/*
	 * enable phy counters if hw supports or if not, enable phy
	 * interrupts (so we can count each one)
	 */
370
	ath9k_ani_restart(ah);
S
Sujith 已提交
371 372 373

	ENABLE_REGWRITE_BUFFER(ah);

S
Sujith 已提交
374 375
	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
S
Sujith 已提交
376 377

	REGWRITE_BUFFER_FLUSH(ah);
S
Sujith 已提交
378 379
}

380
static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
S
Sujith 已提交
381
{
382
	struct ath_common *common = ath9k_hw_common(ah);
383 384 385
	struct ar5416AniState *aniState = &ah->curchan->ani;
	u32 phyCnt1, phyCnt2;
	int32_t listenTime;
S
Sujith 已提交
386

387 388 389
	ath_hw_cycle_counters_update(common);
	listenTime = ath_hw_get_listen_time(common);

390
	if (listenTime <= 0) {
391
		ah->stats.ast_ani_lneg_or_lzero++;
392
		ath9k_ani_restart(ah);
393
		return false;
S
Sujith 已提交
394 395 396 397
	}

	aniState->listenTime += listenTime;

S
Sujith 已提交
398
	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
S
Sujith 已提交
399

S
Sujith 已提交
400 401 402
	phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
	phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);

403 404 405 406 407
	ah->stats.ast_ani_ofdmerrs += phyCnt1 - aniState->ofdmPhyErrCount;
	aniState->ofdmPhyErrCount = phyCnt1;

	ah->stats.ast_ani_cckerrs += phyCnt2 - aniState->cckPhyErrCount;
	aniState->cckPhyErrCount = phyCnt2;
S
Sujith 已提交
408

409
	return true;
410 411
}

412
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
413 414 415 416 417 418 419 420
{
	struct ar5416AniState *aniState;
	struct ath_common *common = ath9k_hw_common(ah);
	u32 ofdmPhyErrRate, cckPhyErrRate;

	if (!DO_ANI(ah))
		return;

421
	aniState = &ah->curchan->ani;
422 423
	if (!ath9k_hw_ani_read_counters(ah))
		return;
424 425 426 427 428 429

	ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
			 aniState->listenTime;
	cckPhyErrRate =  aniState->cckPhyErrCount * 1000 /
			 aniState->listenTime;

430
	ath_dbg(common, ANI,
J
Joe Perches 已提交
431 432 433 434 435
		"listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n",
		aniState->listenTime,
		aniState->ofdmNoiseImmunityLevel,
		ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
		cckPhyErrRate, aniState->ofdmsTurn);
436

437 438
	if (aniState->listenTime > ah->aniperiod) {
		if (cckPhyErrRate < ah->config.cck_trig_low &&
439
		    ofdmPhyErrRate < ah->config.ofdm_trig_low) {
440 441
			ath9k_hw_ani_lower_immunity(ah);
			aniState->ofdmsTurn = !aniState->ofdmsTurn;
442
		} else if (ofdmPhyErrRate > ah->config.ofdm_trig_high) {
443
			ath9k_hw_ani_ofdm_err_trigger(ah);
444
			aniState->ofdmsTurn = false;
445
		} else if (cckPhyErrRate > ah->config.cck_trig_high) {
446
			ath9k_hw_ani_cck_err_trigger(ah);
447
			aniState->ofdmsTurn = true;
S
Sujith 已提交
448
		}
449
		ath9k_ani_restart(ah);
S
Sujith 已提交
450 451
	}
}
452
EXPORT_SYMBOL(ath9k_hw_ani_monitor);
S
Sujith 已提交
453

454
void ath9k_enable_mib_counters(struct ath_hw *ah)
S
Sujith 已提交
455
{
456 457
	struct ath_common *common = ath9k_hw_common(ah);

458
	ath_dbg(common, ANI, "Enable MIB counters\n");
S
Sujith 已提交
459

460
	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
S
Sujith 已提交
461

S
Sujith 已提交
462 463
	ENABLE_REGWRITE_BUFFER(ah);

S
Sujith 已提交
464 465 466 467 468 469 470
	REG_WRITE(ah, AR_FILT_OFDM, 0);
	REG_WRITE(ah, AR_FILT_CCK, 0);
	REG_WRITE(ah, AR_MIBC,
		  ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
		  & 0x0f);
	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
S
Sujith 已提交
471 472

	REGWRITE_BUFFER_FLUSH(ah);
S
Sujith 已提交
473 474
}

475
/* Freeze the MIB counters, get the stats and then clear them */
476
void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
S
Sujith 已提交
477
{
478 479
	struct ath_common *common = ath9k_hw_common(ah);

480
	ath_dbg(common, ANI, "Disable MIB counters\n");
481

482
	REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
483
	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
484
	REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
S
Sujith 已提交
485 486 487
	REG_WRITE(ah, AR_FILT_OFDM, 0);
	REG_WRITE(ah, AR_FILT_CCK, 0);
}
S
Sujith 已提交
488
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
S
Sujith 已提交
489

490
void ath9k_hw_ani_init(struct ath_hw *ah)
S
Sujith 已提交
491
{
492
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
493 494
	int i;

495
	ath_dbg(common, ANI, "Initialize ANI\n");
496

497 498
	ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
	ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
499

500 501
	ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
	ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
502

503 504 505 506
	for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
		struct ath9k_channel *chan = &ah->channels[i];
		struct ar5416AniState *ani = &chan->ani;

507
		ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
508

509
		ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
510

511
		ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false;
512 513

		ani->ofdmsTurn = true;
514

515
		ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
516
		ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
517
		ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
518 519 520 521 522 523
	}

	/*
	 * since we expect some ongoing maintenance on the tables, let's sanity
	 * check here default level should not modify INI setting.
	 */
524 525
	ah->aniperiod = ATH9K_ANI_PERIOD;
	ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL;
S
Sujith 已提交
526

527 528
	if (ah->config.enable_ani)
		ah->proc_phyerr |= HAL_PROCESS_ANI;
529 530 531

	ath9k_ani_restart(ah);
	ath9k_enable_mib_counters(ah);
S
Sujith 已提交
532
}