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 757