1250003Sadrian/* 2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc. 3250003Sadrian * 4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any 5250003Sadrian * purpose with or without fee is hereby granted, provided that the above 6250003Sadrian * copyright notice and this permission notice appear in all copies. 7250003Sadrian * 8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14250003Sadrian * PERFORMANCE OF THIS SOFTWARE. 15250003Sadrian */ 16250003Sadrian 17250003Sadrian#include "opt_ah.h" 18250003Sadrian 19250003Sadrian#include "ah.h" 20250003Sadrian#include "ah_desc.h" 21250003Sadrian#include "ah_internal.h" 22250003Sadrian 23250003Sadrian#include "ar9300/ar9300.h" 24250003Sadrian#include "ar9300/ar9300reg.h" 25250003Sadrian#include "ar9300/ar9300phy.h" 26250003Sadrian#include "ar9300/ar9300desc.h" 27250003Sadrian 28250008Sadrian#define TU_TO_USEC(_tu) ((_tu) << 10) 29250008Sadrian#define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7) 30250008Sadrian 31250003Sadrian/* 32250003Sadrian * Update Tx FIFO trigger level. 33250003Sadrian * 34250003Sadrian * Set b_inc_trig_level to TRUE to increase the trigger level. 35250003Sadrian * Set b_inc_trig_level to FALSE to decrease the trigger level. 36250003Sadrian * 37250003Sadrian * Returns TRUE if the trigger level was updated 38250003Sadrian */ 39250003SadrianHAL_BOOL 40250003Sadrianar9300_update_tx_trig_level(struct ath_hal *ah, HAL_BOOL b_inc_trig_level) 41250003Sadrian{ 42250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 43250003Sadrian u_int32_t txcfg, cur_level, new_level; 44250003Sadrian HAL_INT omask; 45250003Sadrian 46250008Sadrian if (AH9300(ah)->ah_tx_trig_level >= MAX_TX_FIFO_THRESHOLD && 47250003Sadrian b_inc_trig_level) 48250003Sadrian { 49250003Sadrian return AH_FALSE; 50250003Sadrian } 51250003Sadrian 52250003Sadrian /* 53250003Sadrian * Disable interrupts while futzing with the fifo level. 54250003Sadrian */ 55250003Sadrian omask = ar9300_set_interrupts(ah, ahp->ah_mask_reg &~ HAL_INT_GLOBAL, 0); 56250003Sadrian 57250003Sadrian txcfg = OS_REG_READ(ah, AR_TXCFG); 58250003Sadrian cur_level = MS(txcfg, AR_FTRIG); 59250003Sadrian new_level = cur_level; 60250003Sadrian 61250003Sadrian if (b_inc_trig_level) { /* increase the trigger level */ 62250003Sadrian if (cur_level < MAX_TX_FIFO_THRESHOLD) { 63250003Sadrian new_level++; 64250003Sadrian } 65250003Sadrian } else if (cur_level > MIN_TX_FIFO_THRESHOLD) { 66250003Sadrian new_level--; 67250003Sadrian } 68250003Sadrian 69250003Sadrian if (new_level != cur_level) { 70250003Sadrian /* Update the trigger level */ 71250003Sadrian OS_REG_WRITE(ah, 72250003Sadrian AR_TXCFG, (txcfg &~ AR_FTRIG) | SM(new_level, AR_FTRIG)); 73250003Sadrian } 74250003Sadrian 75250003Sadrian /* re-enable chip interrupts */ 76250003Sadrian ar9300_set_interrupts(ah, omask, 0); 77250003Sadrian 78250008Sadrian AH9300(ah)->ah_tx_trig_level = new_level; 79250003Sadrian 80250003Sadrian return (new_level != cur_level); 81250003Sadrian} 82250003Sadrian 83250003Sadrian/* 84250003Sadrian * Returns the value of Tx Trigger Level 85250003Sadrian */ 86250003Sadrianu_int16_t 87250003Sadrianar9300_get_tx_trig_level(struct ath_hal *ah) 88250003Sadrian{ 89250008Sadrian return (AH9300(ah)->ah_tx_trig_level); 90250003Sadrian} 91250003Sadrian 92250003Sadrian/* 93250003Sadrian * Set the properties of the tx queue with the parameters 94250003Sadrian * from q_info. 95250003Sadrian */ 96250003SadrianHAL_BOOL 97250003Sadrianar9300_set_tx_queue_props(struct ath_hal *ah, int q, const HAL_TXQ_INFO *q_info) 98250003Sadrian{ 99250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 100250003Sadrian HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; 101250003Sadrian 102250008Sadrian if (q >= p_cap->halTotalQueues) { 103250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q); 104250003Sadrian return AH_FALSE; 105250003Sadrian } 106250008Sadrian return ath_hal_setTxQProps(ah, &ahp->ah_txq[q], q_info); 107250003Sadrian} 108250003Sadrian 109250003Sadrian/* 110250003Sadrian * Return the properties for the specified tx queue. 111250003Sadrian */ 112250003SadrianHAL_BOOL 113250003Sadrianar9300_get_tx_queue_props(struct ath_hal *ah, int q, HAL_TXQ_INFO *q_info) 114250003Sadrian{ 115250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 116250003Sadrian HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; 117250003Sadrian 118250003Sadrian 119250008Sadrian if (q >= p_cap->halTotalQueues) { 120250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q); 121250003Sadrian return AH_FALSE; 122250003Sadrian } 123250008Sadrian return ath_hal_getTxQProps(ah, q_info, &ahp->ah_txq[q]); 124250003Sadrian} 125250003Sadrian 126250003Sadrianenum { 127250003Sadrian AH_TX_QUEUE_MINUS_OFFSET_BEACON = 1, 128250003Sadrian AH_TX_QUEUE_MINUS_OFFSET_CAB = 2, 129250003Sadrian AH_TX_QUEUE_MINUS_OFFSET_UAPSD = 3, 130250003Sadrian AH_TX_QUEUE_MINUS_OFFSET_PAPRD = 4, 131250003Sadrian}; 132250003Sadrian 133250003Sadrian/* 134250003Sadrian * Allocate and initialize a tx DCU/QCU combination. 135250003Sadrian */ 136250003Sadrianint 137250003Sadrianar9300_setup_tx_queue(struct ath_hal *ah, HAL_TX_QUEUE type, 138250003Sadrian const HAL_TXQ_INFO *q_info) 139250003Sadrian{ 140250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 141250003Sadrian HAL_TX_QUEUE_INFO *qi; 142250003Sadrian HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; 143250003Sadrian int q; 144250003Sadrian 145250003Sadrian /* XXX move queue assignment to driver */ 146250003Sadrian switch (type) { 147250003Sadrian case HAL_TX_QUEUE_BEACON: 148250003Sadrian /* highest priority */ 149250008Sadrian q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_BEACON; 150250003Sadrian break; 151250003Sadrian case HAL_TX_QUEUE_CAB: 152250003Sadrian /* next highest priority */ 153250008Sadrian q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_CAB; 154250003Sadrian break; 155250003Sadrian case HAL_TX_QUEUE_UAPSD: 156250008Sadrian q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_UAPSD; 157250003Sadrian break; 158250003Sadrian case HAL_TX_QUEUE_PAPRD: 159250008Sadrian q = p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_PAPRD; 160250003Sadrian break; 161250003Sadrian case HAL_TX_QUEUE_DATA: 162250003Sadrian /* 163250003Sadrian * don't infringe on top 4 queues, reserved for: 164250003Sadrian * beacon, CAB, UAPSD, PAPRD 165250003Sadrian */ 166250003Sadrian for (q = 0; 167250008Sadrian q < p_cap->halTotalQueues - AH_TX_QUEUE_MINUS_OFFSET_PAPRD; 168250003Sadrian q++) 169250003Sadrian { 170250003Sadrian if (ahp->ah_txq[q].tqi_type == HAL_TX_QUEUE_INACTIVE) { 171250003Sadrian break; 172250003Sadrian } 173250003Sadrian } 174250008Sadrian if (q == p_cap->halTotalQueues - 3) { 175250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 176250003Sadrian "%s: no available tx queue\n", __func__); 177250003Sadrian return -1; 178250003Sadrian } 179250003Sadrian break; 180250003Sadrian default: 181250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 182250003Sadrian "%s: bad tx queue type %u\n", __func__, type); 183250003Sadrian return -1; 184250003Sadrian } 185250003Sadrian 186250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: queue %u\n", __func__, q); 187250003Sadrian 188250003Sadrian qi = &ahp->ah_txq[q]; 189250003Sadrian if (qi->tqi_type != HAL_TX_QUEUE_INACTIVE) { 190250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 191250003Sadrian "%s: tx queue %u already active\n", __func__, q); 192250003Sadrian return -1; 193250003Sadrian } 194250003Sadrian 195250003Sadrian OS_MEMZERO(qi, sizeof(HAL_TX_QUEUE_INFO)); 196250003Sadrian qi->tqi_type = type; 197250003Sadrian 198250003Sadrian if (q_info == AH_NULL) { 199250003Sadrian /* by default enable OK+ERR+DESC+URN interrupts */ 200250008Sadrian qi->tqi_qflags = HAL_TXQ_TXOKINT_ENABLE 201250008Sadrian | HAL_TXQ_TXERRINT_ENABLE 202250008Sadrian | HAL_TXQ_TXDESCINT_ENABLE 203250008Sadrian | HAL_TXQ_TXURNINT_ENABLE; 204250003Sadrian qi->tqi_aifs = INIT_AIFS; 205250003Sadrian qi->tqi_cwmin = HAL_TXQ_USEDEFAULT; /* NB: do at reset */ 206250003Sadrian qi->tqi_cwmax = INIT_CWMAX; 207250003Sadrian qi->tqi_shretry = INIT_SH_RETRY; 208250003Sadrian qi->tqi_lgretry = INIT_LG_RETRY; 209250008Sadrian qi->tqi_physCompBuf = 0; 210250003Sadrian } else { 211250008Sadrian qi->tqi_physCompBuf = q_info->tqi_compBuf; 212250003Sadrian (void) ar9300_set_tx_queue_props(ah, q, q_info); 213250003Sadrian } 214250003Sadrian /* NB: must be followed by ar9300_reset_tx_queue */ 215250003Sadrian return q; 216250003Sadrian} 217250003Sadrian 218250003Sadrian/* 219250003Sadrian * Update the h/w interrupt registers to reflect a tx q's configuration. 220250003Sadrian */ 221250003Sadrianstatic void 222250003Sadrianset_tx_q_interrupts(struct ath_hal *ah, HAL_TX_QUEUE_INFO *qi) 223250003Sadrian{ 224250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 225250003Sadrian 226250003Sadrian HALDEBUG(ah, HAL_DEBUG_INTERRUPT, 227250003Sadrian "%s: tx ok 0x%x err 0x%x eol 0x%x urn 0x%x\n", 228250003Sadrian __func__, 229250003Sadrian ahp->ah_tx_ok_interrupt_mask, 230250003Sadrian ahp->ah_tx_err_interrupt_mask, 231250003Sadrian ahp->ah_tx_eol_interrupt_mask, 232250003Sadrian ahp->ah_tx_urn_interrupt_mask); 233250003Sadrian 234250003Sadrian OS_REG_WRITE(ah, AR_IMR_S0, 235250003Sadrian SM(ahp->ah_tx_ok_interrupt_mask, AR_IMR_S0_QCU_TXOK)); 236250003Sadrian OS_REG_WRITE(ah, AR_IMR_S1, 237250003Sadrian SM(ahp->ah_tx_err_interrupt_mask, AR_IMR_S1_QCU_TXERR) 238250003Sadrian | SM(ahp->ah_tx_eol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); 239250003Sadrian OS_REG_RMW_FIELD(ah, 240250003Sadrian AR_IMR_S2, AR_IMR_S2_QCU_TXURN, ahp->ah_tx_urn_interrupt_mask); 241250003Sadrian ahp->ah_mask2Reg = OS_REG_READ(ah, AR_IMR_S2); 242250003Sadrian} 243250003Sadrian 244250003Sadrian/* 245250003Sadrian * Free a tx DCU/QCU combination. 246250003Sadrian */ 247250003SadrianHAL_BOOL 248250003Sadrianar9300_release_tx_queue(struct ath_hal *ah, u_int q) 249250003Sadrian{ 250250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 251250003Sadrian HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; 252250003Sadrian HAL_TX_QUEUE_INFO *qi; 253250003Sadrian 254250008Sadrian if (q >= p_cap->halTotalQueues) { 255250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q); 256250003Sadrian return AH_FALSE; 257250003Sadrian } 258250003Sadrian 259250003Sadrian qi = &ahp->ah_txq[q]; 260250003Sadrian if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 261250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: inactive queue %u\n", __func__, q); 262250003Sadrian return AH_FALSE; 263250003Sadrian } 264250003Sadrian 265250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: release queue %u\n", __func__, q); 266250003Sadrian 267250003Sadrian qi->tqi_type = HAL_TX_QUEUE_INACTIVE; 268250003Sadrian ahp->ah_tx_ok_interrupt_mask &= ~(1 << q); 269250003Sadrian ahp->ah_tx_err_interrupt_mask &= ~(1 << q); 270250003Sadrian ahp->ah_tx_eol_interrupt_mask &= ~(1 << q); 271250003Sadrian ahp->ah_tx_urn_interrupt_mask &= ~(1 << q); 272250003Sadrian set_tx_q_interrupts(ah, qi); 273250003Sadrian 274250003Sadrian return AH_TRUE; 275250003Sadrian} 276250003Sadrian 277250003Sadrian/* 278250003Sadrian * Set the retry, aifs, cwmin/max, ready_time regs for specified queue 279250003Sadrian * Assumes: 280250003Sadrian * phw_channel has been set to point to the current channel 281250003Sadrian */ 282250003SadrianHAL_BOOL 283250003Sadrianar9300_reset_tx_queue(struct ath_hal *ah, u_int q) 284250003Sadrian{ 285250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 286250008Sadrian// struct ath_hal_private *ap = AH_PRIVATE(ah); 287250003Sadrian HAL_CAPABILITIES *p_cap = &AH_PRIVATE(ah)->ah_caps; 288250008Sadrian const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 289250003Sadrian HAL_TX_QUEUE_INFO *qi; 290250003Sadrian u_int32_t cw_min, chan_cw_min, value; 291301641Sadrian uint32_t qmisc, dmisc; 292250003Sadrian 293250008Sadrian if (q >= p_cap->halTotalQueues) { 294250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: invalid queue num %u\n", __func__, q); 295250003Sadrian return AH_FALSE; 296250003Sadrian } 297250003Sadrian 298250003Sadrian qi = &ahp->ah_txq[q]; 299250003Sadrian if (qi->tqi_type == HAL_TX_QUEUE_INACTIVE) { 300250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: inactive queue %u\n", __func__, q); 301250003Sadrian return AH_TRUE; /* XXX??? */ 302250003Sadrian } 303250003Sadrian 304250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: reset queue %u\n", __func__, q); 305250003Sadrian 306250003Sadrian if (qi->tqi_cwmin == HAL_TXQ_USEDEFAULT) { 307250003Sadrian /* 308250003Sadrian * Select cwmin according to channel type. 309250003Sadrian * NB: chan can be NULL during attach 310250003Sadrian */ 311250008Sadrian if (chan && IEEE80211_IS_CHAN_B(chan)) { 312250003Sadrian chan_cw_min = INIT_CWMIN_11B; 313250003Sadrian } else { 314250003Sadrian chan_cw_min = INIT_CWMIN; 315250003Sadrian } 316250003Sadrian /* make sure that the CWmin is of the form (2^n - 1) */ 317250003Sadrian for (cw_min = 1; cw_min < chan_cw_min; cw_min = (cw_min << 1) | 1) {} 318250003Sadrian } else { 319250003Sadrian cw_min = qi->tqi_cwmin; 320250003Sadrian } 321250003Sadrian 322250003Sadrian /* set cw_min/Max and AIFS values */ 323250008Sadrian if (q > 3 || (!AH9300(ah)->ah_fccaifs)) 324250003Sadrian /* values should not be overwritten if domain is FCC and manual rate 325250003Sadrian less than 24Mb is set, this check is making sure this */ 326250003Sadrian { 327250003Sadrian OS_REG_WRITE(ah, AR_DLCL_IFS(q), SM(cw_min, AR_D_LCL_IFS_CWMIN) 328250003Sadrian | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) 329250003Sadrian | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); 330250003Sadrian } 331250003Sadrian 332250003Sadrian /* Set retry limit values */ 333250003Sadrian OS_REG_WRITE(ah, AR_DRETRY_LIMIT(q), 334250003Sadrian SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | 335250003Sadrian SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) | 336250003Sadrian SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); 337250003Sadrian 338250003Sadrian /* enable early termination on the QCU */ 339301641Sadrian qmisc = AR_Q_MISC_DCU_EARLY_TERM_REQ; 340250003Sadrian 341250003Sadrian /* enable DCU to wait for next fragment from QCU */ 342250003Sadrian if (AR_SREV_WASP(ah) && (AH_PRIVATE((ah))->ah_macRev <= AR_SREV_REVISION_WASP_12)) { 343250003Sadrian /* WAR for EV#85395: Wasp Rx overrun issue - reduces Tx queue backoff 344250003Sadrian * threshold to 1 to avoid Rx overruns - Fixed in Wasp 1.3 */ 345301641Sadrian dmisc = AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1; 346250003Sadrian } else { 347301641Sadrian dmisc = AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2; 348250003Sadrian } 349250003Sadrian 350250003Sadrian /* multiqueue support */ 351250008Sadrian if (qi->tqi_cbrPeriod) { 352250003Sadrian OS_REG_WRITE(ah, 353250003Sadrian AR_QCBRCFG(q), 354250008Sadrian SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | 355250008Sadrian SM(qi->tqi_cbrOverflowLimit, 356250003Sadrian AR_Q_CBRCFG_OVF_THRESH)); 357301641Sadrian qmisc |= AR_Q_MISC_FSP_CBR | 358250008Sadrian (qi->tqi_cbrOverflowLimit ? 359301641Sadrian AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0); 360250003Sadrian } 361250003Sadrian 362250008Sadrian if (qi->tqi_readyTime && (qi->tqi_type != HAL_TX_QUEUE_CAB)) { 363250003Sadrian OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), 364250008Sadrian SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) | 365250003Sadrian AR_Q_RDYTIMECFG_EN); 366250003Sadrian } 367250003Sadrian 368250008Sadrian OS_REG_WRITE(ah, AR_DCHNTIME(q), SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | 369250008Sadrian (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); 370250003Sadrian 371302030Sadrian if (qi->tqi_readyTime && 372302030Sadrian (qi->tqi_qflags & HAL_TXQ_RDYTIME_EXP_POLICY_ENABLE)) 373301641Sadrian qmisc |= AR_Q_MISC_RDYTIME_EXP_POLICY; 374302030Sadrian if (qi->tqi_qflags & HAL_TXQ_DBA_GATED) 375302030Sadrian qmisc = (qmisc &~ AR_Q_MISC_FSP) | AR_Q_MISC_FSP_DBA_GATED; 376302030Sadrian if (MS(qmisc, AR_Q_MISC_FSP) != AR_Q_MISC_FSP_ASAP) { 377302030Sadrian /* 378302030Sadrian * These are meangingful only when not scheduled asap. 379302030Sadrian */ 380302030Sadrian if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_BEMPTY) 381302030Sadrian qmisc |= AR_Q_MISC_CBR_INCR_DIS0; 382302030Sadrian else 383302030Sadrian qmisc &= ~AR_Q_MISC_CBR_INCR_DIS0; 384302030Sadrian if (qi->tqi_qflags & HAL_TXQ_CBR_DIS_QEMPTY) 385302030Sadrian qmisc |= AR_Q_MISC_CBR_INCR_DIS1; 386302030Sadrian else 387302030Sadrian qmisc &= ~AR_Q_MISC_CBR_INCR_DIS1; 388250003Sadrian } 389250003Sadrian 390302030Sadrian if (qi->tqi_qflags & HAL_TXQ_BACKOFF_DISABLE) 391301641Sadrian dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS; 392302030Sadrian if (qi->tqi_qflags & HAL_TXQ_FRAG_BURST_BACKOFF_ENABLE) 393301641Sadrian dmisc |= AR_D_MISC_FRAG_BKOFF_EN; 394302030Sadrian if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_GLOBAL) 395302030Sadrian dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, 396302030Sadrian AR_D_MISC_ARB_LOCKOUT_CNTRL); 397302030Sadrian else if (qi->tqi_qflags & HAL_TXQ_ARB_LOCKOUT_INTRA) 398302030Sadrian dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR, 399302030Sadrian AR_D_MISC_ARB_LOCKOUT_CNTRL); 400302030Sadrian if (qi->tqi_qflags & HAL_TXQ_IGNORE_VIRTCOL) 401302030Sadrian dmisc |= SM(AR_D_MISC_VIR_COL_HANDLING_IGNORE, 402302030Sadrian AR_D_MISC_VIR_COL_HANDLING); 403302030Sadrian if (qi->tqi_qflags & HAL_TXQ_SEQNUM_INC_DIS) 404302030Sadrian dmisc |= AR_D_MISC_SEQ_NUM_INCR_DIS; 405250003Sadrian 406250003Sadrian switch (qi->tqi_type) { 407250003Sadrian case HAL_TX_QUEUE_BEACON: /* beacon frames */ 408301641Sadrian qmisc |= AR_Q_MISC_FSP_DBA_GATED 409250003Sadrian | AR_Q_MISC_BEACON_USE 410301641Sadrian | AR_Q_MISC_CBR_INCR_DIS1; 411250003Sadrian 412301641Sadrian dmisc |= (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << 413250003Sadrian AR_D_MISC_ARB_LOCKOUT_CNTRL_S) 414250003Sadrian | AR_D_MISC_BEACON_USE 415301641Sadrian | AR_D_MISC_POST_FR_BKOFF_DIS; 416250003Sadrian /* XXX cwmin and cwmax should be 0 for beacon queue */ 417250003Sadrian if (AH_PRIVATE(ah)->ah_opmode != HAL_M_IBSS) { 418250003Sadrian OS_REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) 419250003Sadrian | SM(0, AR_D_LCL_IFS_CWMAX) 420250003Sadrian | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); 421250003Sadrian } 422250003Sadrian break; 423250003Sadrian case HAL_TX_QUEUE_CAB: /* CAB frames */ 424250003Sadrian /* 425250003Sadrian * No longer Enable AR_Q_MISC_RDYTIME_EXP_POLICY, 426250003Sadrian * bug #6079. There is an issue with the CAB Queue 427250003Sadrian * not properly refreshing the Tx descriptor if 428250003Sadrian * the TXE clear setting is used. 429250003Sadrian */ 430301641Sadrian qmisc |= AR_Q_MISC_FSP_DBA_GATED 431250003Sadrian | AR_Q_MISC_CBR_INCR_DIS1 432301641Sadrian | AR_Q_MISC_CBR_INCR_DIS0; 433250003Sadrian 434301639Sadrian if (qi->tqi_readyTime) { 435301639Sadrian OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), 436301639Sadrian SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) | 437301639Sadrian AR_Q_RDYTIMECFG_EN); 438301639Sadrian } else { 439250003Sadrian 440301639Sadrian value = (ahp->ah_beaconInterval * 50 / 100) 441301639Sadrian - ah->ah_config.ah_additional_swba_backoff 442301639Sadrian - ah->ah_config.ah_sw_beacon_response_time 443301639Sadrian + ah->ah_config.ah_dma_beacon_response_time; 444301639Sadrian /* 445301639Sadrian * XXX Ensure it isn't too low - nothing lower 446301639Sadrian * XXX than 10 TU 447301639Sadrian */ 448301639Sadrian if (value < 10) 449301639Sadrian value = 10; 450301639Sadrian HALDEBUG(ah, HAL_DEBUG_TXQUEUE, 451301639Sadrian "%s: defaulting to rdytime = %d uS\n", 452301639Sadrian __func__, value); 453301639Sadrian OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), 454301639Sadrian SM(TU_TO_USEC(value), AR_Q_RDYTIMECFG_DURATION) | 455301639Sadrian AR_Q_RDYTIMECFG_EN); 456301639Sadrian } 457302030Sadrian dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, 458302030Sadrian AR_D_MISC_ARB_LOCKOUT_CNTRL); 459250003Sadrian break; 460250003Sadrian case HAL_TX_QUEUE_PSPOLL: 461250003Sadrian /* 462250003Sadrian * We may configure ps_poll QCU to be TIM-gated in the 463250003Sadrian * future; TIM_GATED bit is not enabled currently because 464250003Sadrian * of a hardware problem in Oahu that overshoots the TIM 465250003Sadrian * bitmap in beacon and may find matching associd bit in 466250003Sadrian * non-TIM elements and send PS-poll PS poll processing 467250003Sadrian * will be done in software 468250003Sadrian */ 469301641Sadrian qmisc |= AR_Q_MISC_CBR_INCR_DIS1; 470250003Sadrian break; 471250003Sadrian case HAL_TX_QUEUE_UAPSD: 472301641Sadrian dmisc |= AR_D_MISC_POST_FR_BKOFF_DIS; 473250003Sadrian break; 474250003Sadrian default: /* NB: silence compiler */ 475250003Sadrian break; 476250003Sadrian } 477250003Sadrian 478250003Sadrian#ifndef AH_DISABLE_WME 479250003Sadrian /* 480250003Sadrian * Yes, this is a hack and not the right way to do it, but 481250003Sadrian * it does get the lockout bits and backoff set for the 482250003Sadrian * high-pri WME queues for testing. We need to either extend 483250003Sadrian * the meaning of queue_info->mode, or create something like 484250003Sadrian * queue_info->dcumode. 485250003Sadrian */ 486250008Sadrian if (qi->tqi_intFlags & HAL_TXQ_USE_LOCKOUT_BKOFF_DIS) { 487301641Sadrian dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, 488250003Sadrian AR_D_MISC_ARB_LOCKOUT_CNTRL) | 489301641Sadrian AR_D_MISC_POST_FR_BKOFF_DIS; 490250003Sadrian } 491250003Sadrian#endif 492250003Sadrian 493250003Sadrian OS_REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN); 494301641Sadrian OS_REG_WRITE(ah, AR_QMISC(q), qmisc); 495301641Sadrian OS_REG_WRITE(ah, AR_DMISC(q), dmisc); 496250003Sadrian 497250003Sadrian /* 498250003Sadrian * Always update the secondary interrupt mask registers - this 499250003Sadrian * could be a new queue getting enabled in a running system or 500250003Sadrian * hw getting re-initialized during a reset! 501250003Sadrian * 502250003Sadrian * Since we don't differentiate between tx interrupts corresponding 503250003Sadrian * to individual queues - secondary tx mask regs are always unmasked; 504250003Sadrian * tx interrupts are enabled/disabled for all queues collectively 505250003Sadrian * using the primary mask reg 506250003Sadrian */ 507250008Sadrian if (qi->tqi_qflags & HAL_TXQ_TXOKINT_ENABLE) { 508250003Sadrian ahp->ah_tx_ok_interrupt_mask |= (1 << q); 509250003Sadrian } else { 510250003Sadrian ahp->ah_tx_ok_interrupt_mask &= ~(1 << q); 511250003Sadrian } 512250008Sadrian if (qi->tqi_qflags & HAL_TXQ_TXERRINT_ENABLE) { 513250003Sadrian ahp->ah_tx_err_interrupt_mask |= (1 << q); 514250003Sadrian } else { 515250003Sadrian ahp->ah_tx_err_interrupt_mask &= ~(1 << q); 516250003Sadrian } 517250008Sadrian if (qi->tqi_qflags & HAL_TXQ_TXEOLINT_ENABLE) { 518250003Sadrian ahp->ah_tx_eol_interrupt_mask |= (1 << q); 519250003Sadrian } else { 520250003Sadrian ahp->ah_tx_eol_interrupt_mask &= ~(1 << q); 521250003Sadrian } 522250008Sadrian if (qi->tqi_qflags & HAL_TXQ_TXURNINT_ENABLE) { 523250003Sadrian ahp->ah_tx_urn_interrupt_mask |= (1 << q); 524250003Sadrian } else { 525250003Sadrian ahp->ah_tx_urn_interrupt_mask &= ~(1 << q); 526250003Sadrian } 527250003Sadrian set_tx_q_interrupts(ah, qi); 528250003Sadrian 529250003Sadrian return AH_TRUE; 530250003Sadrian} 531250003Sadrian 532250003Sadrian/* 533250003Sadrian * Get the TXDP for the specified queue 534250003Sadrian */ 535250003Sadrianu_int32_t 536250003Sadrianar9300_get_tx_dp(struct ath_hal *ah, u_int q) 537250003Sadrian{ 538250008Sadrian HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); 539250003Sadrian return OS_REG_READ(ah, AR_QTXDP(q)); 540250003Sadrian} 541250003Sadrian 542250003Sadrian/* 543250003Sadrian * Set the tx_dp for the specified queue 544250003Sadrian */ 545250003SadrianHAL_BOOL 546250003Sadrianar9300_set_tx_dp(struct ath_hal *ah, u_int q, u_int32_t txdp) 547250003Sadrian{ 548250008Sadrian HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); 549250003Sadrian HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); 550250003Sadrian HALASSERT(txdp != 0); 551250003Sadrian 552250003Sadrian OS_REG_WRITE(ah, AR_QTXDP(q), txdp); 553250003Sadrian 554250003Sadrian return AH_TRUE; 555250003Sadrian} 556250003Sadrian 557250003Sadrian/* 558250003Sadrian * Transmit Enable is read-only now 559250003Sadrian */ 560250003SadrianHAL_BOOL 561250003Sadrianar9300_start_tx_dma(struct ath_hal *ah, u_int q) 562250003Sadrian{ 563250003Sadrian return AH_TRUE; 564250003Sadrian} 565250003Sadrian 566250003Sadrian/* 567250003Sadrian * Return the number of pending frames or 0 if the specified 568250003Sadrian * queue is stopped. 569250003Sadrian */ 570250003Sadrianu_int32_t 571250003Sadrianar9300_num_tx_pending(struct ath_hal *ah, u_int q) 572250003Sadrian{ 573250003Sadrian u_int32_t npend; 574250003Sadrian 575250008Sadrian HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues); 576250003Sadrian 577250003Sadrian npend = OS_REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; 578250003Sadrian if (npend == 0) { 579250003Sadrian /* 580250003Sadrian * Pending frame count (PFC) can momentarily go to zero 581250003Sadrian * while TXE remains asserted. In other words a PFC of 582250003Sadrian * zero is not sufficient to say that the queue has stopped. 583250003Sadrian */ 584250003Sadrian if (OS_REG_READ(ah, AR_Q_TXE) & (1 << q)) { 585250003Sadrian npend = 1; /* arbitrarily return 1 */ 586250003Sadrian } 587250003Sadrian } 588250003Sadrian#ifdef DEBUG 589250003Sadrian if (npend && (AH9300(ah)->ah_txq[q].tqi_type == HAL_TX_QUEUE_CAB)) { 590250003Sadrian if (OS_REG_READ(ah, AR_Q_RDYTIMESHDN) & (1 << q)) { 591250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "RTSD on CAB queue\n"); 592250003Sadrian /* Clear the ready_time shutdown status bits */ 593250003Sadrian OS_REG_WRITE(ah, AR_Q_RDYTIMESHDN, 1 << q); 594250003Sadrian } 595250003Sadrian } 596250003Sadrian#endif 597250003Sadrian HALASSERT((npend == 0) || 598250003Sadrian (AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE)); 599250003Sadrian 600250003Sadrian return npend; 601250003Sadrian} 602250003Sadrian 603250003Sadrian/* 604250003Sadrian * Stop transmit on the specified queue 605250003Sadrian */ 606250003SadrianHAL_BOOL 607250003Sadrianar9300_stop_tx_dma(struct ath_hal *ah, u_int q, u_int timeout) 608250003Sadrian{ 609278741Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 610278741Sadrian 611250003Sadrian /* 612278741Sadrian * If we call abort txdma instead, no need to stop RX. 613278741Sadrian * Otherwise, the RX logic might not be restarted properly. 614278741Sadrian */ 615278741Sadrian ahp->ah_abort_txdma_norx = AH_FALSE; 616278741Sadrian 617278741Sadrian /* 618250003Sadrian * Directly call abort. It is better, hardware-wise, to stop all 619250003Sadrian * queues at once than individual ones. 620250003Sadrian */ 621250003Sadrian return ar9300_abort_tx_dma(ah); 622250003Sadrian 623250003Sadrian#if 0 624250003Sadrian#define AH_TX_STOP_DMA_TIMEOUT 4000 /* usec */ 625250003Sadrian#define AH_TIME_QUANTUM 100 /* usec */ 626250003Sadrian u_int wait; 627250003Sadrian 628250003Sadrian HALASSERT(q < AH_PRIVATE(ah)->ah_caps.hal_total_queues); 629250003Sadrian 630250003Sadrian HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); 631250003Sadrian 632250003Sadrian if (timeout == 0) { 633250003Sadrian timeout = AH_TX_STOP_DMA_TIMEOUT; 634250003Sadrian } 635250003Sadrian 636250003Sadrian OS_REG_WRITE(ah, AR_Q_TXD, 1 << q); 637250003Sadrian 638250003Sadrian for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) { 639250003Sadrian if (ar9300_num_tx_pending(ah, q) == 0) { 640250003Sadrian break; 641250003Sadrian } 642250003Sadrian OS_DELAY(AH_TIME_QUANTUM); /* XXX get actual value */ 643250003Sadrian } 644250003Sadrian 645250003Sadrian#ifdef AH_DEBUG 646250003Sadrian if (wait == 0) { 647250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 648250003Sadrian "%s: queue %u DMA did not stop in 100 msec\n", __func__, q); 649250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 650250003Sadrian "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", 651250003Sadrian __func__, 652250003Sadrian OS_REG_READ(ah, AR_QSTS(q)), 653250003Sadrian OS_REG_READ(ah, AR_Q_TXE), 654250003Sadrian OS_REG_READ(ah, AR_Q_TXD), 655250003Sadrian OS_REG_READ(ah, AR_QCBRCFG(q))); 656250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 657250003Sadrian "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n", 658250003Sadrian __func__, 659250003Sadrian OS_REG_READ(ah, AR_QMISC(q)), 660250003Sadrian OS_REG_READ(ah, AR_QRDYTIMECFG(q)), 661250003Sadrian OS_REG_READ(ah, AR_Q_RDYTIMESHDN)); 662250003Sadrian } 663250003Sadrian#endif /* AH_DEBUG */ 664250003Sadrian 665250003Sadrian /* 2413+ and up can kill packets at the PCU level */ 666250003Sadrian if (ar9300_num_tx_pending(ah, q)) { 667250003Sadrian u_int32_t tsf_low, j; 668250003Sadrian 669250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Num of pending TX Frames %d on Q %d\n", 670250003Sadrian __func__, ar9300_num_tx_pending(ah, q), q); 671250003Sadrian 672250003Sadrian /* Kill last PCU Tx Frame */ 673250003Sadrian /* TODO - save off and restore current values of Q1/Q2? */ 674250003Sadrian for (j = 0; j < 2; j++) { 675250003Sadrian tsf_low = OS_REG_READ(ah, AR_TSF_L32); 676250003Sadrian OS_REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR)); 677250003Sadrian OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100); 678250003Sadrian OS_REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsf_low >> 10); 679250003Sadrian OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); 680250003Sadrian 681250003Sadrian if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsf_low >> 10)) { 682250003Sadrian break; 683250003Sadrian } 684250003Sadrian 685250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 686250003Sadrian "%s: TSF have moved while trying to set " 687250003Sadrian "quiet time TSF: 0x%08x\n", 688250003Sadrian __func__, tsf_low); 689250003Sadrian /* TSF shouldn't count twice or reg access is taking forever */ 690250003Sadrian HALASSERT(j < 1); 691250003Sadrian } 692250003Sadrian 693250003Sadrian OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); 694250003Sadrian 695250003Sadrian /* Allow the quiet mechanism to do its work */ 696250003Sadrian OS_DELAY(200); 697250003Sadrian OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); 698250003Sadrian 699250003Sadrian /* Verify all transmit is dead */ 700250003Sadrian wait = timeout / AH_TIME_QUANTUM; 701250003Sadrian while (ar9300_num_tx_pending(ah, q)) { 702250003Sadrian if ((--wait) == 0) { 703250003Sadrian HALDEBUG(ah, HAL_DEBUG_TX, 704250003Sadrian "%s: Failed to stop Tx DMA in %d msec " 705250003Sadrian "after killing last frame\n", 706250003Sadrian __func__, timeout / 1000); 707250003Sadrian break; 708250003Sadrian } 709250003Sadrian OS_DELAY(AH_TIME_QUANTUM); 710250003Sadrian } 711250003Sadrian 712250003Sadrian OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); 713250003Sadrian } 714250003Sadrian 715250003Sadrian OS_REG_WRITE(ah, AR_Q_TXD, 0); 716250003Sadrian return (wait != 0); 717250003Sadrian 718250003Sadrian#undef AH_TX_STOP_DMA_TIMEOUT 719250003Sadrian#undef AH_TIME_QUANTUM 720250003Sadrian#endif 721250003Sadrian} 722250003Sadrian 723250003Sadrian/* 724250003Sadrian * Really Stop transmit on the specified queue 725250003Sadrian */ 726250003SadrianHAL_BOOL 727250003Sadrianar9300_stop_tx_dma_indv_que(struct ath_hal *ah, u_int q, u_int timeout) 728250003Sadrian{ 729250003Sadrian#define AH_TX_STOP_DMA_TIMEOUT 4000 /* usec */ 730250003Sadrian#define AH_TIME_QUANTUM 100 /* usec */ 731250003Sadrian u_int wait; 732250003Sadrian 733250003Sadrian HALASSERT(q < AH_PRIVATE(ah)->ah_caps.hal_total_queues); 734250003Sadrian 735250003Sadrian HALASSERT(AH9300(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE); 736250003Sadrian 737250003Sadrian if (timeout == 0) { 738250003Sadrian timeout = AH_TX_STOP_DMA_TIMEOUT; 739250003Sadrian } 740250003Sadrian 741250003Sadrian OS_REG_WRITE(ah, AR_Q_TXD, 1 << q); 742250003Sadrian 743250003Sadrian for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) { 744250003Sadrian if (ar9300_num_tx_pending(ah, q) == 0) { 745250003Sadrian break; 746250003Sadrian } 747250003Sadrian OS_DELAY(AH_TIME_QUANTUM); /* XXX get actual value */ 748250003Sadrian } 749250003Sadrian 750250003Sadrian#ifdef AH_DEBUG 751250003Sadrian if (wait == 0) { 752250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 753250003Sadrian "%s: queue %u DMA did not stop in 100 msec\n", __func__, q); 754250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 755250003Sadrian "%s: QSTS 0x%x Q_TXE 0x%x Q_TXD 0x%x Q_CBR 0x%x\n", 756250003Sadrian __func__, 757250003Sadrian OS_REG_READ(ah, AR_QSTS(q)), 758250003Sadrian OS_REG_READ(ah, AR_Q_TXE), 759250003Sadrian OS_REG_READ(ah, AR_Q_TXD), 760250003Sadrian OS_REG_READ(ah, AR_QCBRCFG(q))); 761250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 762250003Sadrian "%s: Q_MISC 0x%x Q_RDYTIMECFG 0x%x Q_RDYTIMESHDN 0x%x\n", 763250003Sadrian __func__, 764250003Sadrian OS_REG_READ(ah, AR_QMISC(q)), 765250003Sadrian OS_REG_READ(ah, AR_QRDYTIMECFG(q)), 766250003Sadrian OS_REG_READ(ah, AR_Q_RDYTIMESHDN)); 767250003Sadrian } 768250003Sadrian#endif /* AH_DEBUG */ 769250003Sadrian 770250003Sadrian /* 2413+ and up can kill packets at the PCU level */ 771250003Sadrian if (ar9300_num_tx_pending(ah, q)) { 772250003Sadrian u_int32_t tsf_low, j; 773250003Sadrian 774250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, "%s: Num of pending TX Frames %d on Q %d\n", 775250003Sadrian __func__, ar9300_num_tx_pending(ah, q), q); 776250003Sadrian 777250003Sadrian /* Kill last PCU Tx Frame */ 778250003Sadrian /* TODO - save off and restore current values of Q1/Q2? */ 779250003Sadrian for (j = 0; j < 2; j++) { 780250003Sadrian tsf_low = OS_REG_READ(ah, AR_TSF_L32); 781250003Sadrian OS_REG_WRITE(ah, AR_QUIET2, SM(10, AR_QUIET2_QUIET_DUR)); 782250003Sadrian OS_REG_WRITE(ah, AR_QUIET_PERIOD, 100); 783250003Sadrian OS_REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsf_low >> 10); 784250003Sadrian OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); 785250003Sadrian 786250003Sadrian if ((OS_REG_READ(ah, AR_TSF_L32) >> 10) == (tsf_low >> 10)) { 787250003Sadrian break; 788250003Sadrian } 789250003Sadrian 790250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 791250003Sadrian "%s: TSF have moved while trying to set " 792250003Sadrian "quiet time TSF: 0x%08x\n", 793250003Sadrian __func__, tsf_low); 794250003Sadrian /* TSF shouldn't count twice or reg access is taking forever */ 795250003Sadrian HALASSERT(j < 1); 796250003Sadrian } 797250003Sadrian 798250003Sadrian OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); 799250003Sadrian 800250003Sadrian /* Allow the quiet mechanism to do its work */ 801250003Sadrian OS_DELAY(200); 802250003Sadrian OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); 803250003Sadrian 804250003Sadrian /* Verify all transmit is dead */ 805250003Sadrian wait = timeout / AH_TIME_QUANTUM; 806250003Sadrian while (ar9300_num_tx_pending(ah, q)) { 807250003Sadrian if ((--wait) == 0) { 808250003Sadrian HALDEBUG(ah, HAL_DEBUG_TX, 809250003Sadrian "%s: Failed to stop Tx DMA in %d msec " 810250003Sadrian "after killing last frame\n", 811250003Sadrian __func__, timeout / 1000); 812250003Sadrian break; 813250003Sadrian } 814250003Sadrian OS_DELAY(AH_TIME_QUANTUM); 815250003Sadrian } 816250003Sadrian 817250003Sadrian OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); 818250003Sadrian } 819250003Sadrian 820250003Sadrian OS_REG_WRITE(ah, AR_Q_TXD, 0); 821250003Sadrian return (wait != 0); 822250003Sadrian 823250003Sadrian#undef AH_TX_STOP_DMA_TIMEOUT 824250003Sadrian#undef AH_TIME_QUANTUM 825250003Sadrian} 826250003Sadrian 827250003Sadrian/* 828250003Sadrian * Abort transmit on all queues 829250003Sadrian */ 830250003Sadrian#define AR9300_ABORT_LOOPS 1000 831250003Sadrian#define AR9300_ABORT_WAIT 5 832278741Sadrian#define NEXT_TBTT_NOW 10 833250003SadrianHAL_BOOL 834250003Sadrianar9300_abort_tx_dma(struct ath_hal *ah) 835250003Sadrian{ 836278741Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 837250003Sadrian int i, q; 838278741Sadrian u_int32_t nexttbtt, nextdba, tsf_tbtt, tbtt, dba; 839278741Sadrian HAL_BOOL stopped; 840278741Sadrian HAL_BOOL status = AH_TRUE; 841250003Sadrian 842278741Sadrian if (ahp->ah_abort_txdma_norx) { 843278741Sadrian /* 844278741Sadrian * First of all, make sure RX has been stopped 845278741Sadrian */ 846278741Sadrian if (ar9300_get_power_mode(ah) != HAL_PM_FULL_SLEEP) { 847278741Sadrian /* Need to stop RX DMA before reset otherwise chip might hang */ 848278741Sadrian stopped = ar9300_set_rx_abort(ah, AH_TRUE); /* abort and disable PCU */ 849278741Sadrian ar9300_set_rx_filter(ah, 0); 850278741Sadrian stopped &= ar9300_stop_dma_receive(ah, 0); /* stop and disable RX DMA */ 851278741Sadrian if (!stopped) { 852278741Sadrian /* 853278741Sadrian * During the transition from full sleep to reset, 854278741Sadrian * recv DMA regs are not available to be read 855278741Sadrian */ 856278741Sadrian HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, 857278741Sadrian "%s[%d]: ar9300_stop_dma_receive failed\n", __func__, __LINE__); 858278741Sadrian //We still continue to stop TX dma 859278741Sadrian //return AH_FALSE; 860278741Sadrian } 861278741Sadrian } else { 862278741Sadrian HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, 863278741Sadrian "%s[%d]: Chip is already in full sleep\n", __func__, __LINE__); 864278741Sadrian } 865278741Sadrian } 866278741Sadrian 867250003Sadrian /* 868250003Sadrian * set txd on all queues 869250003Sadrian */ 870250003Sadrian OS_REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M); 871250003Sadrian 872250003Sadrian /* 873250003Sadrian * set tx abort bits (also disable rx) 874250003Sadrian */ 875250003Sadrian OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); 876278741Sadrian /* Add a new receipe from K31 code */ 877278741Sadrian OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | 878278741Sadrian AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); 879278741Sadrian /* beacon Q flush */ 880278741Sadrian nexttbtt = OS_REG_READ(ah, AR_NEXT_TBTT_TIMER); 881278741Sadrian nextdba = OS_REG_READ(ah, AR_NEXT_DMA_BEACON_ALERT); 882278741Sadrian //printk("%s[%d]:dba: %d, nt: %d \n", __func__, __LINE__, nextdba, nexttbtt); 883278741Sadrian tsf_tbtt = OS_REG_READ(ah, AR_TSF_L32); 884278741Sadrian tbtt = tsf_tbtt + NEXT_TBTT_NOW; 885278741Sadrian dba = tsf_tbtt; 886278741Sadrian OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, dba); 887278741Sadrian OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, tbtt); 888250003Sadrian OS_REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); 889250003Sadrian 890278741Sadrian /* 891278741Sadrian * Let TXE (all queues) clear before waiting for any pending frames 892278741Sadrian * This is needed before starting the RF_BUS GRANT sequence other wise causes kernel 893278741Sadrian * panic 894278741Sadrian */ 895278741Sadrian for(i = 0; i < AR9300_ABORT_LOOPS; i++) { 896278741Sadrian if(OS_REG_READ(ah, AR_Q_TXE) == 0) { 897250003Sadrian break; 898250003Sadrian } 899250003Sadrian OS_DELAY(AR9300_ABORT_WAIT); 900250003Sadrian } 901250003Sadrian if (i == AR9300_ABORT_LOOPS) { 902250003Sadrian HALDEBUG(ah, HAL_DEBUG_TX, "%s[%d] reached max wait on TXE\n", 903250003Sadrian __func__, __LINE__); 904250003Sadrian } 905250003Sadrian 906250003Sadrian /* 907250003Sadrian * wait on all tx queues 908278741Sadrian * This need to be checked in the last to gain extra 50 usec. on avg. 909278741Sadrian * Currently checked first since we dont have a previous channel information currently. 910278741Sadrian * Which is needed to revert the rf changes. 911250003Sadrian */ 912278741Sadrian for (q = AR_NUM_QCU - 1; q >= 0; q--) { 913250003Sadrian for (i = 0; i < AR9300_ABORT_LOOPS; i++) { 914278741Sadrian if (!(ar9300_num_tx_pending(ah, q))) { 915250003Sadrian break; 916250003Sadrian } 917250003Sadrian OS_DELAY(AR9300_ABORT_WAIT); 918250003Sadrian } 919250003Sadrian if (i == AR9300_ABORT_LOOPS) { 920278741Sadrian status = AH_FALSE; 921278741Sadrian HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, 922278741Sadrian "ABORT LOOP finsihsed for Q: %d, num_pending: %d \n", 923278741Sadrian q, ar9300_num_tx_pending(ah, q)); 924278741Sadrian goto exit; 925250003Sadrian } 926250003Sadrian } 927250003Sadrian 928278741Sadrian /* Updating the beacon alert register with correct value */ 929278741Sadrian OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, nextdba); 930278741Sadrian OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, nexttbtt); 931278741Sadrian 932278741Sadrianexit: 933250003Sadrian /* 934250003Sadrian * clear tx abort bits 935250003Sadrian */ 936250003Sadrian OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); 937278741Sadrian /* Added a new receipe from K31 code */ 938278741Sadrian OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | 939278741Sadrian AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); 940250003Sadrian OS_REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); 941250003Sadrian 942250003Sadrian /* 943250003Sadrian * clear txd 944250003Sadrian */ 945250003Sadrian OS_REG_WRITE(ah, AR_Q_TXD, 0); 946250003Sadrian 947278741Sadrian ahp->ah_abort_txdma_norx = AH_TRUE; 948278741Sadrian 949278741Sadrian return status; 950250003Sadrian} 951250003Sadrian 952250003Sadrian/* 953250003Sadrian * Determine which tx queues need interrupt servicing. 954250003Sadrian */ 955250003Sadrianvoid 956250003Sadrianar9300_get_tx_intr_queue(struct ath_hal *ah, u_int32_t *txqs) 957250003Sadrian{ 958250003Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, 959250003Sadrian "ar9300_get_tx_intr_queue: Should not be called\n"); 960250003Sadrian#if 0 961250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 962250003Sadrian *txqs &= ahp->ah_intr_txqs; 963250003Sadrian ahp->ah_intr_txqs &= ~(*txqs); 964250003Sadrian#endif 965250003Sadrian} 966250003Sadrian 967250003Sadrianvoid 968250003Sadrianar9300_reset_tx_status_ring(struct ath_hal *ah) 969250003Sadrian{ 970250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 971250003Sadrian 972250003Sadrian ahp->ts_tail = 0; 973250003Sadrian 974250003Sadrian /* Zero out the status descriptors */ 975250003Sadrian OS_MEMZERO((void *)ahp->ts_ring, ahp->ts_size * sizeof(struct ar9300_txs)); 976250003Sadrian HALDEBUG(ah, HAL_DEBUG_QUEUE, 977250003Sadrian "%s: TS Start 0x%x End 0x%x Virt %p, Size %d\n", __func__, 978250003Sadrian ahp->ts_paddr_start, ahp->ts_paddr_end, ahp->ts_ring, ahp->ts_size); 979250003Sadrian 980250003Sadrian OS_REG_WRITE(ah, AR_Q_STATUS_RING_START, ahp->ts_paddr_start); 981250003Sadrian OS_REG_WRITE(ah, AR_Q_STATUS_RING_END, ahp->ts_paddr_end); 982250003Sadrian} 983250003Sadrian 984250003Sadrianvoid 985250003Sadrianar9300_setup_tx_status_ring(struct ath_hal *ah, void *ts_start, 986250003Sadrian u_int32_t ts_paddr_start, u_int16_t size) 987250003Sadrian{ 988250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 989250003Sadrian 990250003Sadrian ahp->ts_paddr_start = ts_paddr_start; 991250003Sadrian ahp->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9300_txs)); 992250003Sadrian ahp->ts_size = size; 993250003Sadrian ahp->ts_ring = (struct ar9300_txs *)ts_start; 994250003Sadrian 995250003Sadrian ar9300_reset_tx_status_ring(ah); 996250003Sadrian} 997