1 /*-
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5 * Copyright (c) 2002-2008 Atheros Communications, Inc.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * $FreeBSD$
20 */
21 #include "opt_ah.h"
22
23 #include "ah.h"
24 #include "ah_internal.h"
25 #include "ah_devid.h"
26 #include "ah_desc.h" /* NB: for HAL_PHYERR* */
27
28 #include "ar5416/ar5416.h"
29 #include "ar5416/ar5416reg.h"
30 #include "ar5416/ar5416phy.h"
31
32 #include "ah_eeprom_v14.h" /* for owl_get_ntxchains() */
33
34 /*
35 * Return the wireless modes (a,b,g,n,t) supported by hardware.
36 *
37 * This value is what is actually supported by the hardware
38 * and is unaffected by regulatory/country code settings.
39 *
40 */
41 u_int
42 ar5416GetWirelessModes(struct ath_hal *ah)
43 {
44 u_int mode;
45 struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
46 HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
47
48 mode = ar5212GetWirelessModes(ah);
49
50 /* Only enable HT modes if the NIC supports HT */
51 if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11A))
52 mode |= HAL_MODE_11NA_HT20
53 | HAL_MODE_11NA_HT40PLUS
54 | HAL_MODE_11NA_HT40MINUS
55 ;
56 if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11G))
57 mode |= HAL_MODE_11NG_HT20
58 | HAL_MODE_11NG_HT40PLUS
59 | HAL_MODE_11NG_HT40MINUS
60 ;
61 return mode;
62 }
63
64 /*
65 * Change the LED blinking pattern to correspond to the connectivity
66 */
67 void
68 ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
69 {
70 static const uint32_t ledbits[8] = {
71 AR_MAC_LED_ASSOC_NONE, /* HAL_LED_INIT */
72 AR_MAC_LED_ASSOC_PEND, /* HAL_LED_SCAN */
73 AR_MAC_LED_ASSOC_PEND, /* HAL_LED_AUTH */
74 AR_MAC_LED_ASSOC_ACTIVE, /* HAL_LED_ASSOC*/
75 AR_MAC_LED_ASSOC_ACTIVE, /* HAL_LED_RUN */
76 AR_MAC_LED_ASSOC_NONE,
77 AR_MAC_LED_ASSOC_NONE,
78 AR_MAC_LED_ASSOC_NONE,
79 };
80
81 if (AR_SREV_HOWL(ah))
82 return;
83
84 /*
85 * Set the blink operating mode.
86 */
87 OS_REG_RMW_FIELD(ah, AR_MAC_LED,
88 AR_MAC_LED_ASSOC, ledbits[state & 0x7]);
89
90 /* XXX Blink slow mode? */
91 /* XXX Blink threshold? */
92 /* XXX Blink sleep hystersis? */
93
94 /*
95 * Set the LED blink configuration to be proportional
96 * to the current TX and RX filter bytes. (Ie, RX'ed
97 * frames that don't match the filter are ignored.)
98 * This means that higher TX/RX throughput will result
99 * in the blink rate increasing.
100 */
101 OS_REG_RMW_FIELD(ah, AR_MAC_LED, AR_MAC_LED_MODE,
102 AR_MAC_LED_MODE_PROP);
103 }
104
105 /*
106 * Get the current hardware tsf for stamlme
107 */
108 uint64_t
109 ar5416GetTsf64(struct ath_hal *ah)
110 {
111 uint32_t low1, low2, u32;
112
113 /* sync multi-word read */
114 low1 = OS_REG_READ(ah, AR_TSF_L32);
115 u32 = OS_REG_READ(ah, AR_TSF_U32);
116 low2 = OS_REG_READ(ah, AR_TSF_L32);
117 if (low2 < low1) { /* roll over */
118 /*
119 * If we are not preempted this will work. If we are
120 * then we re-reading AR_TSF_U32 does no good as the
121 * low bits will be meaningless. Likewise reading
122 * L32, U32, U32, then comparing the last two reads
123 * to check for rollover doesn't help if preempted--so
124 * we take this approach as it costs one less PCI read
125 * which can be noticeable when doing things like
126 * timestamping packets in monitor mode.
127 */
128 u32++;
129 }
130 return (((uint64_t) u32) << 32) | ((uint64_t) low2);
131 }
132
133 /*
134 * Update the TSF.
135 *
136 * The full TSF is only updated once the upper 32 bits have
137 * been written. Writing only the lower 32 bits of the TSF
138 * will not actually correctly update the TSF.
139 *
140 * The #if 0'ed code is to check whether the previous TSF
141 * reset or write has completed before writing to the
142 * TSF. Strictly speaking, it should be also checked before
143 * reading the TSF as the write/reset may not have completed.
144 */
145 void
146 ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64)
147 {
148 /* XXX check if this is correct! */
149 #if 0
150 int i;
151 uint32_t v;
152
153 for (i = 0; i < 10; i++) {
154 v = OS_REG_READ(ah, AR_SLP32_MODE);
155 if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
156 break;
157 OS_DELAY(10);
158 }
159 if (i == 10)
160 ath_hal_printf(ah, "%s: couldn't slew things right!\n", __func__);
161 #endif
162
163 OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
164 OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
165 }
166
167 /*
168 * Reset the current hardware tsf for stamlme.
169 */
170 void
171 ar5416ResetTsf(struct ath_hal *ah)
172 {
173 uint32_t v;
174 int i;
175
176 for (i = 0; i < 10; i++) {
177 v = OS_REG_READ(ah, AR_SLP32_MODE);
178 if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
179 break;
180 OS_DELAY(10);
181 }
182 OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
183 }
184
185 uint32_t
186 ar5416GetCurRssi(struct ath_hal *ah)
187 {
188 if (AR_SREV_OWL(ah))
189 return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
190 return (OS_REG_READ(ah, AR9130_PHY_CURRENT_RSSI) & 0xff);
191 }
192
193 HAL_BOOL
194 ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
195 {
196 return AH_TRUE;
197 }
198
199 /* Setup decompression for given key index */
200 HAL_BOOL
201 ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
202 {
203 return AH_TRUE;
204 }
205
206 /* Setup coverage class */
207 void
208 ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
209 {
210
211 ar5212SetCoverageClass(ah, coverageclass, now);
212 }
213
214 /*
215 * Return the busy for rx_frame, rx_clear, and tx_frame
216 */
217 HAL_BOOL
218 ar5416GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample)
219 {
220 struct ath_hal_5416 *ahp = AH5416(ah);
221 u_int32_t good = AH_TRUE;
222
223 /* XXX freeze/unfreeze mib counters */
224 uint32_t rc = OS_REG_READ(ah, AR_RCCNT);
225 uint32_t ec = OS_REG_READ(ah, AR_EXTRCCNT);
226 uint32_t rf = OS_REG_READ(ah, AR_RFCNT);
227 uint32_t tf = OS_REG_READ(ah, AR_TFCNT);
228 uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */
229
230 if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) {
231 /*
232 * Cycle counter wrap (or initial call); it's not possible
233 * to accurately calculate a value because the registers
234 * right shift rather than wrap--so punt and return 0.
235 */
236 HALDEBUG(ah, HAL_DEBUG_ANY,
237 "%s: cycle counter wrap. ExtBusy = 0\n", __func__);
238 good = AH_FALSE;
239 } else {
240 hsample->cycle_count = cc - ahp->ah_cycleCount;
241 hsample->chan_busy = rc - ahp->ah_ctlBusy;
242 hsample->ext_chan_busy = ec - ahp->ah_extBusy;
243 hsample->rx_busy = rf - ahp->ah_rxBusy;
244 hsample->tx_busy = tf - ahp->ah_txBusy;
245 }
246
247 /*
248 * Keep a copy of the MIB results so the next sample has something
249 * to work from.
250 */
251 ahp->ah_cycleCount = cc;
252 ahp->ah_rxBusy = rf;
253 ahp->ah_ctlBusy = rc;
254 ahp->ah_txBusy = tf;
255 ahp->ah_extBusy = ec;
256
257 return (good);
258 }
259
260 /*
261 * Setup the TX/RX chainmasks - this needs to be done before a call
262 * to the reset method as it doesn't update the hardware.
263 */
264 void
265 ar5416SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask,
266 uint32_t rx_chainmask)
267 {
268 HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
269
270 AH5416(ah)->ah_tx_chainmask = tx_chainmask & pCap->halTxChainMask;
271 AH5416(ah)->ah_rx_chainmask = rx_chainmask & pCap->halRxChainMask;
272 }
273
274 /*
275 * Return approximation of extension channel busy over an time interval
276 * 0% (clear) -> 100% (busy)
277 *
278 * XXX TODO: update this to correctly sample all the counters,
279 * rather than a subset of it.
280 */
281 uint32_t
282 ar5416Get11nExtBusy(struct ath_hal *ah)
283 {
284 struct ath_hal_5416 *ahp = AH5416(ah);
285 uint32_t busy; /* percentage */
286 uint32_t cycleCount, ctlBusy, extBusy;
287
288 ctlBusy = OS_REG_READ(ah, AR_RCCNT);
289 extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
290 cycleCount = OS_REG_READ(ah, AR_CCCNT);
291
292 if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
293 /*
294 * Cycle counter wrap (or initial call); it's not possible
295 * to accurately calculate a value because the registers
296 * right shift rather than wrap--so punt and return 0.
297 */
298 busy = 0;
299 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
300 __func__);
301
302 } else {
303 uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
304 uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
305 uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
306 uint32_t ctlClearDelta = 0;
307
308 /* Compute control channel rxclear.
309 * The cycle delta may be less than the control channel delta.
310 * This could be solved by freezing the timers (or an atomic read,
311 * if one was available). Checking for the condition should be
312 * sufficient.
313 */
314 if (cycleDelta > ctlBusyDelta) {
315 ctlClearDelta = cycleDelta - ctlBusyDelta;
316 }
317
318 /* Compute ratio of extension channel busy to control channel clear
319 * as an approximation to extension channel cleanliness.
320 *
321 * According to the hardware folks, ext rxclear is undefined
322 * if the ctrl rxclear is de-asserted (i.e. busy)
323 */
324 if (ctlClearDelta) {
325 busy = (extBusyDelta * 100) / ctlClearDelta;
326 } else {
327 busy = 100;
328 }
329 if (busy > 100) {
330 busy = 100;
331 }
332 #if 0
333 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
334 "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
335 "busy %d\n",
336 __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
337 #endif
338 }
339
340 ahp->ah_cycleCount = cycleCount;
341 ahp->ah_ctlBusy = ctlBusy;
342 ahp->ah_extBusy = extBusy;
343
344 return busy;
345 }
346
347 /*
348 * Configure 20/40 operation
349 *
350 * 20/40 = joint rx clear (control and extension)
351 * 20 = rx clear (control)
352 *
353 * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
354 * from 20/40 => 20 only
355 */
356 void
357 ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
358 {
359 uint32_t macmode;
360
361 /* Configure MAC for 20/40 operation */
362 if (mode == HAL_HT_MACMODE_2040) {
363 macmode = AR_2040_JOINED_RX_CLEAR;
364 } else {
365 macmode = 0;
366 }
367 OS_REG_WRITE(ah, AR_2040_MODE, macmode);
368 }
369
370 /*
371 * Get Rx clear (control/extension channel)
372 *
373 * Returns active low (busy) for ctrl/ext channel
374 * Owl 2.0
375 */
376 HAL_HT_RXCLEAR
377 ar5416Get11nRxClear(struct ath_hal *ah)
378 {
379 HAL_HT_RXCLEAR rxclear = 0;
380 uint32_t val;
381
382 val = OS_REG_READ(ah, AR_DIAG_SW);
383
384 /* control channel */
385 if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
386 rxclear |= HAL_RX_CLEAR_CTL_LOW;
387 }
388 /* extension channel */
389 if (val & AR_DIAG_RXCLEAR_EXT_LOW) {
390 rxclear |= HAL_RX_CLEAR_EXT_LOW;
391 }
392 return rxclear;
393 }
394
395 /*
396 * Set Rx clear (control/extension channel)
397 *
398 * Useful for forcing the channel to appear busy for
399 * debugging/diagnostics
400 * Owl 2.0
401 */
402 void
403 ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
404 {
405 /* control channel */
406 if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
407 OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
408 } else {
409 OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
410 }
411 /* extension channel */
412 if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
413 OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
414 } else {
415 OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
416 }
417 }
418
419 /* XXX shouldn't be here! */
420 #define TU_TO_USEC(_tu) ((_tu) << 10)
421
422 HAL_STATUS
423 ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
424 uint32_t nextStart, HAL_QUIET_FLAG flag)
425 {
426 uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */
427 uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */
428 if (flag & HAL_QUIET_ENABLE) {
429 if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) {
430 /* Add the nextStart offset to the current TSF */
431 nextStart_us += OS_REG_READ(ah, AR_TSF_L32);
432 }
433 if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) {
434 nextStart_us += ah->ah_config.ah_sw_beacon_response_time;
435 }
436 OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
437 OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR));
438 OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us);
439 OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us);
440 OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
441 } else {
442 OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
443 }
444 return HAL_OK;
445 }
446 #undef TU_TO_USEC
447
448 HAL_STATUS
449 ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
450 uint32_t capability, uint32_t *result)
451 {
452 switch (type) {
453 case HAL_CAP_BB_HANG:
454 switch (capability) {
455 case HAL_BB_HANG_RIFS:
456 return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
457 case HAL_BB_HANG_DFS:
458 return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
459 case HAL_BB_HANG_RX_CLEAR:
460 return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
461 }
462 break;
463 case HAL_CAP_MAC_HANG:
464 return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
465 (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
466 AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ?
467 HAL_OK : HAL_ENOTSUPP;
468 case HAL_CAP_DIVERSITY: /* disable classic fast diversity */
469 return HAL_ENXIO;
470 case HAL_CAP_ENFORCE_TXOP:
471 if (capability == 0)
472 return (HAL_OK);
473 if (capability != 1)
474 return (HAL_ENOTSUPP);
475 (*result) =
476 !! (AH5212(ah)->ah_miscMode & AR_PCU_TXOP_TBTT_LIMIT_ENA);
477 return (HAL_OK);
478 default:
479 break;
480 }
481 return ar5212GetCapability(ah, type, capability, result);
482 }
483
484 HAL_BOOL
485 ar5416SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
486 u_int32_t capability, u_int32_t setting, HAL_STATUS *status)
487 {
488 HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
489
490 switch (type) {
491 case HAL_CAP_RX_CHAINMASK:
492 setting &= ath_hal_eepromGet(ah, AR_EEP_RXMASK, NULL);
493 pCap->halRxChainMask = setting;
494 if (owl_get_ntxchains(setting) > 2)
495 pCap->halRxStreams = 2;
496 else
497 pCap->halRxStreams = 1;
498 return AH_TRUE;
499 case HAL_CAP_TX_CHAINMASK:
500 setting &= ath_hal_eepromGet(ah, AR_EEP_TXMASK, NULL);
501 pCap->halTxChainMask = setting;
502 if (owl_get_ntxchains(setting) > 2)
503 pCap->halTxStreams = 2;
504 else
505 pCap->halTxStreams = 1;
506 return AH_TRUE;
507 case HAL_CAP_ENFORCE_TXOP:
508 if (capability != 1)
509 return AH_FALSE;
510 if (setting) {
511 AH5212(ah)->ah_miscMode
512 |= AR_PCU_TXOP_TBTT_LIMIT_ENA;
513 OS_REG_SET_BIT(ah, AR_MISC_MODE,
514 AR_PCU_TXOP_TBTT_LIMIT_ENA);
515 } else {
516 AH5212(ah)->ah_miscMode
517 &= ~AR_PCU_TXOP_TBTT_LIMIT_ENA;
518 OS_REG_CLR_BIT(ah, AR_MISC_MODE,
519 AR_PCU_TXOP_TBTT_LIMIT_ENA);
520 }
521 return AH_TRUE;
522 default:
523 break;
524 }
525 return ar5212SetCapability(ah, type, capability, setting, status);
526 }
527
528 static int ar5416DetectMacHang(struct ath_hal *ah);
529 static int ar5416DetectBBHang(struct ath_hal *ah);
530
531 HAL_BOOL
532 ar5416GetDiagState(struct ath_hal *ah, int request,
533 const void *args, uint32_t argsize,
534 void **result, uint32_t *resultsize)
535 {
536 struct ath_hal_5416 *ahp = AH5416(ah);
537 int hangs;
538
539 if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
540 return AH_TRUE;
541 switch (request) {
542 case HAL_DIAG_EEPROM:
543 return ath_hal_eepromDiag(ah, request,
544 args, argsize, result, resultsize);
545 case HAL_DIAG_CHECK_HANGS:
546 if (argsize != sizeof(int))
547 return AH_FALSE;
548 hangs = *(const int *) args;
549 ahp->ah_hangs = 0;
550 if (hangs & HAL_BB_HANGS)
551 ahp->ah_hangs |= ar5416DetectBBHang(ah);
552 /* NB: if BB is hung MAC will be hung too so skip check */
553 if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
554 ahp->ah_hangs |= ar5416DetectMacHang(ah);
555 *result = &ahp->ah_hangs;
556 *resultsize = sizeof(ahp->ah_hangs);
557 return AH_TRUE;
558 }
559 return ar5212GetDiagState(ah, request,
560 args, argsize, result, resultsize);
561 }
562
563 HAL_BOOL
564 ar5416SetRifsDelay(struct ath_hal *ah, const struct ieee80211_channel *chan,
565 HAL_BOOL enable)
566 {
567 uint32_t val;
568 HAL_BOOL is_chan_2g = AH_FALSE;
569 HAL_BOOL is_ht40 = AH_FALSE;
570
571 if (chan)
572 is_chan_2g = IEEE80211_IS_CHAN_2GHZ(chan);
573
574 if (chan)
575 is_ht40 = IEEE80211_IS_CHAN_HT40(chan);
576
577 /* Only support disabling RIFS delay for now */
578 HALASSERT(enable == AH_FALSE);
579
580 if (enable == AH_TRUE)
581 return AH_FALSE;
582
583 /* Change RIFS init delay to 0 */
584 val = OS_REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
585 val &= ~AR_PHY_RIFS_INIT_DELAY;
586 OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
587
588 /*
589 * For Owl, RIFS RX parameters are controlled differently;
590 * it isn't enabled in the inivals by default.
591 *
592 * For Sowl/Howl, RIFS RX is enabled in the inivals by default;
593 * the following code sets them back to non-RIFS values.
594 *
595 * For > Sowl/Howl, RIFS RX can be left on by default and so
596 * this function shouldn't be called.
597 */
598 if ((! AR_SREV_SOWL(ah)) && (! AR_SREV_HOWL(ah)))
599 return AH_TRUE;
600
601 /* Reset search delay to default values */
602 if (is_chan_2g)
603 if (is_ht40)
604 OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x268);
605 else
606 OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x134);
607 else
608 if (is_ht40)
609 OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x370);
610 else
611 OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x1b8);
612
613 return AH_TRUE;
614 }
615
616 static HAL_BOOL
617 ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
618 const hal_mac_hang_check_t *check)
619 {
620 int found_states;
621
622 found_states = 0;
623 if (check->states & dcu_chain_state) {
624 int i;
625
626 for (i = 0; i < 6; i++) {
627 if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
628 check->dcu_chain_state)
629 found_states |= dcu_chain_state;
630 }
631 for (i = 0; i < 4; i++) {
632 if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
633 check->dcu_chain_state)
634 found_states |= dcu_chain_state;
635 }
636 }
637 if (check->states & dcu_complete_state) {
638 if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
639 found_states |= dcu_complete_state;
640 }
641 if (check->states & qcu_stitch_state) {
642 if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
643 found_states |= qcu_stitch_state;
644 }
645 if (check->states & qcu_fetch_state) {
646 if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
647 found_states |= qcu_fetch_state;
648 }
649 if (check->states & qcu_complete_state) {
650 if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
651 found_states |= qcu_complete_state;
652 }
653 return (found_states == check->states);
654 }
655
656 #define NUM_STATUS_READS 50
657
658 static int
659 ar5416DetectMacHang(struct ath_hal *ah)
660 {
661 static const hal_mac_hang_check_t hang_sig1 = {
662 .dcu_chain_state = 0x6,
663 .dcu_complete_state = 0x1,
664 .states = dcu_chain_state
665 | dcu_complete_state,
666 };
667 static const hal_mac_hang_check_t hang_sig2 = {
668 .qcu_stitch_state = 0x9,
669 .qcu_fetch_state = 0x8,
670 .qcu_complete_state = 0x4,
671 .states = qcu_stitch_state
672 | qcu_fetch_state
673 | qcu_complete_state,
674 };
675 mac_dbg_regs_t mac_dbg;
676 int i;
677
678 mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
679 mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
680 mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
681 mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
682 for (i = 1; i <= NUM_STATUS_READS; i++) {
683 if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
684 mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
685 mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
686 mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
687 return 0;
688 }
689
690 if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
691 return HAL_MAC_HANG_SIG1;
692 if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
693 return HAL_MAC_HANG_SIG2;
694
695 HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown MAC hang signature "
696 "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
697 __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
698 mac_dbg.dma_dbg_6);
699
700 return 0;
701 }
702
703 /*
704 * Determine if the baseband using the Observation Bus Register
705 */
706 static int
707 ar5416DetectBBHang(struct ath_hal *ah)
708 {
709 #define N(a) (sizeof(a)/sizeof(a[0]))
710 /*
711 * Check the PCU Observation Bus 1 register (0x806c)
712 * NUM_STATUS_READS times
713 *
714 * 4 known BB hang signatures -
715 * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
716 * [2] bits 8,9 are 1, bit 11 is 0. State machine state
717 * (bits 25-31) is 0x52
718 * [3] bits 8,9 are 1, bit 11 is 0. State machine state
719 * (bits 25-31) is 0x18
720 * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
721 * Rx State (bits 20-24) is 0x7.
722 */
723 static const struct {
724 uint32_t val;
725 uint32_t mask;
726 int code;
727 } hang_list[] = {
728 /* Reg Value Reg Mask Hang Code XXX */
729 { 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
730 { 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
731 { 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
732 { 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
733 };
734 uint32_t hang_sig;
735 int i;
736
737 hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
738 for (i = 1; i <= NUM_STATUS_READS; i++) {
739 if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
740 return 0;
741 }
742 for (i = 0; i < N(hang_list); i++)
743 if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
744 HALDEBUG(ah, HAL_DEBUG_HANG,
745 "%s BB hang, signature 0x%x, code 0x%x\n",
746 __func__, hang_sig, hang_list[i].code);
747 return hang_list[i].code;
748 }
749
750 HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! "
751 "<0x806c>=0x%x\n", __func__, hang_sig);
752
753 return 0;
754 #undef N
755 }
756 #undef NUM_STATUS_READS
Cache object: a28bafeb75e897caa60b108ad0c5633b
|