aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/mac.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c490
1 files changed, 193 insertions, 297 deletions
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 4a2060e5a777..7bbf502563bc 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -25,6 +25,8 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
25 ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, 25 ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
26 ah->txurn_interrupt_mask); 26 ah->txurn_interrupt_mask);
27 27
28 ENABLE_REGWRITE_BUFFER(ah);
29
28 REG_WRITE(ah, AR_IMR_S0, 30 REG_WRITE(ah, AR_IMR_S0,
29 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) 31 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
30 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); 32 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
@@ -35,6 +37,9 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
35 ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN; 37 ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
36 ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN); 38 ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
37 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); 39 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
40
41 REGWRITE_BUFFER_FLUSH(ah);
42 DISABLE_REGWRITE_BUFFER(ah);
38} 43}
39 44
40u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) 45u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
@@ -57,6 +62,18 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
57} 62}
58EXPORT_SYMBOL(ath9k_hw_txstart); 63EXPORT_SYMBOL(ath9k_hw_txstart);
59 64
65void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
66{
67 struct ar5416_desc *ads = AR5416DESC(ds);
68
69 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
70 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
71 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
72 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
73 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
74}
75EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
76
60u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) 77u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
61{ 78{
62 u32 npend; 79 u32 npend;
@@ -207,281 +224,6 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
207} 224}
208EXPORT_SYMBOL(ath9k_hw_stoptxdma); 225EXPORT_SYMBOL(ath9k_hw_stoptxdma);
209 226
210void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
211 u32 segLen, bool firstSeg,
212 bool lastSeg, const struct ath_desc *ds0)
213{
214 struct ar5416_desc *ads = AR5416DESC(ds);
215
216 if (firstSeg) {
217 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
218 } else if (lastSeg) {
219 ads->ds_ctl0 = 0;
220 ads->ds_ctl1 = segLen;
221 ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
222 ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
223 } else {
224 ads->ds_ctl0 = 0;
225 ads->ds_ctl1 = segLen | AR_TxMore;
226 ads->ds_ctl2 = 0;
227 ads->ds_ctl3 = 0;
228 }
229 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
230 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
231 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
232 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
233 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
234}
235EXPORT_SYMBOL(ath9k_hw_filltxdesc);
236
237void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
238{
239 struct ar5416_desc *ads = AR5416DESC(ds);
240
241 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
242 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
243 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
244 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
245 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
246}
247EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
248
249int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
250 struct ath_tx_status *ts)
251{
252 struct ar5416_desc *ads = AR5416DESC(ds);
253
254 if ((ads->ds_txstatus9 & AR_TxDone) == 0)
255 return -EINPROGRESS;
256
257 ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
258 ts->ts_tstamp = ads->AR_SendTimestamp;
259 ts->ts_status = 0;
260 ts->ts_flags = 0;
261
262 if (ads->ds_txstatus1 & AR_FrmXmitOK)
263 ts->ts_status |= ATH9K_TX_ACKED;
264 if (ads->ds_txstatus1 & AR_ExcessiveRetries)
265 ts->ts_status |= ATH9K_TXERR_XRETRY;
266 if (ads->ds_txstatus1 & AR_Filtered)
267 ts->ts_status |= ATH9K_TXERR_FILT;
268 if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
269 ts->ts_status |= ATH9K_TXERR_FIFO;
270 ath9k_hw_updatetxtriglevel(ah, true);
271 }
272 if (ads->ds_txstatus9 & AR_TxOpExceeded)
273 ts->ts_status |= ATH9K_TXERR_XTXOP;
274 if (ads->ds_txstatus1 & AR_TxTimerExpired)
275 ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
276
277 if (ads->ds_txstatus1 & AR_DescCfgErr)
278 ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
279 if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
280 ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
281 ath9k_hw_updatetxtriglevel(ah, true);
282 }
283 if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
284 ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
285 ath9k_hw_updatetxtriglevel(ah, true);
286 }
287 if (ads->ds_txstatus0 & AR_TxBaStatus) {
288 ts->ts_flags |= ATH9K_TX_BA;
289 ts->ba_low = ads->AR_BaBitmapLow;
290 ts->ba_high = ads->AR_BaBitmapHigh;
291 }
292
293 ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
294 switch (ts->ts_rateindex) {
295 case 0:
296 ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
297 break;
298 case 1:
299 ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
300 break;
301 case 2:
302 ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
303 break;
304 case 3:
305 ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
306 break;
307 }
308
309 ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
310 ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
311 ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
312 ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
313 ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
314 ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
315 ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
316 ts->evm0 = ads->AR_TxEVM0;
317 ts->evm1 = ads->AR_TxEVM1;
318 ts->evm2 = ads->AR_TxEVM2;
319 ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
320 ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
321 ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
322 ts->ts_antenna = 0;
323
324 return 0;
325}
326EXPORT_SYMBOL(ath9k_hw_txprocdesc);
327
328void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
329 u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
330 u32 keyIx, enum ath9k_key_type keyType, u32 flags)
331{
332 struct ar5416_desc *ads = AR5416DESC(ds);
333
334 txPower += ah->txpower_indexoffset;
335 if (txPower > 63)
336 txPower = 63;
337
338 ads->ds_ctl0 = (pktLen & AR_FrameLen)
339 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
340 | SM(txPower, AR_XmitPower)
341 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
342 | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
343 | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
344 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
345
346 ads->ds_ctl1 =
347 (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
348 | SM(type, AR_FrameType)
349 | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
350 | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
351 | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
352
353 ads->ds_ctl6 = SM(keyType, AR_EncrType);
354
355 if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
356 ads->ds_ctl8 = 0;
357 ads->ds_ctl9 = 0;
358 ads->ds_ctl10 = 0;
359 ads->ds_ctl11 = 0;
360 }
361}
362EXPORT_SYMBOL(ath9k_hw_set11n_txdesc);
363
364void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
365 struct ath_desc *lastds,
366 u32 durUpdateEn, u32 rtsctsRate,
367 u32 rtsctsDuration,
368 struct ath9k_11n_rate_series series[],
369 u32 nseries, u32 flags)
370{
371 struct ar5416_desc *ads = AR5416DESC(ds);
372 struct ar5416_desc *last_ads = AR5416DESC(lastds);
373 u32 ds_ctl0;
374
375 if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
376 ds_ctl0 = ads->ds_ctl0;
377
378 if (flags & ATH9K_TXDESC_RTSENA) {
379 ds_ctl0 &= ~AR_CTSEnable;
380 ds_ctl0 |= AR_RTSEnable;
381 } else {
382 ds_ctl0 &= ~AR_RTSEnable;
383 ds_ctl0 |= AR_CTSEnable;
384 }
385
386 ads->ds_ctl0 = ds_ctl0;
387 } else {
388 ads->ds_ctl0 =
389 (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
390 }
391
392 ads->ds_ctl2 = set11nTries(series, 0)
393 | set11nTries(series, 1)
394 | set11nTries(series, 2)
395 | set11nTries(series, 3)
396 | (durUpdateEn ? AR_DurUpdateEna : 0)
397 | SM(0, AR_BurstDur);
398
399 ads->ds_ctl3 = set11nRate(series, 0)
400 | set11nRate(series, 1)
401 | set11nRate(series, 2)
402 | set11nRate(series, 3);
403
404 ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
405 | set11nPktDurRTSCTS(series, 1);
406
407 ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
408 | set11nPktDurRTSCTS(series, 3);
409
410 ads->ds_ctl7 = set11nRateFlags(series, 0)
411 | set11nRateFlags(series, 1)
412 | set11nRateFlags(series, 2)
413 | set11nRateFlags(series, 3)
414 | SM(rtsctsRate, AR_RTSCTSRate);
415 last_ads->ds_ctl2 = ads->ds_ctl2;
416 last_ads->ds_ctl3 = ads->ds_ctl3;
417}
418EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario);
419
420void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
421 u32 aggrLen)
422{
423 struct ar5416_desc *ads = AR5416DESC(ds);
424
425 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
426 ads->ds_ctl6 &= ~AR_AggrLen;
427 ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
428}
429EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first);
430
431void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
432 u32 numDelims)
433{
434 struct ar5416_desc *ads = AR5416DESC(ds);
435 unsigned int ctl6;
436
437 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
438
439 ctl6 = ads->ds_ctl6;
440 ctl6 &= ~AR_PadDelim;
441 ctl6 |= SM(numDelims, AR_PadDelim);
442 ads->ds_ctl6 = ctl6;
443}
444EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle);
445
446void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
447{
448 struct ar5416_desc *ads = AR5416DESC(ds);
449
450 ads->ds_ctl1 |= AR_IsAggr;
451 ads->ds_ctl1 &= ~AR_MoreAggr;
452 ads->ds_ctl6 &= ~AR_PadDelim;
453}
454EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last);
455
456void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
457{
458 struct ar5416_desc *ads = AR5416DESC(ds);
459
460 ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
461}
462EXPORT_SYMBOL(ath9k_hw_clr11n_aggr);
463
464void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
465 u32 burstDuration)
466{
467 struct ar5416_desc *ads = AR5416DESC(ds);
468
469 ads->ds_ctl2 &= ~AR_BurstDur;
470 ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
471}
472EXPORT_SYMBOL(ath9k_hw_set11n_burstduration);
473
474void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
475 u32 vmf)
476{
477 struct ar5416_desc *ads = AR5416DESC(ds);
478
479 if (vmf)
480 ads->ds_ctl0 |= AR_VirtMoreFrag;
481 else
482 ads->ds_ctl0 &= ~AR_VirtMoreFrag;
483}
484
485void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) 227void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
486{ 228{
487 *txqs &= ah->intr_txqs; 229 *txqs &= ah->intr_txqs;
@@ -733,6 +475,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
733 } else 475 } else
734 cwMin = qi->tqi_cwmin; 476 cwMin = qi->tqi_cwmin;
735 477
478 ENABLE_REGWRITE_BUFFER(ah);
479
736 REG_WRITE(ah, AR_DLCL_IFS(q), 480 REG_WRITE(ah, AR_DLCL_IFS(q),
737 SM(cwMin, AR_D_LCL_IFS_CWMIN) | 481 SM(cwMin, AR_D_LCL_IFS_CWMIN) |
738 SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | 482 SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
@@ -747,6 +491,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
747 REG_WRITE(ah, AR_DMISC(q), 491 REG_WRITE(ah, AR_DMISC(q),
748 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); 492 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
749 493
494 REGWRITE_BUFFER_FLUSH(ah);
495
750 if (qi->tqi_cbrPeriod) { 496 if (qi->tqi_cbrPeriod) {
751 REG_WRITE(ah, AR_QCBRCFG(q), 497 REG_WRITE(ah, AR_QCBRCFG(q),
752 SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | 498 SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
@@ -762,6 +508,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
762 AR_Q_RDYTIMECFG_EN); 508 AR_Q_RDYTIMECFG_EN);
763 } 509 }
764 510
511 REGWRITE_BUFFER_FLUSH(ah);
512
765 REG_WRITE(ah, AR_DCHNTIME(q), 513 REG_WRITE(ah, AR_DCHNTIME(q),
766 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | 514 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
767 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); 515 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
@@ -779,6 +527,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
779 REG_READ(ah, AR_DMISC(q)) | 527 REG_READ(ah, AR_DMISC(q)) |
780 AR_D_MISC_POST_FR_BKOFF_DIS); 528 AR_D_MISC_POST_FR_BKOFF_DIS);
781 } 529 }
530
531 REGWRITE_BUFFER_FLUSH(ah);
532 DISABLE_REGWRITE_BUFFER(ah);
533
782 if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { 534 if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
783 REG_WRITE(ah, AR_DMISC(q), 535 REG_WRITE(ah, AR_DMISC(q),
784 REG_READ(ah, AR_DMISC(q)) | 536 REG_READ(ah, AR_DMISC(q)) |
@@ -786,6 +538,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
786 } 538 }
787 switch (qi->tqi_type) { 539 switch (qi->tqi_type) {
788 case ATH9K_TX_QUEUE_BEACON: 540 case ATH9K_TX_QUEUE_BEACON:
541 ENABLE_REGWRITE_BUFFER(ah);
542
789 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) 543 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
790 | AR_Q_MISC_FSP_DBA_GATED 544 | AR_Q_MISC_FSP_DBA_GATED
791 | AR_Q_MISC_BEACON_USE 545 | AR_Q_MISC_BEACON_USE
@@ -796,8 +550,20 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
796 AR_D_MISC_ARB_LOCKOUT_CNTRL_S) 550 AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
797 | AR_D_MISC_BEACON_USE 551 | AR_D_MISC_BEACON_USE
798 | AR_D_MISC_POST_FR_BKOFF_DIS); 552 | AR_D_MISC_POST_FR_BKOFF_DIS);
553
554 REGWRITE_BUFFER_FLUSH(ah);
555 DISABLE_REGWRITE_BUFFER(ah);
556
557 /* cwmin and cwmax should be 0 for beacon queue */
558 if (AR_SREV_9300_20_OR_LATER(ah)) {
559 REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN)
560 | SM(0, AR_D_LCL_IFS_CWMAX)
561 | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
562 }
799 break; 563 break;
800 case ATH9K_TX_QUEUE_CAB: 564 case ATH9K_TX_QUEUE_CAB:
565 ENABLE_REGWRITE_BUFFER(ah);
566
801 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) 567 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
802 | AR_Q_MISC_FSP_DBA_GATED 568 | AR_Q_MISC_FSP_DBA_GATED
803 | AR_Q_MISC_CBR_INCR_DIS1 569 | AR_Q_MISC_CBR_INCR_DIS1
@@ -811,6 +577,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
811 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) 577 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
812 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << 578 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
813 AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); 579 AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
580
581 REGWRITE_BUFFER_FLUSH(ah);
582 DISABLE_REGWRITE_BUFFER(ah);
583
814 break; 584 break;
815 case ATH9K_TX_QUEUE_PSPOLL: 585 case ATH9K_TX_QUEUE_PSPOLL:
816 REG_WRITE(ah, AR_QMISC(q), 586 REG_WRITE(ah, AR_QMISC(q),
@@ -832,6 +602,9 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
832 AR_D_MISC_POST_FR_BKOFF_DIS); 602 AR_D_MISC_POST_FR_BKOFF_DIS);
833 } 603 }
834 604
605 if (AR_SREV_9300_20_OR_LATER(ah))
606 REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
607
835 if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) 608 if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
836 ah->txok_interrupt_mask |= 1 << q; 609 ah->txok_interrupt_mask |= 1 << q;
837 else 610 else
@@ -940,22 +713,6 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
940} 713}
941EXPORT_SYMBOL(ath9k_hw_rxprocdesc); 714EXPORT_SYMBOL(ath9k_hw_rxprocdesc);
942 715
943void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
944 u32 size, u32 flags)
945{
946 struct ar5416_desc *ads = AR5416DESC(ds);
947 struct ath9k_hw_capabilities *pCap = &ah->caps;
948
949 ads->ds_ctl1 = size & AR_BufLen;
950 if (flags & ATH9K_RXDESC_INTREQ)
951 ads->ds_ctl1 |= AR_RxIntrReq;
952
953 ads->ds_rxstatus8 &= ~AR_RxDone;
954 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
955 memset(&(ads->u), 0, sizeof(ads->u));
956}
957EXPORT_SYMBOL(ath9k_hw_setuprxdesc);
958
959/* 716/*
960 * This can stop or re-enables RX. 717 * This can stop or re-enables RX.
961 * 718 *
@@ -999,12 +756,6 @@ void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
999} 756}
1000EXPORT_SYMBOL(ath9k_hw_putrxbuf); 757EXPORT_SYMBOL(ath9k_hw_putrxbuf);
1001 758
1002void ath9k_hw_rxena(struct ath_hw *ah)
1003{
1004 REG_WRITE(ah, AR_CR, AR_CR_RXE);
1005}
1006EXPORT_SYMBOL(ath9k_hw_rxena);
1007
1008void ath9k_hw_startpcureceive(struct ath_hw *ah) 759void ath9k_hw_startpcureceive(struct ath_hw *ah)
1009{ 760{
1010 ath9k_enable_mib_counters(ah); 761 ath9k_enable_mib_counters(ah);
@@ -1023,6 +774,14 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah)
1023} 774}
1024EXPORT_SYMBOL(ath9k_hw_stoppcurecv); 775EXPORT_SYMBOL(ath9k_hw_stoppcurecv);
1025 776
777void ath9k_hw_abortpcurecv(struct ath_hw *ah)
778{
779 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
780
781 ath9k_hw_disable_mib_counters(ah);
782}
783EXPORT_SYMBOL(ath9k_hw_abortpcurecv);
784
1026bool ath9k_hw_stopdmarecv(struct ath_hw *ah) 785bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
1027{ 786{
1028#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ 787#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
@@ -1068,3 +827,140 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah)
1068 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); 827 return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
1069} 828}
1070EXPORT_SYMBOL(ath9k_hw_beaconq_setup); 829EXPORT_SYMBOL(ath9k_hw_beaconq_setup);
830
831bool ath9k_hw_intrpend(struct ath_hw *ah)
832{
833 u32 host_isr;
834
835 if (AR_SREV_9100(ah))
836 return true;
837
838 host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
839 if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
840 return true;
841
842 host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
843 if ((host_isr & AR_INTR_SYNC_DEFAULT)
844 && (host_isr != AR_INTR_SPURIOUS))
845 return true;
846
847 return false;
848}
849EXPORT_SYMBOL(ath9k_hw_intrpend);
850
851enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
852 enum ath9k_int ints)
853{
854 enum ath9k_int omask = ah->imask;
855 u32 mask, mask2;
856 struct ath9k_hw_capabilities *pCap = &ah->caps;
857 struct ath_common *common = ath9k_hw_common(ah);
858
859 ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
860
861 if (omask & ATH9K_INT_GLOBAL) {
862 ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
863 REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
864 (void) REG_READ(ah, AR_IER);
865 if (!AR_SREV_9100(ah)) {
866 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
867 (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
868
869 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
870 (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
871 }
872 }
873
874 /* TODO: global int Ref count */
875 mask = ints & ATH9K_INT_COMMON;
876 mask2 = 0;
877
878 if (ints & ATH9K_INT_TX) {
879 if (ah->config.tx_intr_mitigation)
880 mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
881 if (ah->txok_interrupt_mask)
882 mask |= AR_IMR_TXOK;
883 if (ah->txdesc_interrupt_mask)
884 mask |= AR_IMR_TXDESC;
885 if (ah->txerr_interrupt_mask)
886 mask |= AR_IMR_TXERR;
887 if (ah->txeol_interrupt_mask)
888 mask |= AR_IMR_TXEOL;
889 }
890 if (ints & ATH9K_INT_RX) {
891 if (AR_SREV_9300_20_OR_LATER(ah)) {
892 mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
893 if (ah->config.rx_intr_mitigation) {
894 mask &= ~AR_IMR_RXOK_LP;
895 mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
896 } else {
897 mask |= AR_IMR_RXOK_LP;
898 }
899 } else {
900 if (ah->config.rx_intr_mitigation)
901 mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
902 else
903 mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
904 }
905 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
906 mask |= AR_IMR_GENTMR;
907 }
908
909 if (ints & (ATH9K_INT_BMISC)) {
910 mask |= AR_IMR_BCNMISC;
911 if (ints & ATH9K_INT_TIM)
912 mask2 |= AR_IMR_S2_TIM;
913 if (ints & ATH9K_INT_DTIM)
914 mask2 |= AR_IMR_S2_DTIM;
915 if (ints & ATH9K_INT_DTIMSYNC)
916 mask2 |= AR_IMR_S2_DTIMSYNC;
917 if (ints & ATH9K_INT_CABEND)
918 mask2 |= AR_IMR_S2_CABEND;
919 if (ints & ATH9K_INT_TSFOOR)
920 mask2 |= AR_IMR_S2_TSFOOR;
921 }
922
923 if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
924 mask |= AR_IMR_BCNMISC;
925 if (ints & ATH9K_INT_GTT)
926 mask2 |= AR_IMR_S2_GTT;
927 if (ints & ATH9K_INT_CST)
928 mask2 |= AR_IMR_S2_CST;
929 }
930
931 ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
932 REG_WRITE(ah, AR_IMR, mask);
933 ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
934 AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
935 AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
936 ah->imrs2_reg |= mask2;
937 REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
938
939 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
940 if (ints & ATH9K_INT_TIM_TIMER)
941 REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
942 else
943 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
944 }
945
946 if (ints & ATH9K_INT_GLOBAL) {
947 ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
948 REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
949 if (!AR_SREV_9100(ah)) {
950 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
951 AR_INTR_MAC_IRQ);
952 REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
953
954
955 REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
956 AR_INTR_SYNC_DEFAULT);
957 REG_WRITE(ah, AR_INTR_SYNC_MASK,
958 AR_INTR_SYNC_DEFAULT);
959 }
960 ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
961 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
962 }
963
964 return omask;
965}
966EXPORT_SYMBOL(ath9k_hw_set_interrupts);