1 /* 2 * Copyright (c) 2010-2011 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 #include "hw.h" 17 #include "ar9003_mac.h" 18 19 static void ar9003_hw_rx_enable(struct ath_hw *hw) 20 { 21 REG_WRITE(hw, AR_CR, 0); 22 } 23 24 static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) 25 { 26 int checksum; 27 28 checksum = ads->info + ads->link 29 + ads->data0 + ads->ctl3 30 + ads->data1 + ads->ctl5 31 + ads->data2 + ads->ctl7 32 + ads->data3 + ads->ctl9; 33 34 return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum; 35 } 36 37 static void ar9003_hw_set_desc_link(void *ds, u32 ds_link) 38 { 39 struct ar9003_txc *ads = ds; 40 41 ads->link = ds_link; 42 ads->ctl10 &= ~AR_TxPtrChkSum; 43 ads->ctl10 |= ar9003_calc_ptr_chksum(ads); 44 } 45 46 static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) 47 { 48 u32 isr = 0; 49 u32 mask2 = 0; 50 struct ath9k_hw_capabilities *pCap = &ah->caps; 51 u32 sync_cause = 0; 52 struct ath_common *common = ath9k_hw_common(ah); 53 54 if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { 55 if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) 56 == AR_RTC_STATUS_ON) 57 isr = REG_READ(ah, AR_ISR); 58 } 59 60 sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; 61 62 *masked = 0; 63 64 if (!isr && !sync_cause) 65 return false; 66 67 if (isr) { 68 if (isr & AR_ISR_BCNMISC) { 69 u32 isr2; 70 isr2 = REG_READ(ah, AR_ISR_S2); 71 72 mask2 |= ((isr2 & AR_ISR_S2_TIM) >> 73 MAP_ISR_S2_TIM); 74 mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> 75 MAP_ISR_S2_DTIM); 76 mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> 77 MAP_ISR_S2_DTIMSYNC); 78 mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> 79 MAP_ISR_S2_CABEND); 80 mask2 |= ((isr2 & AR_ISR_S2_GTT) << 81 MAP_ISR_S2_GTT); 82 mask2 |= ((isr2 & AR_ISR_S2_CST) << 83 MAP_ISR_S2_CST); 84 mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> 85 MAP_ISR_S2_TSFOOR); 86 mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >> 87 MAP_ISR_S2_BB_WATCHDOG); 88 89 if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 90 REG_WRITE(ah, AR_ISR_S2, isr2); 91 isr &= ~AR_ISR_BCNMISC; 92 } 93 } 94 95 if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) 96 isr = REG_READ(ah, AR_ISR_RAC); 97 98 if (isr == 0xffffffff) { 99 *masked = 0; 100 return false; 101 } 102 103 *masked = isr & ATH9K_INT_COMMON; 104 105 if (ah->config.rx_intr_mitigation) 106 if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) 107 *masked |= ATH9K_INT_RXLP; 108 109 if (ah->config.tx_intr_mitigation) 110 if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) 111 *masked |= ATH9K_INT_TX; 112 113 if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) 114 *masked |= ATH9K_INT_RXLP; 115 116 if (isr & AR_ISR_HP_RXOK) 117 *masked |= ATH9K_INT_RXHP; 118 119 if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) { 120 *masked |= ATH9K_INT_TX; 121 122 if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 123 u32 s0, s1; 124 s0 = REG_READ(ah, AR_ISR_S0); 125 REG_WRITE(ah, AR_ISR_S0, s0); 126 s1 = REG_READ(ah, AR_ISR_S1); 127 REG_WRITE(ah, AR_ISR_S1, s1); 128 129 isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | 130 AR_ISR_TXEOL); 131 } 132 } 133 134 if (isr & AR_ISR_GENTMR) { 135 u32 s5; 136 137 if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) 138 s5 = REG_READ(ah, AR_ISR_S5_S); 139 else 140 s5 = REG_READ(ah, AR_ISR_S5); 141 142 ah->intr_gen_timer_trigger = 143 MS(s5, AR_ISR_S5_GENTIMER_TRIG); 144 145 ah->intr_gen_timer_thresh = 146 MS(s5, AR_ISR_S5_GENTIMER_THRESH); 147 148 if (ah->intr_gen_timer_trigger) 149 *masked |= ATH9K_INT_GENTIMER; 150 151 if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 152 REG_WRITE(ah, AR_ISR_S5, s5); 153 isr &= ~AR_ISR_GENTMR; 154 } 155 156 } 157 158 *masked |= mask2; 159 160 if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 161 REG_WRITE(ah, AR_ISR, isr); 162 163 (void) REG_READ(ah, AR_ISR); 164 } 165 166 if (*masked & ATH9K_INT_BB_WATCHDOG) 167 ar9003_hw_bb_watchdog_read(ah); 168 } 169 170 if (sync_cause) { 171 if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { 172 REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); 173 REG_WRITE(ah, AR_RC, 0); 174 *masked |= ATH9K_INT_FATAL; 175 } 176 177 if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) 178 ath_dbg(common, ATH_DBG_INTERRUPT, 179 "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); 180 181 REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); 182 (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); 183 184 } 185 return true; 186 } 187 188 static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, 189 bool is_firstseg, bool is_lastseg, 190 const void *ds0, dma_addr_t buf_addr, 191 unsigned int qcu) 192 { 193 struct ar9003_txc *ads = (struct ar9003_txc *) ds; 194 unsigned int descid = 0; 195 196 ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) | 197 (1 << AR_TxRxDesc_S) | 198 (1 << AR_CtrlStat_S) | 199 (qcu << AR_TxQcuNum_S) | 0x17; 200 201 ads->data0 = buf_addr; 202 ads->data1 = 0; 203 ads->data2 = 0; 204 ads->data3 = 0; 205 206 ads->ctl3 = (seglen << AR_BufLen_S); 207 ads->ctl3 &= AR_BufLen; 208 209 /* Fill in pointer checksum and descriptor id */ 210 ads->ctl10 = ar9003_calc_ptr_chksum(ads); 211 ads->ctl10 |= (descid << AR_TxDescId_S); 212 213 if (is_firstseg) { 214 ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore); 215 } else if (is_lastseg) { 216 ads->ctl11 = 0; 217 ads->ctl12 = 0; 218 ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13; 219 ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14; 220 } else { 221 /* XXX Intermediate descriptor in a multi-descriptor frame.*/ 222 ads->ctl11 = 0; 223 ads->ctl12 = AR_TxMore; 224 ads->ctl13 = 0; 225 ads->ctl14 = 0; 226 } 227 } 228 229 static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, 230 struct ath_tx_status *ts) 231 { 232 struct ar9003_txc *txc = (struct ar9003_txc *) ds; 233 struct ar9003_txs *ads; 234 u32 status; 235 236 ads = &ah->ts_ring[ah->ts_tail]; 237 238 status = ACCESS_ONCE(ads->status8); 239 if ((status & AR_TxDone) == 0) 240 return -EINPROGRESS; 241 242 ts->qid = MS(ads->ds_info, AR_TxQcuNum); 243 if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid)) 244 ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; 245 else 246 return -ENOENT; 247 248 if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || 249 (MS(ads->ds_info, AR_TxRxDesc) != 1)) { 250 ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, 251 "Tx Descriptor error %x\n", ads->ds_info); 252 memset(ads, 0, sizeof(*ads)); 253 return -EIO; 254 } 255 256 if (status & AR_TxOpExceeded) 257 ts->ts_status |= ATH9K_TXERR_XTXOP; 258 ts->ts_rateindex = MS(status, AR_FinalTxIdx); 259 ts->ts_seqnum = MS(status, AR_SeqNum); 260 ts->tid = MS(status, AR_TxTid); 261 262 ts->desc_id = MS(ads->status1, AR_TxDescId); 263 ts->ts_tstamp = ads->status4; 264 ts->ts_status = 0; 265 ts->ts_flags = 0; 266 267 status = ACCESS_ONCE(ads->status2); 268 ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); 269 ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); 270 ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); 271 if (status & AR_TxBaStatus) { 272 ts->ts_flags |= ATH9K_TX_BA; 273 ts->ba_low = ads->status5; 274 ts->ba_high = ads->status6; 275 } 276 277 status = ACCESS_ONCE(ads->status3); 278 if (status & AR_ExcessiveRetries) 279 ts->ts_status |= ATH9K_TXERR_XRETRY; 280 if (status & AR_Filtered) 281 ts->ts_status |= ATH9K_TXERR_FILT; 282 if (status & AR_FIFOUnderrun) { 283 ts->ts_status |= ATH9K_TXERR_FIFO; 284 ath9k_hw_updatetxtriglevel(ah, true); 285 } 286 if (status & AR_TxTimerExpired) 287 ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; 288 if (status & AR_DescCfgErr) 289 ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; 290 if (status & AR_TxDataUnderrun) { 291 ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; 292 ath9k_hw_updatetxtriglevel(ah, true); 293 } 294 if (status & AR_TxDelimUnderrun) { 295 ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; 296 ath9k_hw_updatetxtriglevel(ah, true); 297 } 298 ts->ts_shortretry = MS(status, AR_RTSFailCnt); 299 ts->ts_longretry = MS(status, AR_DataFailCnt); 300 ts->ts_virtcol = MS(status, AR_VirtRetryCnt); 301 302 status = ACCESS_ONCE(ads->status7); 303 ts->ts_rssi = MS(status, AR_TxRSSICombined); 304 ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); 305 ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); 306 ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); 307 308 memset(ads, 0, sizeof(*ads)); 309 310 return 0; 311 } 312 313 static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, 314 u32 pktlen, enum ath9k_pkt_type type, u32 txpower, 315 u32 keyIx, enum ath9k_key_type keyType, u32 flags) 316 { 317 struct ar9003_txc *ads = (struct ar9003_txc *) ds; 318 319 if (txpower > ah->txpower_limit) 320 txpower = ah->txpower_limit; 321 322 if (txpower > 63) 323 txpower = 63; 324 325 ads->ctl11 = (pktlen & AR_FrameLen) 326 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) 327 | SM(txpower, AR_XmitPower) 328 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) 329 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) 330 | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); 331 332 ads->ctl12 = 333 (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) 334 | SM(type, AR_FrameType) 335 | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) 336 | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) 337 | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); 338 339 ads->ctl17 = SM(keyType, AR_EncrType) | 340 (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); 341 ads->ctl18 = 0; 342 ads->ctl19 = AR_Not_Sounding; 343 344 ads->ctl20 = 0; 345 ads->ctl21 = 0; 346 ads->ctl22 = 0; 347 } 348 349 static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) 350 { 351 struct ar9003_txc *ads = (struct ar9003_txc *) ds; 352 353 if (val) 354 ads->ctl11 |= AR_ClrDestMask; 355 else 356 ads->ctl11 &= ~AR_ClrDestMask; 357 } 358 359 static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, 360 void *lastds, 361 u32 durUpdateEn, u32 rtsctsRate, 362 u32 rtsctsDuration, 363 struct ath9k_11n_rate_series series[], 364 u32 nseries, u32 flags) 365 { 366 struct ar9003_txc *ads = (struct ar9003_txc *) ds; 367 struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds; 368 u_int32_t ctl11; 369 370 if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { 371 ctl11 = ads->ctl11; 372 373 if (flags & ATH9K_TXDESC_RTSENA) { 374 ctl11 &= ~AR_CTSEnable; 375 ctl11 |= AR_RTSEnable; 376 } else { 377 ctl11 &= ~AR_RTSEnable; 378 ctl11 |= AR_CTSEnable; 379 } 380 381 ads->ctl11 = ctl11; 382 } else { 383 ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable)); 384 } 385 386 ads->ctl13 = set11nTries(series, 0) 387 | set11nTries(series, 1) 388 | set11nTries(series, 2) 389 | set11nTries(series, 3) 390 | (durUpdateEn ? AR_DurUpdateEna : 0) 391 | SM(0, AR_BurstDur); 392 393 ads->ctl14 = set11nRate(series, 0) 394 | set11nRate(series, 1) 395 | set11nRate(series, 2) 396 | set11nRate(series, 3); 397 398 ads->ctl15 = set11nPktDurRTSCTS(series, 0) 399 | set11nPktDurRTSCTS(series, 1); 400 401 ads->ctl16 = set11nPktDurRTSCTS(series, 2) 402 | set11nPktDurRTSCTS(series, 3); 403 404 ads->ctl18 = set11nRateFlags(series, 0) 405 | set11nRateFlags(series, 1) 406 | set11nRateFlags(series, 2) 407 | set11nRateFlags(series, 3) 408 | SM(rtsctsRate, AR_RTSCTSRate); 409 ads->ctl19 = AR_Not_Sounding; 410 411 last_ads->ctl13 = ads->ctl13; 412 last_ads->ctl14 = ads->ctl14; 413 } 414 415 static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, 416 u32 aggrLen) 417 { 418 #define FIRST_DESC_NDELIMS 60 419 struct ar9003_txc *ads = (struct ar9003_txc *) ds; 420 421 ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); 422 423 if (ah->ent_mode & AR_ENT_OTP_MPSD) { 424 u32 ctl17, ndelim; 425 /* 426 * Add delimiter when using RTS/CTS with aggregation 427 * and non enterprise AR9003 card 428 */ 429 ctl17 = ads->ctl17; 430 ndelim = MS(ctl17, AR_PadDelim); 431 432 if (ndelim < FIRST_DESC_NDELIMS) { 433 aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4; 434 ndelim = FIRST_DESC_NDELIMS; 435 } 436 437 ctl17 &= ~AR_AggrLen; 438 ctl17 |= SM(aggrLen, AR_AggrLen); 439 440 ctl17 &= ~AR_PadDelim; 441 ctl17 |= SM(ndelim, AR_PadDelim); 442 443 ads->ctl17 = ctl17; 444 } else { 445 ads->ctl17 &= ~AR_AggrLen; 446 ads->ctl17 |= SM(aggrLen, AR_AggrLen); 447 } 448 } 449 450 static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, 451 u32 numDelims) 452 { 453 struct ar9003_txc *ads = (struct ar9003_txc *) ds; 454 unsigned int ctl17; 455 456 ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); 457 458 /* 459 * We use a stack variable to manipulate ctl6 to reduce uncached 460 * read modify, modfiy, write. 461 */ 462 ctl17 = ads->ctl17; 463 ctl17 &= ~AR_PadDelim; 464 ctl17 |= SM(numDelims, AR_PadDelim); 465 ads->ctl17 = ctl17; 466 } 467 468 static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) 469 { 470 struct ar9003_txc *ads = (struct ar9003_txc *) ds; 471 472 ads->ctl12 |= AR_IsAggr; 473 ads->ctl12 &= ~AR_MoreAggr; 474 ads->ctl17 &= ~AR_PadDelim; 475 } 476 477 static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) 478 { 479 struct ar9003_txc *ads = (struct ar9003_txc *) ds; 480 481 ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); 482 } 483 484 void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) 485 { 486 struct ar9003_txc *ads = ds; 487 488 ads->ctl12 |= SM(chains, AR_PAPRDChainMask); 489 } 490 EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc); 491 492 void ar9003_hw_attach_mac_ops(struct ath_hw *hw) 493 { 494 struct ath_hw_ops *ops = ath9k_hw_ops(hw); 495 496 ops->rx_enable = ar9003_hw_rx_enable; 497 ops->set_desc_link = ar9003_hw_set_desc_link; 498 ops->get_isr = ar9003_hw_get_isr; 499 ops->fill_txdesc = ar9003_hw_fill_txdesc; 500 ops->proc_txdesc = ar9003_hw_proc_txdesc; 501 ops->set11n_txdesc = ar9003_hw_set11n_txdesc; 502 ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario; 503 ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first; 504 ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; 505 ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; 506 ops->clr11n_aggr = ar9003_hw_clr11n_aggr; 507 ops->set_clrdmask = ar9003_hw_set_clrdmask; 508 } 509 510 void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) 511 { 512 REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK); 513 } 514 EXPORT_SYMBOL(ath9k_hw_set_rx_bufsize); 515 516 void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, 517 enum ath9k_rx_qtype qtype) 518 { 519 if (qtype == ATH9K_RX_QUEUE_HP) 520 REG_WRITE(ah, AR_HP_RXDP, rxdp); 521 else 522 REG_WRITE(ah, AR_LP_RXDP, rxdp); 523 } 524 EXPORT_SYMBOL(ath9k_hw_addrxbuf_edma); 525 526 int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, 527 void *buf_addr) 528 { 529 struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr; 530 unsigned int phyerr; 531 532 /* TODO: byte swap on big endian for ar9300_10 */ 533 534 if ((rxsp->status11 & AR_RxDone) == 0) 535 return -EINPROGRESS; 536 537 if (MS(rxsp->ds_info, AR_DescId) != 0x168c) 538 return -EINVAL; 539 540 if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) 541 return -EINPROGRESS; 542 543 if (!rxs) 544 return 0; 545 546 rxs->rs_status = 0; 547 rxs->rs_flags = 0; 548 549 rxs->rs_datalen = rxsp->status2 & AR_DataLen; 550 rxs->rs_tstamp = rxsp->status3; 551 552 /* XXX: Keycache */ 553 rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined); 554 rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00); 555 rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01); 556 rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02); 557 rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10); 558 rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11); 559 rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12); 560 561 if (rxsp->status11 & AR_RxKeyIdxValid) 562 rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx); 563 else 564 rxs->rs_keyix = ATH9K_RXKEYIX_INVALID; 565 566 rxs->rs_rate = MS(rxsp->status1, AR_RxRate); 567 rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0; 568 569 rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; 570 rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; 571 rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); 572 rxs->rs_flags = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0; 573 rxs->rs_flags |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0; 574 575 rxs->evm0 = rxsp->status6; 576 rxs->evm1 = rxsp->status7; 577 rxs->evm2 = rxsp->status8; 578 rxs->evm3 = rxsp->status9; 579 rxs->evm4 = (rxsp->status10 & 0xffff); 580 581 if (rxsp->status11 & AR_PreDelimCRCErr) 582 rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; 583 584 if (rxsp->status11 & AR_PostDelimCRCErr) 585 rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST; 586 587 if (rxsp->status11 & AR_DecryptBusyErr) 588 rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; 589 590 if ((rxsp->status11 & AR_RxFrameOK) == 0) { 591 /* 592 * AR_CRCErr will bet set to true if we're on the last 593 * subframe and the AR_PostDelimCRCErr is caught. 594 * In a way this also gives us a guarantee that when 595 * (!(AR_CRCErr) && (AR_PostDelimCRCErr)) we cannot 596 * possibly be reviewing the last subframe. AR_CRCErr 597 * is the CRC of the actual data. 598 */ 599 if (rxsp->status11 & AR_CRCErr) 600 rxs->rs_status |= ATH9K_RXERR_CRC; 601 else if (rxsp->status11 & AR_PHYErr) { 602 phyerr = MS(rxsp->status11, AR_PHYErrCode); 603 /* 604 * If we reach a point here where AR_PostDelimCRCErr is 605 * true it implies we're *not* on the last subframe. In 606 * in that case that we know already that the CRC of 607 * the frame was OK, and MAC would send an ACK for that 608 * subframe, even if we did get a phy error of type 609 * ATH9K_PHYERR_OFDM_RESTART. This is only applicable 610 * to frame that are prior to the last subframe. 611 * The AR_PostDelimCRCErr is the CRC for the MPDU 612 * delimiter, which contains the 4 reserved bits, 613 * the MPDU length (12 bits), and follows the MPDU 614 * delimiter for an A-MPDU subframe (0x4E = 'N' ASCII). 615 */ 616 if ((phyerr == ATH9K_PHYERR_OFDM_RESTART) && 617 (rxsp->status11 & AR_PostDelimCRCErr)) { 618 rxs->rs_phyerr = 0; 619 } else { 620 rxs->rs_status |= ATH9K_RXERR_PHY; 621 rxs->rs_phyerr = phyerr; 622 } 623 624 } else if (rxsp->status11 & AR_DecryptCRCErr) 625 rxs->rs_status |= ATH9K_RXERR_DECRYPT; 626 else if (rxsp->status11 & AR_MichaelErr) 627 rxs->rs_status |= ATH9K_RXERR_MIC; 628 else if (rxsp->status11 & AR_KeyMiss) 629 rxs->rs_status |= ATH9K_RXERR_DECRYPT; 630 } 631 632 return 0; 633 } 634 EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma); 635 636 void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) 637 { 638 ah->ts_tail = 0; 639 640 memset((void *) ah->ts_ring, 0, 641 ah->ts_size * sizeof(struct ar9003_txs)); 642 643 ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, 644 "TS Start 0x%x End 0x%x Virt %p, Size %d\n", 645 ah->ts_paddr_start, ah->ts_paddr_end, 646 ah->ts_ring, ah->ts_size); 647 648 REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start); 649 REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end); 650 } 651 652 void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start, 653 u32 ts_paddr_start, 654 u8 size) 655 { 656 657 ah->ts_paddr_start = ts_paddr_start; 658 ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs)); 659 ah->ts_size = size; 660 ah->ts_ring = (struct ar9003_txs *) ts_start; 661 662 ath9k_hw_reset_txstatus_ring(ah); 663 } 664 EXPORT_SYMBOL(ath9k_hw_setup_statusring); 665