1049 lines · c
1/*2 * Copyright (c) 2008-2011 Atheros Communications Inc.3 *4 * Permission to use, copy, modify, and/or distribute this software for any5 * purpose with or without fee is hereby granted, provided that the above6 * copyright notice and this permission notice appear in all copies.7 *8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15 */16 17#include "hw.h"18#include "hw-ops.h"19#include <linux/export.h>20 21static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,22 struct ath9k_tx_queue_info *qi)23{24 ath_dbg(ath9k_hw_common(ah), INTERRUPT,25 "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",26 ah->txok_interrupt_mask, ah->txerr_interrupt_mask,27 ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,28 ah->txurn_interrupt_mask);29 30 ENABLE_REGWRITE_BUFFER(ah);31 32 REG_WRITE(ah, AR_IMR_S0,33 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)34 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));35 REG_WRITE(ah, AR_IMR_S1,36 SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)37 | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));38 39 ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;40 ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);41 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);42 43 REGWRITE_BUFFER_FLUSH(ah);44}45 46u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)47{48 return REG_READ(ah, AR_QTXDP(q));49}50EXPORT_SYMBOL(ath9k_hw_gettxbuf);51 52void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)53{54 REG_WRITE(ah, AR_QTXDP(q), txdp);55}56EXPORT_SYMBOL(ath9k_hw_puttxbuf);57 58void ath9k_hw_txstart(struct ath_hw *ah, u32 q)59{60 ath_dbg(ath9k_hw_common(ah), QUEUE, "Enable TXE on queue: %u\n", q);61 REG_WRITE(ah, AR_Q_TXE, 1 << q);62}63EXPORT_SYMBOL(ath9k_hw_txstart);64 65u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)66{67 u32 npend;68 69 npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;70 if (npend == 0) {71 72 if (REG_READ(ah, AR_Q_TXE) & (1 << q))73 npend = 1;74 }75 76 return npend;77}78EXPORT_SYMBOL(ath9k_hw_numtxpending);79 80/**81 * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level82 *83 * @ah: atheros hardware struct84 * @bIncTrigLevel: whether or not the frame trigger level should be updated85 *86 * The frame trigger level specifies the minimum number of bytes,87 * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO88 * before the PCU will initiate sending the frame on the air. This can89 * mean we initiate transmit before a full frame is on the PCU TX FIFO.90 * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs91 * first)92 *93 * Caution must be taken to ensure to set the frame trigger level based94 * on the DMA request size. For example if the DMA request size is set to95 * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because96 * there need to be enough space in the tx FIFO for the requested transfer97 * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set98 * the threshold to a value beyond 6, then the transmit will hang.99 *100 * Current dual stream devices have a PCU TX FIFO size of 8 KB.101 * Current single stream devices have a PCU TX FIFO size of 4 KB, however,102 * there is a hardware issue which forces us to use 2 KB instead so the103 * frame trigger level must not exceed 2 KB for these chipsets.104 */105bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)106{107 u32 txcfg, curLevel, newLevel;108 109 if (ah->tx_trig_level >= ah->config.max_txtrig_level)110 return false;111 112 ath9k_hw_disable_interrupts(ah);113 114 txcfg = REG_READ(ah, AR_TXCFG);115 curLevel = MS(txcfg, AR_FTRIG);116 newLevel = curLevel;117 if (bIncTrigLevel) {118 if (curLevel < ah->config.max_txtrig_level)119 newLevel++;120 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)121 newLevel--;122 if (newLevel != curLevel)123 REG_WRITE(ah, AR_TXCFG,124 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));125 126 ath9k_hw_enable_interrupts(ah);127 128 ah->tx_trig_level = newLevel;129 130 return newLevel != curLevel;131}132EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);133 134void ath9k_hw_abort_tx_dma(struct ath_hw *ah)135{136 int maxdelay = 1000;137 int i, q;138 139 if (ah->curchan) {140 if (IS_CHAN_HALF_RATE(ah->curchan))141 maxdelay *= 2;142 else if (IS_CHAN_QUARTER_RATE(ah->curchan))143 maxdelay *= 4;144 }145 146 REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);147 148 REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);149 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);150 REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);151 152 for (q = 0; q < AR_NUM_QCU; q++) {153 for (i = 0; i < maxdelay; i++) {154 if (i)155 udelay(5);156 157 if (!ath9k_hw_numtxpending(ah, q))158 break;159 }160 }161 162 REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);163 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);164 REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);165 166 REG_WRITE(ah, AR_Q_TXD, 0);167}168EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);169 170bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)171{172#define ATH9K_TX_STOP_DMA_TIMEOUT 1000 /* usec */173#define ATH9K_TIME_QUANTUM 100 /* usec */174 int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;175 int wait;176 177 REG_WRITE(ah, AR_Q_TXD, 1 << q);178 179 for (wait = wait_time; wait != 0; wait--) {180 if (wait != wait_time)181 udelay(ATH9K_TIME_QUANTUM);182 183 if (ath9k_hw_numtxpending(ah, q) == 0)184 break;185 }186 187 REG_WRITE(ah, AR_Q_TXD, 0);188 189 return wait != 0;190 191#undef ATH9K_TX_STOP_DMA_TIMEOUT192#undef ATH9K_TIME_QUANTUM193}194EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);195 196bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,197 const struct ath9k_tx_queue_info *qinfo)198{199 u32 cw;200 struct ath_common *common = ath9k_hw_common(ah);201 struct ath9k_tx_queue_info *qi;202 203 qi = &ah->txq[q];204 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {205 ath_dbg(common, QUEUE,206 "Set TXQ properties, inactive queue: %u\n", q);207 return false;208 }209 210 ath_dbg(common, QUEUE, "Set queue properties for: %u\n", q);211 212 qi->tqi_ver = qinfo->tqi_ver;213 qi->tqi_subtype = qinfo->tqi_subtype;214 qi->tqi_qflags = qinfo->tqi_qflags;215 qi->tqi_priority = qinfo->tqi_priority;216 if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)217 qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);218 else219 qi->tqi_aifs = INIT_AIFS;220 if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {221 cw = min(qinfo->tqi_cwmin, 1024U);222 qi->tqi_cwmin = 1;223 while (qi->tqi_cwmin < cw)224 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;225 } else226 qi->tqi_cwmin = qinfo->tqi_cwmin;227 if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {228 cw = min(qinfo->tqi_cwmax, 1024U);229 qi->tqi_cwmax = 1;230 while (qi->tqi_cwmax < cw)231 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;232 } else233 qi->tqi_cwmax = INIT_CWMAX;234 235 if (qinfo->tqi_shretry != 0)236 qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);237 else238 qi->tqi_shretry = INIT_SH_RETRY;239 if (qinfo->tqi_lgretry != 0)240 qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);241 else242 qi->tqi_lgretry = INIT_LG_RETRY;243 qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;244 qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;245 qi->tqi_burstTime = qinfo->tqi_burstTime;246 qi->tqi_readyTime = qinfo->tqi_readyTime;247 248 switch (qinfo->tqi_subtype) {249 case ATH9K_WME_UPSD:250 if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)251 qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;252 break;253 default:254 break;255 }256 257 return true;258}259EXPORT_SYMBOL(ath9k_hw_set_txq_props);260 261bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,262 struct ath9k_tx_queue_info *qinfo)263{264 struct ath_common *common = ath9k_hw_common(ah);265 struct ath9k_tx_queue_info *qi;266 267 qi = &ah->txq[q];268 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {269 ath_dbg(common, QUEUE,270 "Get TXQ properties, inactive queue: %u\n", q);271 return false;272 }273 274 qinfo->tqi_qflags = qi->tqi_qflags;275 qinfo->tqi_ver = qi->tqi_ver;276 qinfo->tqi_subtype = qi->tqi_subtype;277 qinfo->tqi_qflags = qi->tqi_qflags;278 qinfo->tqi_priority = qi->tqi_priority;279 qinfo->tqi_aifs = qi->tqi_aifs;280 qinfo->tqi_cwmin = qi->tqi_cwmin;281 qinfo->tqi_cwmax = qi->tqi_cwmax;282 qinfo->tqi_shretry = qi->tqi_shretry;283 qinfo->tqi_lgretry = qi->tqi_lgretry;284 qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;285 qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;286 qinfo->tqi_burstTime = qi->tqi_burstTime;287 qinfo->tqi_readyTime = qi->tqi_readyTime;288 289 return true;290}291EXPORT_SYMBOL(ath9k_hw_get_txq_props);292 293int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,294 const struct ath9k_tx_queue_info *qinfo)295{296 struct ath_common *common = ath9k_hw_common(ah);297 struct ath9k_tx_queue_info *qi;298 int q;299 300 switch (type) {301 case ATH9K_TX_QUEUE_BEACON:302 q = ATH9K_NUM_TX_QUEUES - 1;303 break;304 case ATH9K_TX_QUEUE_CAB:305 q = ATH9K_NUM_TX_QUEUES - 2;306 break;307 case ATH9K_TX_QUEUE_PSPOLL:308 q = 1;309 break;310 case ATH9K_TX_QUEUE_UAPSD:311 q = ATH9K_NUM_TX_QUEUES - 3;312 break;313 case ATH9K_TX_QUEUE_DATA:314 q = qinfo->tqi_subtype;315 break;316 default:317 ath_err(common, "Invalid TX queue type: %u\n", type);318 return -1;319 }320 321 ath_dbg(common, QUEUE, "Setup TX queue: %u\n", q);322 323 qi = &ah->txq[q];324 if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {325 ath_err(common, "TX queue: %u already active\n", q);326 return -1;327 }328 memset(qi, 0, sizeof(struct ath9k_tx_queue_info));329 qi->tqi_type = type;330 qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;331 (void) ath9k_hw_set_txq_props(ah, q, qinfo);332 333 return q;334}335EXPORT_SYMBOL(ath9k_hw_setuptxqueue);336 337static void ath9k_hw_clear_queue_interrupts(struct ath_hw *ah, u32 q)338{339 ah->txok_interrupt_mask &= ~(1 << q);340 ah->txerr_interrupt_mask &= ~(1 << q);341 ah->txdesc_interrupt_mask &= ~(1 << q);342 ah->txeol_interrupt_mask &= ~(1 << q);343 ah->txurn_interrupt_mask &= ~(1 << q);344}345 346bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)347{348 struct ath_common *common = ath9k_hw_common(ah);349 struct ath9k_tx_queue_info *qi;350 351 qi = &ah->txq[q];352 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {353 ath_dbg(common, QUEUE, "Release TXQ, inactive queue: %u\n", q);354 return false;355 }356 357 ath_dbg(common, QUEUE, "Release TX queue: %u\n", q);358 359 qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;360 ath9k_hw_clear_queue_interrupts(ah, q);361 ath9k_hw_set_txq_interrupts(ah, qi);362 363 return true;364}365EXPORT_SYMBOL(ath9k_hw_releasetxqueue);366 367bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)368{369 struct ath_common *common = ath9k_hw_common(ah);370 struct ath9k_tx_queue_info *qi;371 u32 cwMin, chanCwMin, value;372 373 qi = &ah->txq[q];374 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {375 ath_dbg(common, QUEUE, "Reset TXQ, inactive queue: %u\n", q);376 return true;377 }378 379 ath_dbg(common, QUEUE, "Reset TX queue: %u\n", q);380 381 if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {382 chanCwMin = INIT_CWMIN;383 384 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);385 } else386 cwMin = qi->tqi_cwmin;387 388 ENABLE_REGWRITE_BUFFER(ah);389 390 REG_WRITE(ah, AR_DLCL_IFS(q),391 SM(cwMin, AR_D_LCL_IFS_CWMIN) |392 SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |393 SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));394 395 REG_WRITE(ah, AR_DRETRY_LIMIT(q),396 SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |397 SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |398 SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));399 400 REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);401 402 if (AR_SREV_9340(ah) && !AR_SREV_9340_13_OR_LATER(ah))403 REG_WRITE(ah, AR_DMISC(q),404 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);405 else406 REG_WRITE(ah, AR_DMISC(q),407 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);408 409 if (qi->tqi_cbrPeriod) {410 REG_WRITE(ah, AR_QCBRCFG(q),411 SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |412 SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));413 REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR |414 (qi->tqi_cbrOverflowLimit ?415 AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));416 }417 if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {418 REG_WRITE(ah, AR_QRDYTIMECFG(q),419 SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |420 AR_Q_RDYTIMECFG_EN);421 }422 423 REG_WRITE(ah, AR_DCHNTIME(q),424 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |425 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));426 427 if (qi->tqi_burstTime428 && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE))429 REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY);430 431 if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE)432 REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);433 434 REGWRITE_BUFFER_FLUSH(ah);435 436 if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)437 REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN);438 439 switch (qi->tqi_type) {440 case ATH9K_TX_QUEUE_BEACON:441 ENABLE_REGWRITE_BUFFER(ah);442 443 REG_SET_BIT(ah, AR_QMISC(q),444 AR_Q_MISC_FSP_DBA_GATED445 | AR_Q_MISC_BEACON_USE446 | AR_Q_MISC_CBR_INCR_DIS1);447 448 REG_SET_BIT(ah, AR_DMISC(q),449 (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<450 AR_D_MISC_ARB_LOCKOUT_CNTRL_S)451 | AR_D_MISC_BEACON_USE452 | AR_D_MISC_POST_FR_BKOFF_DIS);453 454 REGWRITE_BUFFER_FLUSH(ah);455 456 /*457 * cwmin and cwmax should be 0 for beacon queue458 * but not for IBSS as we would create an imbalance459 * on beaconing fairness for participating nodes.460 */461 if (AR_SREV_9300_20_OR_LATER(ah) &&462 ah->opmode != NL80211_IFTYPE_ADHOC) {463 REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN)464 | SM(0, AR_D_LCL_IFS_CWMAX)465 | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));466 }467 break;468 case ATH9K_TX_QUEUE_CAB:469 ENABLE_REGWRITE_BUFFER(ah);470 471 REG_SET_BIT(ah, AR_QMISC(q),472 AR_Q_MISC_FSP_DBA_GATED473 | AR_Q_MISC_CBR_INCR_DIS1474 | AR_Q_MISC_CBR_INCR_DIS0);475 value = (qi->tqi_readyTime -476 (ah->config.sw_beacon_response_time -477 ah->config.dma_beacon_response_time)) * 1024;478 REG_WRITE(ah, AR_QRDYTIMECFG(q),479 value | AR_Q_RDYTIMECFG_EN);480 REG_SET_BIT(ah, AR_DMISC(q),481 (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<482 AR_D_MISC_ARB_LOCKOUT_CNTRL_S));483 484 REGWRITE_BUFFER_FLUSH(ah);485 486 break;487 case ATH9K_TX_QUEUE_PSPOLL:488 REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1);489 break;490 case ATH9K_TX_QUEUE_UAPSD:491 REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS);492 break;493 default:494 break;495 }496 497 if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {498 REG_SET_BIT(ah, AR_DMISC(q),499 SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,500 AR_D_MISC_ARB_LOCKOUT_CNTRL) |501 AR_D_MISC_POST_FR_BKOFF_DIS);502 }503 504 if (AR_SREV_9300_20_OR_LATER(ah))505 REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);506 507 ath9k_hw_clear_queue_interrupts(ah, q);508 if (qi->tqi_qflags & TXQ_FLAG_TXINT_ENABLE) {509 ah->txok_interrupt_mask |= 1 << q;510 ah->txerr_interrupt_mask |= 1 << q;511 }512 if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)513 ah->txdesc_interrupt_mask |= 1 << q;514 if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)515 ah->txeol_interrupt_mask |= 1 << q;516 if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)517 ah->txurn_interrupt_mask |= 1 << q;518 ath9k_hw_set_txq_interrupts(ah, qi);519 520 return true;521}522EXPORT_SYMBOL(ath9k_hw_resettxqueue);523 524int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,525 struct ath_rx_status *rs)526{527 struct ar5416_desc ads;528 struct ar5416_desc *adsp = AR5416DESC(ds);529 u32 phyerr;530 531 if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)532 return -EINPROGRESS;533 534 ads.u.rx = adsp->u.rx;535 536 rs->rs_status = 0;537 rs->rs_flags = 0;538 rs->enc_flags = 0;539 rs->bw = RATE_INFO_BW_20;540 541 rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen;542 rs->rs_tstamp = ads.AR_RcvTimestamp;543 544 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {545 rs->rs_rssi = ATH9K_RSSI_BAD;546 rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;547 rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;548 rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;549 rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;550 rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;551 rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;552 } else {553 rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);554 rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,555 AR_RxRSSIAnt00);556 rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,557 AR_RxRSSIAnt01);558 rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,559 AR_RxRSSIAnt02);560 rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,561 AR_RxRSSIAnt10);562 rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,563 AR_RxRSSIAnt11);564 rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,565 AR_RxRSSIAnt12);566 }567 if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)568 rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);569 else570 rs->rs_keyix = ATH9K_RXKEYIX_INVALID;571 572 rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);573 rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;574 575 rs->rs_firstaggr = (ads.ds_rxstatus8 & AR_RxFirstAggr) ? 1 : 0;576 rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;577 rs->rs_moreaggr = (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;578 rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);579 580 /* directly mapped flags for ieee80211_rx_status */581 rs->enc_flags |=582 (ads.ds_rxstatus3 & AR_GI) ? RX_ENC_FLAG_SHORT_GI : 0;583 rs->bw = (ads.ds_rxstatus3 & AR_2040) ? RATE_INFO_BW_40 :584 RATE_INFO_BW_20;585 if (AR_SREV_9280_20_OR_LATER(ah))586 rs->enc_flags |=587 (ads.ds_rxstatus3 & AR_STBC) ?588 /* we can only Nss=1 STBC */589 (1 << RX_ENC_FLAG_STBC_SHIFT) : 0;590 591 if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)592 rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;593 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)594 rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;595 if (ads.ds_rxstatus8 & AR_DecryptBusyErr)596 rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;597 598 if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {599 /*600 * Treat these errors as mutually exclusive to avoid spurious601 * extra error reports from the hardware. If a CRC error is602 * reported, then decryption and MIC errors are irrelevant,603 * the frame is going to be dropped either way604 */605 if (ads.ds_rxstatus8 & AR_PHYErr) {606 rs->rs_status |= ATH9K_RXERR_PHY;607 phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);608 rs->rs_phyerr = phyerr;609 } else if (ads.ds_rxstatus8 & AR_CRCErr)610 rs->rs_status |= ATH9K_RXERR_CRC;611 else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)612 rs->rs_status |= ATH9K_RXERR_DECRYPT;613 else if (ads.ds_rxstatus8 & AR_MichaelErr)614 rs->rs_status |= ATH9K_RXERR_MIC;615 } else {616 if (ads.ds_rxstatus8 &617 (AR_CRCErr | AR_PHYErr | AR_DecryptCRCErr | AR_MichaelErr))618 rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;619 620 /* Only up to MCS16 supported, everything above is invalid */621 if (rs->rs_rate >= 0x90)622 rs->rs_status |= ATH9K_RXERR_CORRUPT_DESC;623 }624 625 if (ads.ds_rxstatus8 & AR_KeyMiss)626 rs->rs_status |= ATH9K_RXERR_KEYMISS;627 628 return 0;629}630EXPORT_SYMBOL(ath9k_hw_rxprocdesc);631 632/*633 * This can stop or re-enables RX.634 *635 * If bool is set this will kill any frame which is currently being636 * transferred between the MAC and baseband and also prevent any new637 * frames from getting started.638 */639bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)640{641 u32 reg;642 643 if (set) {644 REG_SET_BIT(ah, AR_DIAG_SW,645 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));646 647 if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,648 0, AH_WAIT_TIMEOUT)) {649 REG_CLR_BIT(ah, AR_DIAG_SW,650 (AR_DIAG_RX_DIS |651 AR_DIAG_RX_ABORT));652 653 reg = REG_READ(ah, AR_OBS_BUS_1);654 ath_err(ath9k_hw_common(ah),655 "RX failed to go idle in 10 ms RXSM=0x%x\n",656 reg);657 658 return false;659 }660 } else {661 REG_CLR_BIT(ah, AR_DIAG_SW,662 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));663 }664 665 return true;666}667EXPORT_SYMBOL(ath9k_hw_setrxabort);668 669void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)670{671 REG_WRITE(ah, AR_RXDP, rxdp);672}673EXPORT_SYMBOL(ath9k_hw_putrxbuf);674 675void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning)676{677 ath9k_enable_mib_counters(ah);678 679 ath9k_ani_reset(ah, is_scanning);680 681 REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));682}683EXPORT_SYMBOL(ath9k_hw_startpcureceive);684 685void ath9k_hw_abortpcurecv(struct ath_hw *ah)686{687 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);688 689 ath9k_hw_disable_mib_counters(ah);690}691EXPORT_SYMBOL(ath9k_hw_abortpcurecv);692 693bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset)694{695#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */696 struct ath_common *common = ath9k_hw_common(ah);697 u32 mac_status, last_mac_status = 0;698 int i;699 700 /* Enable access to the DMA observation bus */701 REG_WRITE(ah, AR_MACMISC,702 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |703 (AR_MACMISC_MISC_OBS_BUS_1 <<704 AR_MACMISC_MISC_OBS_BUS_MSB_S)));705 706 REG_WRITE(ah, AR_CR, AR_CR_RXD);707 708 /* Wait for rx enable bit to go low */709 for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {710 if ((REG_READ(ah, AR_CR) & AR_CR_RXE(ah)) == 0)711 break;712 713 if (!AR_SREV_9300_20_OR_LATER(ah)) {714 mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;715 if (mac_status == 0x1c0 && mac_status == last_mac_status) {716 *reset = true;717 break;718 }719 720 last_mac_status = mac_status;721 }722 723 udelay(AH_TIME_QUANTUM);724 }725 726 if (i == 0) {727 ath_err(common,728 "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",729 AH_RX_STOP_DMA_TIMEOUT / 1000,730 REG_READ(ah, AR_CR),731 REG_READ(ah, AR_DIAG_SW),732 REG_READ(ah, AR_DMADBG_7));733 return false;734 } else {735 return true;736 }737 738#undef AH_RX_STOP_DMA_TIMEOUT739}740EXPORT_SYMBOL(ath9k_hw_stopdmarecv);741 742int ath9k_hw_beaconq_setup(struct ath_hw *ah)743{744 struct ath9k_tx_queue_info qi;745 746 memset(&qi, 0, sizeof(qi));747 qi.tqi_aifs = 1;748 qi.tqi_cwmin = 0;749 qi.tqi_cwmax = 0;750 751 if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)752 qi.tqi_qflags = TXQ_FLAG_TXINT_ENABLE;753 754 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);755}756EXPORT_SYMBOL(ath9k_hw_beaconq_setup);757 758bool ath9k_hw_intrpend(struct ath_hw *ah)759{760 u32 host_isr;761 762 if (AR_SREV_9100(ah))763 return true;764 765 host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE(ah));766 767 if (((host_isr & AR_INTR_MAC_IRQ) ||768 (host_isr & AR_INTR_ASYNC_MASK_MCI)) &&769 (host_isr != AR_INTR_SPURIOUS))770 return true;771 772 host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE(ah));773 if ((host_isr & AR_INTR_SYNC_DEFAULT)774 && (host_isr != AR_INTR_SPURIOUS))775 return true;776 777 return false;778}779EXPORT_SYMBOL(ath9k_hw_intrpend);780 781void ath9k_hw_kill_interrupts(struct ath_hw *ah)782{783 struct ath_common *common = ath9k_hw_common(ah);784 785 ath_dbg(common, INTERRUPT, "disable IER\n");786 REG_WRITE(ah, AR_IER, AR_IER_DISABLE);787 (void) REG_READ(ah, AR_IER);788 if (!AR_SREV_9100(ah)) {789 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE(ah), 0);790 (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE(ah));791 792 REG_WRITE(ah, AR_INTR_SYNC_ENABLE(ah), 0);793 (void) REG_READ(ah, AR_INTR_SYNC_ENABLE(ah));794 }795}796EXPORT_SYMBOL(ath9k_hw_kill_interrupts);797 798void ath9k_hw_disable_interrupts(struct ath_hw *ah)799{800 if (!(ah->imask & ATH9K_INT_GLOBAL))801 atomic_set(&ah->intr_ref_cnt, -1);802 else803 atomic_dec(&ah->intr_ref_cnt);804 805 ath9k_hw_kill_interrupts(ah);806}807EXPORT_SYMBOL(ath9k_hw_disable_interrupts);808 809static void __ath9k_hw_enable_interrupts(struct ath_hw *ah)810{811 struct ath_common *common = ath9k_hw_common(ah);812 u32 sync_default = AR_INTR_SYNC_DEFAULT;813 u32 async_mask;814 815 if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||816 AR_SREV_9561(ah))817 sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;818 819 async_mask = AR_INTR_MAC_IRQ;820 821 if (ah->imask & ATH9K_INT_MCI)822 async_mask |= AR_INTR_ASYNC_MASK_MCI;823 824 ath_dbg(common, INTERRUPT, "enable IER\n");825 REG_WRITE(ah, AR_IER, AR_IER_ENABLE);826 if (!AR_SREV_9100(ah)) {827 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE(ah), async_mask);828 REG_WRITE(ah, AR_INTR_ASYNC_MASK(ah), async_mask);829 830 REG_WRITE(ah, AR_INTR_SYNC_ENABLE(ah), sync_default);831 REG_WRITE(ah, AR_INTR_SYNC_MASK(ah), sync_default);832 }833 ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",834 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));835 836 if (ah->msi_enabled) {837 u32 _msi_reg = 0;838 u32 i = 0;839 u32 msi_pend_addr_mask = AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64;840 841 ath_dbg(ath9k_hw_common(ah), INTERRUPT,842 "Enabling MSI, msi_mask=0x%X\n", ah->msi_mask);843 844 REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE(ah), ah->msi_mask);845 REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK(ah), ah->msi_mask);846 ath_dbg(ath9k_hw_common(ah), INTERRUPT,847 "AR_INTR_PRIO_ASYNC_ENABLE=0x%X, AR_INTR_PRIO_ASYNC_MASK=0x%X\n",848 REG_READ(ah, AR_INTR_PRIO_ASYNC_ENABLE(ah)),849 REG_READ(ah, AR_INTR_PRIO_ASYNC_MASK(ah)));850 851 if (ah->msi_reg == 0)852 ah->msi_reg = REG_READ(ah, AR_PCIE_MSI(ah));853 854 ath_dbg(ath9k_hw_common(ah), INTERRUPT,855 "AR_PCIE_MSI=0x%X, ah->msi_reg = 0x%X\n",856 AR_PCIE_MSI(ah), ah->msi_reg);857 858 i = 0;859 do {860 REG_WRITE(ah, AR_PCIE_MSI(ah),861 (ah->msi_reg | AR_PCIE_MSI_ENABLE)862 & msi_pend_addr_mask);863 _msi_reg = REG_READ(ah, AR_PCIE_MSI(ah));864 i++;865 } while ((_msi_reg & AR_PCIE_MSI_ENABLE) == 0 && i < 200);866 867 if (i >= 200)868 ath_err(ath9k_hw_common(ah),869 "%s: _msi_reg = 0x%X\n",870 __func__, _msi_reg);871 }872}873 874void ath9k_hw_resume_interrupts(struct ath_hw *ah)875{876 struct ath_common *common = ath9k_hw_common(ah);877 878 if (!(ah->imask & ATH9K_INT_GLOBAL))879 return;880 881 if (atomic_read(&ah->intr_ref_cnt) != 0) {882 ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",883 atomic_read(&ah->intr_ref_cnt));884 return;885 }886 887 __ath9k_hw_enable_interrupts(ah);888}889EXPORT_SYMBOL(ath9k_hw_resume_interrupts);890 891void ath9k_hw_enable_interrupts(struct ath_hw *ah)892{893 struct ath_common *common = ath9k_hw_common(ah);894 895 if (!(ah->imask & ATH9K_INT_GLOBAL))896 return;897 898 if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {899 ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n",900 atomic_read(&ah->intr_ref_cnt));901 return;902 }903 904 __ath9k_hw_enable_interrupts(ah);905}906EXPORT_SYMBOL(ath9k_hw_enable_interrupts);907 908void ath9k_hw_set_interrupts(struct ath_hw *ah)909{910 enum ath9k_int ints = ah->imask;911 u32 mask, mask2;912 struct ath9k_hw_capabilities *pCap = &ah->caps;913 struct ath_common *common = ath9k_hw_common(ah);914 915 if (!(ints & ATH9K_INT_GLOBAL))916 ath9k_hw_disable_interrupts(ah);917 918 if (ah->msi_enabled) {919 ath_dbg(common, INTERRUPT, "Clearing AR_INTR_PRIO_ASYNC_ENABLE\n");920 921 REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE(ah), 0);922 REG_READ(ah, AR_INTR_PRIO_ASYNC_ENABLE(ah));923 }924 925 ath_dbg(common, INTERRUPT, "New interrupt mask 0x%x\n", ints);926 927 mask = ints & ATH9K_INT_COMMON;928 mask2 = 0;929 930 ah->msi_mask = 0;931 if (ints & ATH9K_INT_TX) {932 ah->msi_mask |= AR_INTR_PRIO_TX;933 if (ah->config.tx_intr_mitigation)934 mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;935 else {936 if (ah->txok_interrupt_mask)937 mask |= AR_IMR_TXOK;938 if (ah->txdesc_interrupt_mask)939 mask |= AR_IMR_TXDESC;940 }941 if (ah->txerr_interrupt_mask)942 mask |= AR_IMR_TXERR;943 if (ah->txeol_interrupt_mask)944 mask |= AR_IMR_TXEOL;945 }946 if (ints & ATH9K_INT_RX) {947 ah->msi_mask |= AR_INTR_PRIO_RXLP | AR_INTR_PRIO_RXHP;948 if (AR_SREV_9300_20_OR_LATER(ah)) {949 mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;950 if (ah->config.rx_intr_mitigation) {951 mask &= ~AR_IMR_RXOK_LP;952 mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;953 } else {954 mask |= AR_IMR_RXOK_LP;955 }956 } else {957 if (ah->config.rx_intr_mitigation)958 mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;959 else960 mask |= AR_IMR_RXOK | AR_IMR_RXDESC;961 }962 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))963 mask |= AR_IMR_GENTMR;964 }965 966 if (ints & ATH9K_INT_GENTIMER)967 mask |= AR_IMR_GENTMR;968 969 if (ints & (ATH9K_INT_BMISC)) {970 mask |= AR_IMR_BCNMISC;971 if (ints & ATH9K_INT_TIM)972 mask2 |= AR_IMR_S2_TIM;973 if (ints & ATH9K_INT_DTIM)974 mask2 |= AR_IMR_S2_DTIM;975 if (ints & ATH9K_INT_DTIMSYNC)976 mask2 |= AR_IMR_S2_DTIMSYNC;977 if (ints & ATH9K_INT_CABEND)978 mask2 |= AR_IMR_S2_CABEND;979 if (ints & ATH9K_INT_TSFOOR)980 mask2 |= AR_IMR_S2_TSFOOR;981 }982 983 if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {984 mask |= AR_IMR_BCNMISC;985 if (ints & ATH9K_INT_GTT)986 mask2 |= AR_IMR_S2_GTT;987 if (ints & ATH9K_INT_CST)988 mask2 |= AR_IMR_S2_CST;989 }990 991 if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) {992 if (ints & ATH9K_INT_BB_WATCHDOG) {993 mask |= AR_IMR_BCNMISC;994 mask2 |= AR_IMR_S2_BB_WATCHDOG;995 }996 }997 998 ath_dbg(common, INTERRUPT, "new IMR 0x%x\n", mask);999 REG_WRITE(ah, AR_IMR, mask);1000 ah->imrs2_reg &= ~(AR_IMR_S2_TIM |1001 AR_IMR_S2_DTIM |1002 AR_IMR_S2_DTIMSYNC |1003 AR_IMR_S2_CABEND |1004 AR_IMR_S2_CABTO |1005 AR_IMR_S2_TSFOOR |1006 AR_IMR_S2_GTT |1007 AR_IMR_S2_CST);1008 1009 if (ah->config.hw_hang_checks & HW_BB_WATCHDOG) {1010 if (ints & ATH9K_INT_BB_WATCHDOG)1011 ah->imrs2_reg &= ~AR_IMR_S2_BB_WATCHDOG;1012 }1013 1014 ah->imrs2_reg |= mask2;1015 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);1016 1017 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {1018 if (ints & ATH9K_INT_TIM_TIMER)1019 REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);1020 else1021 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);1022 }1023 1024 return;1025}1026EXPORT_SYMBOL(ath9k_hw_set_interrupts);1027 1028#define ATH9K_HW_MAX_DCU 101029#define ATH9K_HW_SLICE_PER_DCU 161030#define ATH9K_HW_BIT_IN_SLICE 161031void ath9k_hw_set_tx_filter(struct ath_hw *ah, u8 destidx, bool set)1032{1033 int dcu_idx;1034 u32 filter;1035 1036 for (dcu_idx = 0; dcu_idx < 10; dcu_idx++) {1037 filter = SM(set, AR_D_TXBLK_WRITE_COMMAND);1038 filter |= SM(dcu_idx, AR_D_TXBLK_WRITE_DCU);1039 filter |= SM((destidx / ATH9K_HW_SLICE_PER_DCU),1040 AR_D_TXBLK_WRITE_SLICE);1041 filter |= BIT(destidx % ATH9K_HW_BIT_IN_SLICE);1042 ath_dbg(ath9k_hw_common(ah), PS,1043 "DCU%d staid %d set %d txfilter %08x\n",1044 dcu_idx, destidx, set, filter);1045 REG_WRITE(ah, AR_D_TXBLK_BASE, filter);1046 }1047}1048EXPORT_SYMBOL(ath9k_hw_set_tx_filter);1049