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