1*9999SWang.Lin@Sun.COM /*
2*9999SWang.Lin@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3*9999SWang.Lin@Sun.COM * Use is subject to license terms.
4*9999SWang.Lin@Sun.COM */
5*9999SWang.Lin@Sun.COM
6*9999SWang.Lin@Sun.COM /*
7*9999SWang.Lin@Sun.COM * Copyright (c) 2008 Atheros Communications Inc.
8*9999SWang.Lin@Sun.COM *
9*9999SWang.Lin@Sun.COM * Permission to use, copy, modify, and/or distribute this software for any
10*9999SWang.Lin@Sun.COM * purpose with or without fee is hereby granted, provided that the above
11*9999SWang.Lin@Sun.COM * copyright notice and this permission notice appear in all copies.
12*9999SWang.Lin@Sun.COM *
13*9999SWang.Lin@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14*9999SWang.Lin@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15*9999SWang.Lin@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16*9999SWang.Lin@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17*9999SWang.Lin@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18*9999SWang.Lin@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19*9999SWang.Lin@Sun.COM * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20*9999SWang.Lin@Sun.COM */
21*9999SWang.Lin@Sun.COM
22*9999SWang.Lin@Sun.COM #include "arn_core.h"
23*9999SWang.Lin@Sun.COM #include "arn_hw.h"
24*9999SWang.Lin@Sun.COM #include "arn_reg.h"
25*9999SWang.Lin@Sun.COM #include "arn_phy.h"
26*9999SWang.Lin@Sun.COM
27*9999SWang.Lin@Sun.COM static int
ath9k_hw_get_ani_channel_idx(struct ath_hal * ah,struct ath9k_channel * chan)28*9999SWang.Lin@Sun.COM ath9k_hw_get_ani_channel_idx(struct ath_hal *ah, struct ath9k_channel *chan)
29*9999SWang.Lin@Sun.COM {
30*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
31*9999SWang.Lin@Sun.COM int i;
32*9999SWang.Lin@Sun.COM
33*9999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
34*9999SWang.Lin@Sun.COM if (ahp->ah_ani[i].c.channel == chan->channel)
35*9999SWang.Lin@Sun.COM return (i);
36*9999SWang.Lin@Sun.COM if (ahp->ah_ani[i].c.channel == 0) {
37*9999SWang.Lin@Sun.COM ahp->ah_ani[i].c.channel = chan->channel;
38*9999SWang.Lin@Sun.COM ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
39*9999SWang.Lin@Sun.COM return (i);
40*9999SWang.Lin@Sun.COM }
41*9999SWang.Lin@Sun.COM }
42*9999SWang.Lin@Sun.COM
43*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_get_ani_channel_idx(): "
44*9999SWang.Lin@Sun.COM "No more channel states left. Using channel 0\n"));
45*9999SWang.Lin@Sun.COM
46*9999SWang.Lin@Sun.COM return (0);
47*9999SWang.Lin@Sun.COM }
48*9999SWang.Lin@Sun.COM
49*9999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_ani_control(struct ath_hal * ah,enum ath9k_ani_cmd cmd,int param)50*9999SWang.Lin@Sun.COM ath9k_hw_ani_control(struct ath_hal *ah, enum ath9k_ani_cmd cmd, int param)
51*9999SWang.Lin@Sun.COM {
52*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
53*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState = ahp->ah_curani;
54*9999SWang.Lin@Sun.COM
55*9999SWang.Lin@Sun.COM switch (cmd & ahp->ah_ani_function) {
56*9999SWang.Lin@Sun.COM case ATH9K_ANI_NOISE_IMMUNITY_LEVEL: {
57*9999SWang.Lin@Sun.COM uint32_t level = param;
58*9999SWang.Lin@Sun.COM
59*9999SWang.Lin@Sun.COM if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
60*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
61*9999SWang.Lin@Sun.COM "ah->ah_sc, ATH_DBG_ANI",
62*9999SWang.Lin@Sun.COM "%s: level out of range (%u > %u)\n",
63*9999SWang.Lin@Sun.COM __func__, level,
64*9999SWang.Lin@Sun.COM (unsigned)ARRAY_SIZE(ahp->ah_totalSizeDesired)));
65*9999SWang.Lin@Sun.COM
66*9999SWang.Lin@Sun.COM return (B_FALSE);
67*9999SWang.Lin@Sun.COM }
68*9999SWang.Lin@Sun.COM
69*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
70*9999SWang.Lin@Sun.COM AR_PHY_DESIRED_SZ_TOT_DES,
71*9999SWang.Lin@Sun.COM ahp->ah_totalSizeDesired[level]);
72*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
73*9999SWang.Lin@Sun.COM AR_PHY_AGC_CTL1_COARSE_LOW,
74*9999SWang.Lin@Sun.COM ahp->ah_coarseLow[level]);
75*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
76*9999SWang.Lin@Sun.COM AR_PHY_AGC_CTL1_COARSE_HIGH,
77*9999SWang.Lin@Sun.COM ahp->ah_coarseHigh[level]);
78*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
79*9999SWang.Lin@Sun.COM AR_PHY_FIND_SIG_FIRPWR,
80*9999SWang.Lin@Sun.COM ahp->ah_firpwr[level]);
81*9999SWang.Lin@Sun.COM
82*9999SWang.Lin@Sun.COM if (level > aniState->noiseImmunityLevel)
83*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_niup++;
84*9999SWang.Lin@Sun.COM else if (level < aniState->noiseImmunityLevel)
85*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_nidown++;
86*9999SWang.Lin@Sun.COM aniState->noiseImmunityLevel = (uint8_t)level; /* LINT */
87*9999SWang.Lin@Sun.COM break;
88*9999SWang.Lin@Sun.COM }
89*9999SWang.Lin@Sun.COM case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION: {
90*9999SWang.Lin@Sun.COM const int m1ThreshLow[] = { 127, 50 };
91*9999SWang.Lin@Sun.COM const int m2ThreshLow[] = { 127, 40 };
92*9999SWang.Lin@Sun.COM const int m1Thresh[] = { 127, 0x4d };
93*9999SWang.Lin@Sun.COM const int m2Thresh[] = { 127, 0x40 };
94*9999SWang.Lin@Sun.COM const int m2CountThr[] = { 31, 16 };
95*9999SWang.Lin@Sun.COM const int m2CountThrLow[] = { 63, 48 };
96*9999SWang.Lin@Sun.COM uint32_t on = param ? 1 : 0;
97*9999SWang.Lin@Sun.COM
98*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
99*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
100*9999SWang.Lin@Sun.COM m1ThreshLow[on]);
101*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
102*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
103*9999SWang.Lin@Sun.COM m2ThreshLow[on]);
104*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR,
105*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_M1_THRESH,
106*9999SWang.Lin@Sun.COM m1Thresh[on]);
107*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR,
108*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_M2_THRESH,
109*9999SWang.Lin@Sun.COM m2Thresh[on]);
110*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR,
111*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_M2COUNT_THR,
112*9999SWang.Lin@Sun.COM m2CountThr[on]);
113*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
114*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
115*9999SWang.Lin@Sun.COM m2CountThrLow[on]);
116*9999SWang.Lin@Sun.COM
117*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
118*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
119*9999SWang.Lin@Sun.COM m1ThreshLow[on]);
120*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
121*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
122*9999SWang.Lin@Sun.COM m2ThreshLow[on]);
123*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
124*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_EXT_M1_THRESH,
125*9999SWang.Lin@Sun.COM m1Thresh[on]);
126*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
127*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_EXT_M2_THRESH,
128*9999SWang.Lin@Sun.COM m2Thresh[on]);
129*9999SWang.Lin@Sun.COM
130*9999SWang.Lin@Sun.COM if (on)
131*9999SWang.Lin@Sun.COM REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
132*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
133*9999SWang.Lin@Sun.COM else
134*9999SWang.Lin@Sun.COM REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
135*9999SWang.Lin@Sun.COM AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
136*9999SWang.Lin@Sun.COM
137*9999SWang.Lin@Sun.COM if (!on != aniState->ofdmWeakSigDetectOff) {
138*9999SWang.Lin@Sun.COM if (on)
139*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_ofdmon++;
140*9999SWang.Lin@Sun.COM else
141*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_ofdmoff++;
142*9999SWang.Lin@Sun.COM aniState->ofdmWeakSigDetectOff = !on;
143*9999SWang.Lin@Sun.COM }
144*9999SWang.Lin@Sun.COM break;
145*9999SWang.Lin@Sun.COM }
146*9999SWang.Lin@Sun.COM case ATH9K_ANI_CCK_WEAK_SIGNAL_THR: {
147*9999SWang.Lin@Sun.COM const int weakSigThrCck[] = { 8, 6 };
148*9999SWang.Lin@Sun.COM uint32_t high = param ? 1 : 0;
149*9999SWang.Lin@Sun.COM
150*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
151*9999SWang.Lin@Sun.COM AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
152*9999SWang.Lin@Sun.COM weakSigThrCck[high]);
153*9999SWang.Lin@Sun.COM if (high != aniState->cckWeakSigThreshold) {
154*9999SWang.Lin@Sun.COM if (high)
155*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_cckhigh++;
156*9999SWang.Lin@Sun.COM else
157*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_ccklow++;
158*9999SWang.Lin@Sun.COM /* LINT */
159*9999SWang.Lin@Sun.COM aniState->cckWeakSigThreshold = (uint8_t)high;
160*9999SWang.Lin@Sun.COM }
161*9999SWang.Lin@Sun.COM break;
162*9999SWang.Lin@Sun.COM }
163*9999SWang.Lin@Sun.COM case ATH9K_ANI_FIRSTEP_LEVEL: {
164*9999SWang.Lin@Sun.COM const int firstep[] = { 0, 4, 8 };
165*9999SWang.Lin@Sun.COM uint32_t level = param;
166*9999SWang.Lin@Sun.COM
167*9999SWang.Lin@Sun.COM if (level >= ARRAY_SIZE(firstep)) {
168*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
169*9999SWang.Lin@Sun.COM "%s: level out of range (%u > %u)\n",
170*9999SWang.Lin@Sun.COM __func__, level,
171*9999SWang.Lin@Sun.COM (unsigned)ARRAY_SIZE(firstep)));
172*9999SWang.Lin@Sun.COM
173*9999SWang.Lin@Sun.COM return (B_FALSE);
174*9999SWang.Lin@Sun.COM }
175*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
176*9999SWang.Lin@Sun.COM AR_PHY_FIND_SIG_FIRSTEP, firstep[level]);
177*9999SWang.Lin@Sun.COM if (level > aniState->firstepLevel)
178*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_stepup++;
179*9999SWang.Lin@Sun.COM else if (level < aniState->firstepLevel)
180*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_stepdown++;
181*9999SWang.Lin@Sun.COM aniState->firstepLevel = (uint8_t)level; /* LINT */
182*9999SWang.Lin@Sun.COM break;
183*9999SWang.Lin@Sun.COM }
184*9999SWang.Lin@Sun.COM case ATH9K_ANI_SPUR_IMMUNITY_LEVEL: {
185*9999SWang.Lin@Sun.COM const int cycpwrThr1[] =
186*9999SWang.Lin@Sun.COM { 2, 4, 6, 8, 10, 12, 14, 16 };
187*9999SWang.Lin@Sun.COM uint32_t level = param;
188*9999SWang.Lin@Sun.COM
189*9999SWang.Lin@Sun.COM if (level >= ARRAY_SIZE(cycpwrThr1)) {
190*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
191*9999SWang.Lin@Sun.COM "%s: level out of range (%u > %u)\n",
192*9999SWang.Lin@Sun.COM __func__, level,
193*9999SWang.Lin@Sun.COM (unsigned)ARRAY_SIZE(cycpwrThr1)));
194*9999SWang.Lin@Sun.COM
195*9999SWang.Lin@Sun.COM return (B_FALSE);
196*9999SWang.Lin@Sun.COM }
197*9999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TIMING5,
198*9999SWang.Lin@Sun.COM AR_PHY_TIMING5_CYCPWR_THR1, cycpwrThr1[level]);
199*9999SWang.Lin@Sun.COM if (level > aniState->spurImmunityLevel)
200*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_spurup++;
201*9999SWang.Lin@Sun.COM else if (level < aniState->spurImmunityLevel)
202*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_spurdown++;
203*9999SWang.Lin@Sun.COM aniState->spurImmunityLevel = (uint8_t)level; /* LINT */
204*9999SWang.Lin@Sun.COM break;
205*9999SWang.Lin@Sun.COM }
206*9999SWang.Lin@Sun.COM case ATH9K_ANI_PRESENT:
207*9999SWang.Lin@Sun.COM break;
208*9999SWang.Lin@Sun.COM default:
209*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
210*9999SWang.Lin@Sun.COM "%s: invalid cmd %u\n", __func__, cmd));
211*9999SWang.Lin@Sun.COM return (B_FALSE);
212*9999SWang.Lin@Sun.COM }
213*9999SWang.Lin@Sun.COM
214*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
215*9999SWang.Lin@Sun.COM "%s: ANI parameters:\n", __func__));
216*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
217*9999SWang.Lin@Sun.COM "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
218*9999SWang.Lin@Sun.COM "ofdmWeakSigDetectOff=%d\n",
219*9999SWang.Lin@Sun.COM aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
220*9999SWang.Lin@Sun.COM !aniState->ofdmWeakSigDetectOff));
221*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
222*9999SWang.Lin@Sun.COM "cckWeakSigThreshold=%d, "
223*9999SWang.Lin@Sun.COM "firstepLevel=%d, listenTime=%d\n",
224*9999SWang.Lin@Sun.COM aniState->cckWeakSigThreshold, aniState->firstepLevel,
225*9999SWang.Lin@Sun.COM aniState->listenTime));
226*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
227*9999SWang.Lin@Sun.COM "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
228*9999SWang.Lin@Sun.COM aniState->cycleCount, aniState->ofdmPhyErrCount,
229*9999SWang.Lin@Sun.COM aniState->cckPhyErrCount));
230*9999SWang.Lin@Sun.COM
231*9999SWang.Lin@Sun.COM return (B_TRUE);
232*9999SWang.Lin@Sun.COM }
233*9999SWang.Lin@Sun.COM
234*9999SWang.Lin@Sun.COM static void
ath9k_hw_update_mibstats(struct ath_hal * ah,struct ath9k_mib_stats * stats)235*9999SWang.Lin@Sun.COM ath9k_hw_update_mibstats(struct ath_hal *ah, struct ath9k_mib_stats *stats)
236*9999SWang.Lin@Sun.COM {
237*9999SWang.Lin@Sun.COM stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
238*9999SWang.Lin@Sun.COM stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
239*9999SWang.Lin@Sun.COM stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
240*9999SWang.Lin@Sun.COM stats->rts_good += REG_READ(ah, AR_RTS_OK);
241*9999SWang.Lin@Sun.COM stats->beacons += REG_READ(ah, AR_BEACON_CNT);
242*9999SWang.Lin@Sun.COM }
243*9999SWang.Lin@Sun.COM
244*9999SWang.Lin@Sun.COM static void
ath9k_ani_restart(struct ath_hal * ah)245*9999SWang.Lin@Sun.COM ath9k_ani_restart(struct ath_hal *ah)
246*9999SWang.Lin@Sun.COM {
247*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
248*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState;
249*9999SWang.Lin@Sun.COM
250*9999SWang.Lin@Sun.COM if (!DO_ANI(ah))
251*9999SWang.Lin@Sun.COM return;
252*9999SWang.Lin@Sun.COM
253*9999SWang.Lin@Sun.COM aniState = ahp->ah_curani;
254*9999SWang.Lin@Sun.COM
255*9999SWang.Lin@Sun.COM aniState->listenTime = 0;
256*9999SWang.Lin@Sun.COM if (ahp->ah_hasHwPhyCounters) {
257*9999SWang.Lin@Sun.COM if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
258*9999SWang.Lin@Sun.COM aniState->ofdmPhyErrBase = 0;
259*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
260*9999SWang.Lin@Sun.COM "OFDM Trigger is too high for hw counters\n"));
261*9999SWang.Lin@Sun.COM } else {
262*9999SWang.Lin@Sun.COM aniState->ofdmPhyErrBase =
263*9999SWang.Lin@Sun.COM AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
264*9999SWang.Lin@Sun.COM }
265*9999SWang.Lin@Sun.COM if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
266*9999SWang.Lin@Sun.COM aniState->cckPhyErrBase = 0;
267*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
268*9999SWang.Lin@Sun.COM "CCK Trigger is too high for hw counters\n"));
269*9999SWang.Lin@Sun.COM } else {
270*9999SWang.Lin@Sun.COM aniState->cckPhyErrBase =
271*9999SWang.Lin@Sun.COM AR_PHY_COUNTMAX - aniState->cckTrigHigh;
272*9999SWang.Lin@Sun.COM }
273*9999SWang.Lin@Sun.COM
274*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
275*9999SWang.Lin@Sun.COM "%s: Writing ofdmbase=%u cckbase=%u\n",
276*9999SWang.Lin@Sun.COM __func__, aniState->ofdmPhyErrBase,
277*9999SWang.Lin@Sun.COM aniState->cckPhyErrBase));
278*9999SWang.Lin@Sun.COM
279*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
280*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
281*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
282*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
283*9999SWang.Lin@Sun.COM
284*9999SWang.Lin@Sun.COM ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
285*9999SWang.Lin@Sun.COM }
286*9999SWang.Lin@Sun.COM aniState->ofdmPhyErrCount = 0;
287*9999SWang.Lin@Sun.COM aniState->cckPhyErrCount = 0;
288*9999SWang.Lin@Sun.COM }
289*9999SWang.Lin@Sun.COM
290*9999SWang.Lin@Sun.COM static void
ath9k_hw_ani_ofdm_err_trigger(struct ath_hal * ah)291*9999SWang.Lin@Sun.COM ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
292*9999SWang.Lin@Sun.COM {
293*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
294*9999SWang.Lin@Sun.COM struct ath9k_channel *chan = ah->ah_curchan;
295*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState;
296*9999SWang.Lin@Sun.COM enum wireless_mode mode;
297*9999SWang.Lin@Sun.COM int32_t rssi;
298*9999SWang.Lin@Sun.COM
299*9999SWang.Lin@Sun.COM if (!DO_ANI(ah))
300*9999SWang.Lin@Sun.COM return;
301*9999SWang.Lin@Sun.COM
302*9999SWang.Lin@Sun.COM aniState = ahp->ah_curani;
303*9999SWang.Lin@Sun.COM
304*9999SWang.Lin@Sun.COM if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
305*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
306*9999SWang.Lin@Sun.COM aniState->noiseImmunityLevel + 1)) {
307*9999SWang.Lin@Sun.COM return;
308*9999SWang.Lin@Sun.COM }
309*9999SWang.Lin@Sun.COM }
310*9999SWang.Lin@Sun.COM
311*9999SWang.Lin@Sun.COM if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
312*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
313*9999SWang.Lin@Sun.COM aniState->spurImmunityLevel + 1)) {
314*9999SWang.Lin@Sun.COM return;
315*9999SWang.Lin@Sun.COM }
316*9999SWang.Lin@Sun.COM }
317*9999SWang.Lin@Sun.COM
318*9999SWang.Lin@Sun.COM if (ah->ah_opmode == ATH9K_M_HOSTAP) {
319*9999SWang.Lin@Sun.COM if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
320*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
321*9999SWang.Lin@Sun.COM aniState->firstepLevel + 1);
322*9999SWang.Lin@Sun.COM }
323*9999SWang.Lin@Sun.COM return;
324*9999SWang.Lin@Sun.COM }
325*9999SWang.Lin@Sun.COM rssi = BEACON_RSSI(ahp);
326*9999SWang.Lin@Sun.COM if (rssi > aniState->rssiThrHigh) {
327*9999SWang.Lin@Sun.COM if (!aniState->ofdmWeakSigDetectOff) {
328*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah,
329*9999SWang.Lin@Sun.COM ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
330*9999SWang.Lin@Sun.COM B_FALSE)) {
331*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah,
332*9999SWang.Lin@Sun.COM ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
333*9999SWang.Lin@Sun.COM return;
334*9999SWang.Lin@Sun.COM }
335*9999SWang.Lin@Sun.COM }
336*9999SWang.Lin@Sun.COM if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
337*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
338*9999SWang.Lin@Sun.COM aniState->firstepLevel + 1);
339*9999SWang.Lin@Sun.COM return;
340*9999SWang.Lin@Sun.COM }
341*9999SWang.Lin@Sun.COM } else if (rssi > aniState->rssiThrLow) {
342*9999SWang.Lin@Sun.COM if (aniState->ofdmWeakSigDetectOff)
343*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah,
344*9999SWang.Lin@Sun.COM ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
345*9999SWang.Lin@Sun.COM B_TRUE);
346*9999SWang.Lin@Sun.COM if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
347*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
348*9999SWang.Lin@Sun.COM aniState->firstepLevel + 1);
349*9999SWang.Lin@Sun.COM return;
350*9999SWang.Lin@Sun.COM } else {
351*9999SWang.Lin@Sun.COM mode = ath9k_hw_chan2wmode(ah, chan);
352*9999SWang.Lin@Sun.COM if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
353*9999SWang.Lin@Sun.COM if (!aniState->ofdmWeakSigDetectOff)
354*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah,
355*9999SWang.Lin@Sun.COM ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
356*9999SWang.Lin@Sun.COM B_FALSE);
357*9999SWang.Lin@Sun.COM if (aniState->firstepLevel > 0)
358*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah,
359*9999SWang.Lin@Sun.COM ATH9K_ANI_FIRSTEP_LEVEL, 0);
360*9999SWang.Lin@Sun.COM return;
361*9999SWang.Lin@Sun.COM }
362*9999SWang.Lin@Sun.COM }
363*9999SWang.Lin@Sun.COM }
364*9999SWang.Lin@Sun.COM
365*9999SWang.Lin@Sun.COM static void
ath9k_hw_ani_cck_err_trigger(struct ath_hal * ah)366*9999SWang.Lin@Sun.COM ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
367*9999SWang.Lin@Sun.COM {
368*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
369*9999SWang.Lin@Sun.COM struct ath9k_channel *chan = ah->ah_curchan;
370*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState;
371*9999SWang.Lin@Sun.COM enum wireless_mode mode;
372*9999SWang.Lin@Sun.COM int32_t rssi;
373*9999SWang.Lin@Sun.COM
374*9999SWang.Lin@Sun.COM if (!DO_ANI(ah))
375*9999SWang.Lin@Sun.COM return;
376*9999SWang.Lin@Sun.COM
377*9999SWang.Lin@Sun.COM aniState = ahp->ah_curani;
378*9999SWang.Lin@Sun.COM if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
379*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
380*9999SWang.Lin@Sun.COM aniState->noiseImmunityLevel + 1)) {
381*9999SWang.Lin@Sun.COM return;
382*9999SWang.Lin@Sun.COM }
383*9999SWang.Lin@Sun.COM }
384*9999SWang.Lin@Sun.COM if (ah->ah_opmode == ATH9K_M_HOSTAP) {
385*9999SWang.Lin@Sun.COM if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
386*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
387*9999SWang.Lin@Sun.COM aniState->firstepLevel + 1);
388*9999SWang.Lin@Sun.COM }
389*9999SWang.Lin@Sun.COM return;
390*9999SWang.Lin@Sun.COM }
391*9999SWang.Lin@Sun.COM rssi = BEACON_RSSI(ahp);
392*9999SWang.Lin@Sun.COM if (rssi > aniState->rssiThrLow) {
393*9999SWang.Lin@Sun.COM if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
394*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
395*9999SWang.Lin@Sun.COM aniState->firstepLevel + 1);
396*9999SWang.Lin@Sun.COM } else {
397*9999SWang.Lin@Sun.COM mode = ath9k_hw_chan2wmode(ah, chan);
398*9999SWang.Lin@Sun.COM if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
399*9999SWang.Lin@Sun.COM if (aniState->firstepLevel > 0)
400*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah,
401*9999SWang.Lin@Sun.COM ATH9K_ANI_FIRSTEP_LEVEL, 0);
402*9999SWang.Lin@Sun.COM }
403*9999SWang.Lin@Sun.COM }
404*9999SWang.Lin@Sun.COM }
405*9999SWang.Lin@Sun.COM
406*9999SWang.Lin@Sun.COM static void
ath9k_hw_ani_lower_immunity(struct ath_hal * ah)407*9999SWang.Lin@Sun.COM ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
408*9999SWang.Lin@Sun.COM {
409*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
410*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState;
411*9999SWang.Lin@Sun.COM int32_t rssi;
412*9999SWang.Lin@Sun.COM
413*9999SWang.Lin@Sun.COM aniState = ahp->ah_curani;
414*9999SWang.Lin@Sun.COM
415*9999SWang.Lin@Sun.COM if (ah->ah_opmode == ATH9K_M_HOSTAP) {
416*9999SWang.Lin@Sun.COM if (aniState->firstepLevel > 0) {
417*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
418*9999SWang.Lin@Sun.COM aniState->firstepLevel - 1))
419*9999SWang.Lin@Sun.COM return;
420*9999SWang.Lin@Sun.COM }
421*9999SWang.Lin@Sun.COM } else {
422*9999SWang.Lin@Sun.COM rssi = BEACON_RSSI(ahp);
423*9999SWang.Lin@Sun.COM if (rssi > aniState->rssiThrHigh) {
424*9999SWang.Lin@Sun.COM /* XXX: Handle me */
425*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: ath9k_ani_reset():\n"));
426*9999SWang.Lin@Sun.COM } else if (rssi > aniState->rssiThrLow) {
427*9999SWang.Lin@Sun.COM if (aniState->ofdmWeakSigDetectOff) {
428*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah,
429*9999SWang.Lin@Sun.COM ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
430*9999SWang.Lin@Sun.COM B_TRUE) == B_TRUE)
431*9999SWang.Lin@Sun.COM return;
432*9999SWang.Lin@Sun.COM }
433*9999SWang.Lin@Sun.COM if (aniState->firstepLevel > 0) {
434*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah,
435*9999SWang.Lin@Sun.COM ATH9K_ANI_FIRSTEP_LEVEL,
436*9999SWang.Lin@Sun.COM aniState->firstepLevel - 1) == B_TRUE)
437*9999SWang.Lin@Sun.COM return;
438*9999SWang.Lin@Sun.COM }
439*9999SWang.Lin@Sun.COM } else {
440*9999SWang.Lin@Sun.COM if (aniState->firstepLevel > 0) {
441*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah,
442*9999SWang.Lin@Sun.COM ATH9K_ANI_FIRSTEP_LEVEL,
443*9999SWang.Lin@Sun.COM aniState->firstepLevel - 1) == B_TRUE)
444*9999SWang.Lin@Sun.COM return;
445*9999SWang.Lin@Sun.COM }
446*9999SWang.Lin@Sun.COM }
447*9999SWang.Lin@Sun.COM }
448*9999SWang.Lin@Sun.COM
449*9999SWang.Lin@Sun.COM if (aniState->spurImmunityLevel > 0) {
450*9999SWang.Lin@Sun.COM if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
451*9999SWang.Lin@Sun.COM aniState->spurImmunityLevel - 1))
452*9999SWang.Lin@Sun.COM return;
453*9999SWang.Lin@Sun.COM }
454*9999SWang.Lin@Sun.COM
455*9999SWang.Lin@Sun.COM if (aniState->noiseImmunityLevel > 0) {
456*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
457*9999SWang.Lin@Sun.COM aniState->noiseImmunityLevel - 1);
458*9999SWang.Lin@Sun.COM return;
459*9999SWang.Lin@Sun.COM }
460*9999SWang.Lin@Sun.COM }
461*9999SWang.Lin@Sun.COM
462*9999SWang.Lin@Sun.COM static int32_t
ath9k_hw_ani_get_listen_time(struct ath_hal * ah)463*9999SWang.Lin@Sun.COM ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
464*9999SWang.Lin@Sun.COM {
465*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
466*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState;
467*9999SWang.Lin@Sun.COM uint32_t txFrameCount, rxFrameCount, cycleCount;
468*9999SWang.Lin@Sun.COM int32_t listenTime;
469*9999SWang.Lin@Sun.COM
470*9999SWang.Lin@Sun.COM txFrameCount = REG_READ(ah, AR_TFCNT);
471*9999SWang.Lin@Sun.COM rxFrameCount = REG_READ(ah, AR_RFCNT);
472*9999SWang.Lin@Sun.COM cycleCount = REG_READ(ah, AR_CCCNT);
473*9999SWang.Lin@Sun.COM
474*9999SWang.Lin@Sun.COM aniState = ahp->ah_curani;
475*9999SWang.Lin@Sun.COM if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
476*9999SWang.Lin@Sun.COM
477*9999SWang.Lin@Sun.COM listenTime = 0;
478*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_lzero++;
479*9999SWang.Lin@Sun.COM } else {
480*9999SWang.Lin@Sun.COM int32_t ccdelta = cycleCount - aniState->cycleCount;
481*9999SWang.Lin@Sun.COM int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
482*9999SWang.Lin@Sun.COM int32_t tfdelta = txFrameCount - aniState->txFrameCount;
483*9999SWang.Lin@Sun.COM listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
484*9999SWang.Lin@Sun.COM }
485*9999SWang.Lin@Sun.COM aniState->cycleCount = cycleCount;
486*9999SWang.Lin@Sun.COM aniState->txFrameCount = txFrameCount;
487*9999SWang.Lin@Sun.COM aniState->rxFrameCount = rxFrameCount;
488*9999SWang.Lin@Sun.COM
489*9999SWang.Lin@Sun.COM return (listenTime);
490*9999SWang.Lin@Sun.COM }
491*9999SWang.Lin@Sun.COM
492*9999SWang.Lin@Sun.COM void
ath9k_ani_reset(struct ath_hal * ah)493*9999SWang.Lin@Sun.COM ath9k_ani_reset(struct ath_hal *ah)
494*9999SWang.Lin@Sun.COM {
495*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
496*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState;
497*9999SWang.Lin@Sun.COM struct ath9k_channel *chan = ah->ah_curchan;
498*9999SWang.Lin@Sun.COM int index;
499*9999SWang.Lin@Sun.COM
500*9999SWang.Lin@Sun.COM /* For Lint Reasons */
501*9999SWang.Lin@Sun.COM boolean_t ANI_USE_OFDM_WEAK_SIG = ATH9K_ANI_USE_OFDM_WEAK_SIG;
502*9999SWang.Lin@Sun.COM
503*9999SWang.Lin@Sun.COM if (!DO_ANI(ah))
504*9999SWang.Lin@Sun.COM return;
505*9999SWang.Lin@Sun.COM
506*9999SWang.Lin@Sun.COM index = ath9k_hw_get_ani_channel_idx(ah, chan);
507*9999SWang.Lin@Sun.COM aniState = &ahp->ah_ani[index];
508*9999SWang.Lin@Sun.COM ahp->ah_curani = aniState;
509*9999SWang.Lin@Sun.COM
510*9999SWang.Lin@Sun.COM if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA &&
511*9999SWang.Lin@Sun.COM ah->ah_opmode != ATH9K_M_IBSS) {
512*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: ath9k_ani_reset(): "
513*9999SWang.Lin@Sun.COM "Reset ANI state opmode %u\n", ah->ah_opmode));
514*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_reset++;
515*9999SWang.Lin@Sun.COM
516*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah,
517*9999SWang.Lin@Sun.COM ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
518*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah,
519*9999SWang.Lin@Sun.COM ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
520*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
521*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control
522*9999SWang.Lin@Sun.COM (ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
523*9999SWang.Lin@Sun.COM !ANI_USE_OFDM_WEAK_SIG /* !ATH9K_ANI_USE_OFDM_WEAK_SIG */);
524*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
525*9999SWang.Lin@Sun.COM ATH9K_ANI_CCK_WEAK_SIG_THR);
526*9999SWang.Lin@Sun.COM
527*9999SWang.Lin@Sun.COM ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
528*9999SWang.Lin@Sun.COM ATH9K_RX_FILTER_PHYERR);
529*9999SWang.Lin@Sun.COM
530*9999SWang.Lin@Sun.COM if (ah->ah_opmode == ATH9K_M_HOSTAP) {
531*9999SWang.Lin@Sun.COM ahp->ah_curani->ofdmTrigHigh =
532*9999SWang.Lin@Sun.COM ah->ah_config.ofdm_trig_high;
533*9999SWang.Lin@Sun.COM ahp->ah_curani->ofdmTrigLow =
534*9999SWang.Lin@Sun.COM ah->ah_config.ofdm_trig_low;
535*9999SWang.Lin@Sun.COM ahp->ah_curani->cckTrigHigh =
536*9999SWang.Lin@Sun.COM ah->ah_config.cck_trig_high;
537*9999SWang.Lin@Sun.COM ahp->ah_curani->cckTrigLow =
538*9999SWang.Lin@Sun.COM ah->ah_config.cck_trig_low;
539*9999SWang.Lin@Sun.COM }
540*9999SWang.Lin@Sun.COM ath9k_ani_restart(ah);
541*9999SWang.Lin@Sun.COM return;
542*9999SWang.Lin@Sun.COM }
543*9999SWang.Lin@Sun.COM
544*9999SWang.Lin@Sun.COM if (aniState->noiseImmunityLevel != 0)
545*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
546*9999SWang.Lin@Sun.COM aniState->noiseImmunityLevel);
547*9999SWang.Lin@Sun.COM if (aniState->spurImmunityLevel != 0)
548*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
549*9999SWang.Lin@Sun.COM aniState->spurImmunityLevel);
550*9999SWang.Lin@Sun.COM if (aniState->ofdmWeakSigDetectOff)
551*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control
552*9999SWang.Lin@Sun.COM (ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
553*9999SWang.Lin@Sun.COM !aniState->ofdmWeakSigDetectOff);
554*9999SWang.Lin@Sun.COM if (aniState->cckWeakSigThreshold)
555*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
556*9999SWang.Lin@Sun.COM aniState->cckWeakSigThreshold);
557*9999SWang.Lin@Sun.COM if (aniState->firstepLevel != 0)
558*9999SWang.Lin@Sun.COM (void) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
559*9999SWang.Lin@Sun.COM aniState->firstepLevel);
560*9999SWang.Lin@Sun.COM if (ahp->ah_hasHwPhyCounters) {
561*9999SWang.Lin@Sun.COM ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
562*9999SWang.Lin@Sun.COM ~ATH9K_RX_FILTER_PHYERR);
563*9999SWang.Lin@Sun.COM ath9k_ani_restart(ah);
564*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
565*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
566*9999SWang.Lin@Sun.COM
567*9999SWang.Lin@Sun.COM } else {
568*9999SWang.Lin@Sun.COM ath9k_ani_restart(ah);
569*9999SWang.Lin@Sun.COM ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
570*9999SWang.Lin@Sun.COM ATH9K_RX_FILTER_PHYERR);
571*9999SWang.Lin@Sun.COM }
572*9999SWang.Lin@Sun.COM }
573*9999SWang.Lin@Sun.COM
574*9999SWang.Lin@Sun.COM /* ARGSUSED */
575*9999SWang.Lin@Sun.COM void
ath9k_hw_ani_monitor(struct ath_hal * ah,const struct ath9k_node_stats * stats,struct ath9k_channel * chan)576*9999SWang.Lin@Sun.COM ath9k_hw_ani_monitor(struct ath_hal *ah, const struct ath9k_node_stats *stats,
577*9999SWang.Lin@Sun.COM struct ath9k_channel *chan)
578*9999SWang.Lin@Sun.COM {
579*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
580*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState;
581*9999SWang.Lin@Sun.COM int32_t listenTime;
582*9999SWang.Lin@Sun.COM
583*9999SWang.Lin@Sun.COM aniState = ahp->ah_curani;
584*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_nodestats = *stats;
585*9999SWang.Lin@Sun.COM
586*9999SWang.Lin@Sun.COM listenTime = ath9k_hw_ani_get_listen_time(ah);
587*9999SWang.Lin@Sun.COM if (listenTime < 0) {
588*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_lneg++;
589*9999SWang.Lin@Sun.COM ath9k_ani_restart(ah);
590*9999SWang.Lin@Sun.COM return;
591*9999SWang.Lin@Sun.COM }
592*9999SWang.Lin@Sun.COM
593*9999SWang.Lin@Sun.COM aniState->listenTime += listenTime;
594*9999SWang.Lin@Sun.COM
595*9999SWang.Lin@Sun.COM if (ahp->ah_hasHwPhyCounters) {
596*9999SWang.Lin@Sun.COM uint32_t phyCnt1, phyCnt2;
597*9999SWang.Lin@Sun.COM uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
598*9999SWang.Lin@Sun.COM
599*9999SWang.Lin@Sun.COM ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
600*9999SWang.Lin@Sun.COM
601*9999SWang.Lin@Sun.COM phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
602*9999SWang.Lin@Sun.COM phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
603*9999SWang.Lin@Sun.COM
604*9999SWang.Lin@Sun.COM if (phyCnt1 < aniState->ofdmPhyErrBase ||
605*9999SWang.Lin@Sun.COM phyCnt2 < aniState->cckPhyErrBase) {
606*9999SWang.Lin@Sun.COM if (phyCnt1 < aniState->ofdmPhyErrBase) {
607*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
608*9999SWang.Lin@Sun.COM "%s: phyCnt1 0x%x, resetting "
609*9999SWang.Lin@Sun.COM "counter value to 0x%x\n",
610*9999SWang.Lin@Sun.COM __func__, phyCnt1,
611*9999SWang.Lin@Sun.COM aniState->ofdmPhyErrBase));
612*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_1,
613*9999SWang.Lin@Sun.COM aniState->ofdmPhyErrBase);
614*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_MASK_1,
615*9999SWang.Lin@Sun.COM AR_PHY_ERR_OFDM_TIMING);
616*9999SWang.Lin@Sun.COM }
617*9999SWang.Lin@Sun.COM if (phyCnt2 < aniState->cckPhyErrBase) {
618*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
619*9999SWang.Lin@Sun.COM "%s: phyCnt2 0x%x, resetting "
620*9999SWang.Lin@Sun.COM "counter value to 0x%x\n",
621*9999SWang.Lin@Sun.COM __func__, phyCnt2,
622*9999SWang.Lin@Sun.COM aniState->cckPhyErrBase));
623*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_2,
624*9999SWang.Lin@Sun.COM aniState->cckPhyErrBase);
625*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_MASK_2,
626*9999SWang.Lin@Sun.COM AR_PHY_ERR_CCK_TIMING);
627*9999SWang.Lin@Sun.COM }
628*9999SWang.Lin@Sun.COM return;
629*9999SWang.Lin@Sun.COM }
630*9999SWang.Lin@Sun.COM
631*9999SWang.Lin@Sun.COM ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
632*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_ofdmerrs +=
633*9999SWang.Lin@Sun.COM ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
634*9999SWang.Lin@Sun.COM aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
635*9999SWang.Lin@Sun.COM
636*9999SWang.Lin@Sun.COM cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
637*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_cckerrs +=
638*9999SWang.Lin@Sun.COM cckPhyErrCnt - aniState->cckPhyErrCount;
639*9999SWang.Lin@Sun.COM aniState->cckPhyErrCount = cckPhyErrCnt;
640*9999SWang.Lin@Sun.COM }
641*9999SWang.Lin@Sun.COM
642*9999SWang.Lin@Sun.COM if (!DO_ANI(ah))
643*9999SWang.Lin@Sun.COM return;
644*9999SWang.Lin@Sun.COM
645*9999SWang.Lin@Sun.COM if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
646*9999SWang.Lin@Sun.COM if (aniState->ofdmPhyErrCount <= aniState->listenTime *
647*9999SWang.Lin@Sun.COM aniState->ofdmTrigLow / 1000 &&
648*9999SWang.Lin@Sun.COM aniState->cckPhyErrCount <= aniState->listenTime *
649*9999SWang.Lin@Sun.COM aniState->cckTrigLow / 1000)
650*9999SWang.Lin@Sun.COM ath9k_hw_ani_lower_immunity(ah);
651*9999SWang.Lin@Sun.COM ath9k_ani_restart(ah);
652*9999SWang.Lin@Sun.COM } else if (aniState->listenTime > ahp->ah_aniPeriod) {
653*9999SWang.Lin@Sun.COM if (aniState->ofdmPhyErrCount > aniState->listenTime *
654*9999SWang.Lin@Sun.COM aniState->ofdmTrigHigh / 1000) {
655*9999SWang.Lin@Sun.COM ath9k_hw_ani_ofdm_err_trigger(ah);
656*9999SWang.Lin@Sun.COM ath9k_ani_restart(ah);
657*9999SWang.Lin@Sun.COM } else if (aniState->cckPhyErrCount >
658*9999SWang.Lin@Sun.COM aniState->listenTime * aniState->cckTrigHigh / 1000) {
659*9999SWang.Lin@Sun.COM ath9k_hw_ani_cck_err_trigger(ah);
660*9999SWang.Lin@Sun.COM ath9k_ani_restart(ah);
661*9999SWang.Lin@Sun.COM }
662*9999SWang.Lin@Sun.COM }
663*9999SWang.Lin@Sun.COM }
664*9999SWang.Lin@Sun.COM
665*9999SWang.Lin@Sun.COM boolean_t
ath9k_hw_phycounters(struct ath_hal * ah)666*9999SWang.Lin@Sun.COM ath9k_hw_phycounters(struct ath_hal *ah)
667*9999SWang.Lin@Sun.COM {
668*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
669*9999SWang.Lin@Sun.COM
670*9999SWang.Lin@Sun.COM return (ahp->ah_hasHwPhyCounters ? B_TRUE : B_FALSE);
671*9999SWang.Lin@Sun.COM }
672*9999SWang.Lin@Sun.COM
673*9999SWang.Lin@Sun.COM void
ath9k_enable_mib_counters(struct ath_hal * ah)674*9999SWang.Lin@Sun.COM ath9k_enable_mib_counters(struct ath_hal *ah)
675*9999SWang.Lin@Sun.COM {
676*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
677*9999SWang.Lin@Sun.COM
678*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: ath9k_enable_mib_counters(): "
679*9999SWang.Lin@Sun.COM "Enable MIB counters\n"));
680*9999SWang.Lin@Sun.COM
681*9999SWang.Lin@Sun.COM ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
682*9999SWang.Lin@Sun.COM
683*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_FILT_OFDM, 0);
684*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_FILT_CCK, 0);
685*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_MIBC,
686*9999SWang.Lin@Sun.COM ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f);
687*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
688*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
689*9999SWang.Lin@Sun.COM }
690*9999SWang.Lin@Sun.COM
691*9999SWang.Lin@Sun.COM void
ath9k_hw_disable_mib_counters(struct ath_hal * ah)692*9999SWang.Lin@Sun.COM ath9k_hw_disable_mib_counters(struct ath_hal *ah)
693*9999SWang.Lin@Sun.COM {
694*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
695*9999SWang.Lin@Sun.COM
696*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI,
697*9999SWang.Lin@Sun.COM "arn: ath9k_hw_disable_mib_counters(): "
698*9999SWang.Lin@Sun.COM "Disable MIB counters\n"));
699*9999SWang.Lin@Sun.COM
700*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
701*9999SWang.Lin@Sun.COM
702*9999SWang.Lin@Sun.COM ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
703*9999SWang.Lin@Sun.COM
704*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_FILT_OFDM, 0);
705*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_FILT_CCK, 0);
706*9999SWang.Lin@Sun.COM }
707*9999SWang.Lin@Sun.COM
708*9999SWang.Lin@Sun.COM uint32_t
ath9k_hw_GetMibCycleCountsPct(struct ath_hal * ah,uint32_t * rxc_pcnt,uint32_t * rxf_pcnt,uint32_t * txf_pcnt)709*9999SWang.Lin@Sun.COM ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah, uint32_t *rxc_pcnt,
710*9999SWang.Lin@Sun.COM uint32_t *rxf_pcnt, uint32_t *txf_pcnt)
711*9999SWang.Lin@Sun.COM {
712*9999SWang.Lin@Sun.COM static uint32_t cycles, rx_clear, rx_frame, tx_frame;
713*9999SWang.Lin@Sun.COM uint32_t good = 1;
714*9999SWang.Lin@Sun.COM
715*9999SWang.Lin@Sun.COM uint32_t rc = REG_READ(ah, AR_RCCNT);
716*9999SWang.Lin@Sun.COM uint32_t rf = REG_READ(ah, AR_RFCNT);
717*9999SWang.Lin@Sun.COM uint32_t tf = REG_READ(ah, AR_TFCNT);
718*9999SWang.Lin@Sun.COM uint32_t cc = REG_READ(ah, AR_CCCNT);
719*9999SWang.Lin@Sun.COM
720*9999SWang.Lin@Sun.COM if (cycles == 0 || cycles > cc) {
721*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_CHANNEL,
722*9999SWang.Lin@Sun.COM "arn: ath9k_hw_GetMibCycleCountsPct(): "
723*9999SWang.Lin@Sun.COM "cycle counter wrap. ExtBusy = 0\n"));
724*9999SWang.Lin@Sun.COM good = 0;
725*9999SWang.Lin@Sun.COM } else {
726*9999SWang.Lin@Sun.COM uint32_t cc_d = cc - cycles;
727*9999SWang.Lin@Sun.COM uint32_t rc_d = rc - rx_clear;
728*9999SWang.Lin@Sun.COM uint32_t rf_d = rf - rx_frame;
729*9999SWang.Lin@Sun.COM uint32_t tf_d = tf - tx_frame;
730*9999SWang.Lin@Sun.COM
731*9999SWang.Lin@Sun.COM if (cc_d != 0) {
732*9999SWang.Lin@Sun.COM *rxc_pcnt = rc_d * 100 / cc_d;
733*9999SWang.Lin@Sun.COM *rxf_pcnt = rf_d * 100 / cc_d;
734*9999SWang.Lin@Sun.COM *txf_pcnt = tf_d * 100 / cc_d;
735*9999SWang.Lin@Sun.COM } else {
736*9999SWang.Lin@Sun.COM good = 0;
737*9999SWang.Lin@Sun.COM }
738*9999SWang.Lin@Sun.COM }
739*9999SWang.Lin@Sun.COM
740*9999SWang.Lin@Sun.COM cycles = cc;
741*9999SWang.Lin@Sun.COM rx_frame = rf;
742*9999SWang.Lin@Sun.COM rx_clear = rc;
743*9999SWang.Lin@Sun.COM tx_frame = tf;
744*9999SWang.Lin@Sun.COM
745*9999SWang.Lin@Sun.COM return (good);
746*9999SWang.Lin@Sun.COM }
747*9999SWang.Lin@Sun.COM
748*9999SWang.Lin@Sun.COM /*
749*9999SWang.Lin@Sun.COM * Process a MIB interrupt. We may potentially be invoked because
750*9999SWang.Lin@Sun.COM * any of the MIB counters overflow/trigger so don't assume we're
751*9999SWang.Lin@Sun.COM * here because a PHY error counter triggered.
752*9999SWang.Lin@Sun.COM */
753*9999SWang.Lin@Sun.COM void
ath9k_hw_procmibevent(struct ath_hal * ah,const struct ath9k_node_stats * stats)754*9999SWang.Lin@Sun.COM ath9k_hw_procmibevent(struct ath_hal *ah,
755*9999SWang.Lin@Sun.COM const struct ath9k_node_stats *stats)
756*9999SWang.Lin@Sun.COM {
757*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
758*9999SWang.Lin@Sun.COM uint32_t phyCnt1, phyCnt2;
759*9999SWang.Lin@Sun.COM
760*9999SWang.Lin@Sun.COM /* Reset these counters regardless */
761*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_FILT_OFDM, 0);
762*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_FILT_CCK, 0);
763*9999SWang.Lin@Sun.COM if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
764*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
765*9999SWang.Lin@Sun.COM
766*9999SWang.Lin@Sun.COM /* Clear the mib counters and save them in the stats */
767*9999SWang.Lin@Sun.COM ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
768*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_nodestats = *stats;
769*9999SWang.Lin@Sun.COM
770*9999SWang.Lin@Sun.COM if (!DO_ANI(ah))
771*9999SWang.Lin@Sun.COM return;
772*9999SWang.Lin@Sun.COM
773*9999SWang.Lin@Sun.COM /* NB: these are not reset-on-read */
774*9999SWang.Lin@Sun.COM phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
775*9999SWang.Lin@Sun.COM phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
776*9999SWang.Lin@Sun.COM if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
777*9999SWang.Lin@Sun.COM ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
778*9999SWang.Lin@Sun.COM struct ar5416AniState *aniState = ahp->ah_curani;
779*9999SWang.Lin@Sun.COM uint32_t ofdmPhyErrCnt, cckPhyErrCnt;
780*9999SWang.Lin@Sun.COM
781*9999SWang.Lin@Sun.COM /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
782*9999SWang.Lin@Sun.COM ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
783*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_ofdmerrs +=
784*9999SWang.Lin@Sun.COM ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
785*9999SWang.Lin@Sun.COM aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
786*9999SWang.Lin@Sun.COM
787*9999SWang.Lin@Sun.COM cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
788*9999SWang.Lin@Sun.COM ahp->ah_stats.ast_ani_cckerrs +=
789*9999SWang.Lin@Sun.COM cckPhyErrCnt - aniState->cckPhyErrCount;
790*9999SWang.Lin@Sun.COM aniState->cckPhyErrCount = cckPhyErrCnt;
791*9999SWang.Lin@Sun.COM
792*9999SWang.Lin@Sun.COM /*
793*9999SWang.Lin@Sun.COM * NB: figure out which counter triggered. If both
794*9999SWang.Lin@Sun.COM * trigger we'll only deal with one as the processing
795*9999SWang.Lin@Sun.COM * clobbers the error counter so the trigger threshold
796*9999SWang.Lin@Sun.COM * check will never be true.
797*9999SWang.Lin@Sun.COM */
798*9999SWang.Lin@Sun.COM if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
799*9999SWang.Lin@Sun.COM ath9k_hw_ani_ofdm_err_trigger(ah);
800*9999SWang.Lin@Sun.COM if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
801*9999SWang.Lin@Sun.COM ath9k_hw_ani_cck_err_trigger(ah);
802*9999SWang.Lin@Sun.COM /* NB: always restart to insure the h/w counters are reset */
803*9999SWang.Lin@Sun.COM ath9k_ani_restart(ah);
804*9999SWang.Lin@Sun.COM }
805*9999SWang.Lin@Sun.COM }
806*9999SWang.Lin@Sun.COM
807*9999SWang.Lin@Sun.COM void
ath9k_hw_ani_setup(struct ath_hal * ah)808*9999SWang.Lin@Sun.COM ath9k_hw_ani_setup(struct ath_hal *ah)
809*9999SWang.Lin@Sun.COM {
810*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
811*9999SWang.Lin@Sun.COM int i;
812*9999SWang.Lin@Sun.COM
813*9999SWang.Lin@Sun.COM const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
814*9999SWang.Lin@Sun.COM const int coarseHigh[] = { -14, -14, -14, -14, -12 };
815*9999SWang.Lin@Sun.COM const int coarseLow[] = { -64, -64, -64, -64, -70 };
816*9999SWang.Lin@Sun.COM const int firpwr[] = { -78, -78, -78, -78, -80 };
817*9999SWang.Lin@Sun.COM
818*9999SWang.Lin@Sun.COM for (i = 0; i < 5; i++) {
819*9999SWang.Lin@Sun.COM ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
820*9999SWang.Lin@Sun.COM ahp->ah_coarseHigh[i] = coarseHigh[i];
821*9999SWang.Lin@Sun.COM ahp->ah_coarseLow[i] = coarseLow[i];
822*9999SWang.Lin@Sun.COM ahp->ah_firpwr[i] = firpwr[i];
823*9999SWang.Lin@Sun.COM }
824*9999SWang.Lin@Sun.COM }
825*9999SWang.Lin@Sun.COM
826*9999SWang.Lin@Sun.COM void
ath9k_hw_ani_attach(struct ath_hal * ah)827*9999SWang.Lin@Sun.COM ath9k_hw_ani_attach(struct ath_hal *ah)
828*9999SWang.Lin@Sun.COM {
829*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
830*9999SWang.Lin@Sun.COM int i;
831*9999SWang.Lin@Sun.COM
832*9999SWang.Lin@Sun.COM /* For Lint Reasons */
833*9999SWang.Lin@Sun.COM boolean_t ANI_USE_OFDM_WEAK_SIG = ATH9K_ANI_USE_OFDM_WEAK_SIG;
834*9999SWang.Lin@Sun.COM
835*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_ani_attach(): "
836*9999SWang.Lin@Sun.COM "Attach ANI\n"));
837*9999SWang.Lin@Sun.COM
838*9999SWang.Lin@Sun.COM ahp->ah_hasHwPhyCounters = 1;
839*9999SWang.Lin@Sun.COM
840*9999SWang.Lin@Sun.COM (void) memset(ahp->ah_ani, 0, sizeof (ahp->ah_ani));
841*9999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
842*9999SWang.Lin@Sun.COM ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
843*9999SWang.Lin@Sun.COM ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
844*9999SWang.Lin@Sun.COM ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
845*9999SWang.Lin@Sun.COM ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
846*9999SWang.Lin@Sun.COM ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
847*9999SWang.Lin@Sun.COM ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
848*9999SWang.Lin@Sun.COM ahp->ah_ani[i].ofdmWeakSigDetectOff =
849*9999SWang.Lin@Sun.COM !ANI_USE_OFDM_WEAK_SIG /* !ATH9K_ANI_USE_OFDM_WEAK_SIG */;
850*9999SWang.Lin@Sun.COM ahp->ah_ani[i].cckWeakSigThreshold =
851*9999SWang.Lin@Sun.COM ATH9K_ANI_CCK_WEAK_SIG_THR;
852*9999SWang.Lin@Sun.COM ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
853*9999SWang.Lin@Sun.COM ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
854*9999SWang.Lin@Sun.COM if (ahp->ah_hasHwPhyCounters) {
855*9999SWang.Lin@Sun.COM ahp->ah_ani[i].ofdmPhyErrBase =
856*9999SWang.Lin@Sun.COM AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
857*9999SWang.Lin@Sun.COM ahp->ah_ani[i].cckPhyErrBase =
858*9999SWang.Lin@Sun.COM AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
859*9999SWang.Lin@Sun.COM }
860*9999SWang.Lin@Sun.COM }
861*9999SWang.Lin@Sun.COM if (ahp->ah_hasHwPhyCounters) {
862*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_ani_attach(): "
863*9999SWang.Lin@Sun.COM "Setting OfdmErrBase = 0x%08x\n",
864*9999SWang.Lin@Sun.COM ahp->ah_ani[0].ofdmPhyErrBase));
865*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_ani_attach(): "
866*9999SWang.Lin@Sun.COM "Setting cckErrBase = 0x%08x\n",
867*9999SWang.Lin@Sun.COM ahp->ah_ani[0].cckPhyErrBase));
868*9999SWang.Lin@Sun.COM
869*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
870*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
871*9999SWang.Lin@Sun.COM ath9k_enable_mib_counters(ah);
872*9999SWang.Lin@Sun.COM }
873*9999SWang.Lin@Sun.COM ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
874*9999SWang.Lin@Sun.COM if (ah->ah_config.enable_ani)
875*9999SWang.Lin@Sun.COM ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
876*9999SWang.Lin@Sun.COM }
877*9999SWang.Lin@Sun.COM
878*9999SWang.Lin@Sun.COM void
ath9k_hw_ani_detach(struct ath_hal * ah)879*9999SWang.Lin@Sun.COM ath9k_hw_ani_detach(struct ath_hal *ah)
880*9999SWang.Lin@Sun.COM {
881*9999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
882*9999SWang.Lin@Sun.COM
883*9999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: ath9k_hw_ani_detach(): "
884*9999SWang.Lin@Sun.COM "Detach ANI\n"));
885*9999SWang.Lin@Sun.COM
886*9999SWang.Lin@Sun.COM if (ahp->ah_hasHwPhyCounters) {
887*9999SWang.Lin@Sun.COM ath9k_hw_disable_mib_counters(ah);
888*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_1, 0);
889*9999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_ERR_2, 0);
890*9999SWang.Lin@Sun.COM }
891*9999SWang.Lin@Sun.COM }
892