ani.c 16.0 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),
J
Joe Perches 已提交
155
		aniState->rssiThrLow, aniState->rssiThrHigh);
156

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

	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);

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

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

	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;
	}
191 192
}

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

	if (!DO_ANI(ah))
		return;

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

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

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

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

222
	if (ah->opmode == NL80211_IFTYPE_STATION &&
223
	    BEACON_RSSI(ah) <= aniState->rssiThrLow &&
224 225 226
	    immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
		immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;

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

	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 */
240
	if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah))
241 242
		return;

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

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

	if (!DO_ANI(ah))
		return;

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

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

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

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

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

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

/*
 * 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.
 */
292
void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
293
{
294
	struct ar5416AniState *aniState = &ah->curchan->ani;
295 296
	struct ath9k_channel *chan = ah->curchan;
	struct ath_common *common = ath9k_hw_common(ah);
297
	int ofdm_nil, cck_nil;
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318

	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;

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

324 325 326 327 328 329 330 331 332 333 334 335 336
	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) {
337
			ath_dbg(common, ANI,
J
Joe Perches 已提交
338 339 340 341 342 343 344
				"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);
345

346 347
			ofdm_nil = ATH9K_ANI_OFDM_DEF_LEVEL;
			cck_nil = ATH9K_ANI_CCK_DEF_LEVEL;
348 349 350 351 352
		}
	} else {
		/*
		 * restore historical levels for this channel
		 */
353
		ath_dbg(common, ANI,
J
Joe Perches 已提交
354 355 356 357 358 359 360
			"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);
361
	}
362 363
	ath9k_hw_set_ofdm_nil(ah, ofdm_nil, is_scanning);
	ath9k_hw_set_cck_nil(ah, cck_nil, is_scanning);
364 365 366 367 368

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

	ENABLE_REGWRITE_BUFFER(ah);

S
Sujith 已提交
373 374
	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 已提交
375 376

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

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

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

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

	aniState->listenTime += listenTime;

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

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

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

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

408
	return true;
409 410
}

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

	if (!DO_ANI(ah))
		return;

420
	aniState = &ah->curchan->ani;
421 422 423
	if (WARN_ON(!aniState))
		return;

424 425
	if (!ath9k_hw_ani_read_counters(ah))
		return;
426 427 428 429 430 431

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

432
	ath_dbg(common, ANI,
J
Joe Perches 已提交
433 434 435 436 437
		"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);
438

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

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

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

462
	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
S
Sujith 已提交
463

S
Sujith 已提交
464 465
	ENABLE_REGWRITE_BUFFER(ah);

S
Sujith 已提交
466 467 468 469 470 471 472
	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 已提交
473 474

	REGWRITE_BUFFER_FLUSH(ah);
S
Sujith 已提交
475 476
}

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

482
	ath_dbg(common, ANI, "Disable MIB counters\n");
483

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

492
void ath9k_hw_ani_setup(struct ath_hw *ah)
S
Sujith 已提交
493 494 495
{
	int i;

J
Joe Perches 已提交
496 497 498 499
	static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
	static const int coarseHigh[] = { -14, -14, -14, -14, -12 };
	static const int coarseLow[] = { -64, -64, -64, -64, -70 };
	static const int firpwr[] = { -78, -78, -78, -78, -80 };
S
Sujith 已提交
500 501

	for (i = 0; i < 5; i++) {
502 503 504 505
		ah->totalSizeDesired[i] = totalSizeDesired[i];
		ah->coarse_high[i] = coarseHigh[i];
		ah->coarse_low[i] = coarseLow[i];
		ah->firpwr[i] = firpwr[i];
S
Sujith 已提交
506 507 508
	}
}

509
void ath9k_hw_ani_init(struct ath_hw *ah)
S
Sujith 已提交
510
{
511
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
512 513
	int i;

514
	ath_dbg(common, ANI, "Initialize ANI\n");
515

516 517
	ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
	ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
518

519 520
	ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
	ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
521

522 523 524 525
	for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
		struct ath9k_channel *chan = &ah->channels[i];
		struct ar5416AniState *ani = &chan->ani;

526
		ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
527

528
		ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
529

530
		ani->mrcCCK = AR_SREV_9300_20_OR_LATER(ah) ? true : false;
531 532

		ani->ofdmsTurn = true;
533

534 535
		ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
		ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
536
		ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
537
		ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
538
		ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
539 540 541 542 543 544
	}

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

548 549
	if (ah->config.enable_ani)
		ah->proc_phyerr |= HAL_PROCESS_ANI;
550 551 552

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