init from v2.6.32.60
[mach-moxart.git] / drivers / net / wireless / ath / ath9k / mac.c
blob110c16dd465c798f076f56886021d3dd2e9124ee
1 /*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
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.
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.
17 #include "ath9k.h"
19 static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
20 struct ath9k_tx_queue_info *qi)
22 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
23 "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
24 ah->txok_interrupt_mask, ah->txerr_interrupt_mask,
25 ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
26 ah->txurn_interrupt_mask);
28 REG_WRITE(ah, AR_IMR_S0,
29 SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
30 | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
31 REG_WRITE(ah, AR_IMR_S1,
32 SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR)
33 | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL));
34 REG_RMW_FIELD(ah, AR_IMR_S2,
35 AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask);
38 u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
40 return REG_READ(ah, AR_QTXDP(q));
43 void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
45 REG_WRITE(ah, AR_QTXDP(q), txdp);
48 void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
50 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q);
51 REG_WRITE(ah, AR_Q_TXE, 1 << q);
54 u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
56 u32 npend;
58 npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
59 if (npend == 0) {
61 if (REG_READ(ah, AR_Q_TXE) & (1 << q))
62 npend = 1;
65 return npend;
68 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
70 u32 txcfg, curLevel, newLevel;
71 enum ath9k_int omask;
73 if (ah->tx_trig_level >= ah->config.max_txtrig_level)
74 return false;
76 omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
78 txcfg = REG_READ(ah, AR_TXCFG);
79 curLevel = MS(txcfg, AR_FTRIG);
80 newLevel = curLevel;
81 if (bIncTrigLevel) {
82 if (curLevel < ah->config.max_txtrig_level)
83 newLevel++;
84 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
85 newLevel--;
86 if (newLevel != curLevel)
87 REG_WRITE(ah, AR_TXCFG,
88 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
90 ath9k_hw_set_interrupts(ah, omask);
92 ah->tx_trig_level = newLevel;
94 return newLevel != curLevel;
97 bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
99 #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
100 #define ATH9K_TIME_QUANTUM 100 /* usec */
102 struct ath9k_hw_capabilities *pCap = &ah->caps;
103 struct ath9k_tx_queue_info *qi;
104 u32 tsfLow, j, wait;
105 u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
107 if (q >= pCap->total_queues) {
108 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
109 "invalid queue: %u\n", q);
110 return false;
113 qi = &ah->txq[q];
114 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
115 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
116 "inactive queue: %u\n", q);
117 return false;
120 REG_WRITE(ah, AR_Q_TXD, 1 << q);
122 for (wait = wait_time; wait != 0; wait--) {
123 if (ath9k_hw_numtxpending(ah, q) == 0)
124 break;
125 udelay(ATH9K_TIME_QUANTUM);
128 if (ath9k_hw_numtxpending(ah, q)) {
129 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
130 "%s: Num of pending TX Frames %d on Q %d\n",
131 __func__, ath9k_hw_numtxpending(ah, q), q);
133 for (j = 0; j < 2; j++) {
134 tsfLow = REG_READ(ah, AR_TSF_L32);
135 REG_WRITE(ah, AR_QUIET2,
136 SM(10, AR_QUIET2_QUIET_DUR));
137 REG_WRITE(ah, AR_QUIET_PERIOD, 100);
138 REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
139 REG_SET_BIT(ah, AR_TIMER_MODE,
140 AR_QUIET_TIMER_EN);
142 if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
143 break;
145 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
146 "TSF has moved while trying to set "
147 "quiet time TSF: 0x%08x\n", tsfLow);
150 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
152 udelay(200);
153 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
155 wait = wait_time;
156 while (ath9k_hw_numtxpending(ah, q)) {
157 if ((--wait) == 0) {
158 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
159 "Failed to stop TX DMA in 100 "
160 "msec after killing last frame\n");
161 break;
163 udelay(ATH9K_TIME_QUANTUM);
166 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
169 REG_WRITE(ah, AR_Q_TXD, 0);
170 return wait != 0;
172 #undef ATH9K_TX_STOP_DMA_TIMEOUT
173 #undef ATH9K_TIME_QUANTUM
176 void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
177 u32 segLen, bool firstSeg,
178 bool lastSeg, const struct ath_desc *ds0)
180 struct ar5416_desc *ads = AR5416DESC(ds);
182 if (firstSeg) {
183 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
184 } else if (lastSeg) {
185 ads->ds_ctl0 = 0;
186 ads->ds_ctl1 = segLen;
187 ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
188 ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
189 } else {
190 ads->ds_ctl0 = 0;
191 ads->ds_ctl1 = segLen | AR_TxMore;
192 ads->ds_ctl2 = 0;
193 ads->ds_ctl3 = 0;
195 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
196 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
197 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
198 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
199 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
202 void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
204 struct ar5416_desc *ads = AR5416DESC(ds);
206 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
207 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
208 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
209 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
210 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
213 int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
215 struct ar5416_desc *ads = AR5416DESC(ds);
217 if ((ads->ds_txstatus9 & AR_TxDone) == 0)
218 return -EINPROGRESS;
220 ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
221 ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
222 ds->ds_txstat.ts_status = 0;
223 ds->ds_txstat.ts_flags = 0;
225 if (ads->ds_txstatus1 & AR_FrmXmitOK)
226 ds->ds_txstat.ts_status |= ATH9K_TX_ACKED;
227 if (ads->ds_txstatus1 & AR_ExcessiveRetries)
228 ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
229 if (ads->ds_txstatus1 & AR_Filtered)
230 ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
231 if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
232 ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
233 ath9k_hw_updatetxtriglevel(ah, true);
235 if (ads->ds_txstatus9 & AR_TxOpExceeded)
236 ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
237 if (ads->ds_txstatus1 & AR_TxTimerExpired)
238 ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
240 if (ads->ds_txstatus1 & AR_DescCfgErr)
241 ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
242 if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
243 ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
244 ath9k_hw_updatetxtriglevel(ah, true);
246 if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
247 ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
248 ath9k_hw_updatetxtriglevel(ah, true);
250 if (ads->ds_txstatus0 & AR_TxBaStatus) {
251 ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
252 ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
253 ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
256 ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
257 switch (ds->ds_txstat.ts_rateindex) {
258 case 0:
259 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
260 break;
261 case 1:
262 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
263 break;
264 case 2:
265 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
266 break;
267 case 3:
268 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
269 break;
272 ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
273 ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
274 ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
275 ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
276 ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
277 ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
278 ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
279 ds->ds_txstat.evm0 = ads->AR_TxEVM0;
280 ds->ds_txstat.evm1 = ads->AR_TxEVM1;
281 ds->ds_txstat.evm2 = ads->AR_TxEVM2;
282 ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
283 ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
284 ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
285 ds->ds_txstat.ts_antenna = 0;
287 return 0;
290 void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
291 u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
292 u32 keyIx, enum ath9k_key_type keyType, u32 flags)
294 struct ar5416_desc *ads = AR5416DESC(ds);
296 txPower += ah->txpower_indexoffset;
297 if (txPower > 63)
298 txPower = 63;
300 ads->ds_ctl0 = (pktLen & AR_FrameLen)
301 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
302 | SM(txPower, AR_XmitPower)
303 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
304 | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
305 | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
306 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
308 ads->ds_ctl1 =
309 (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
310 | SM(type, AR_FrameType)
311 | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
312 | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
313 | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
315 ads->ds_ctl6 = SM(keyType, AR_EncrType);
317 if (AR_SREV_9285(ah)) {
318 ads->ds_ctl8 = 0;
319 ads->ds_ctl9 = 0;
320 ads->ds_ctl10 = 0;
321 ads->ds_ctl11 = 0;
325 void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
326 struct ath_desc *lastds,
327 u32 durUpdateEn, u32 rtsctsRate,
328 u32 rtsctsDuration,
329 struct ath9k_11n_rate_series series[],
330 u32 nseries, u32 flags)
332 struct ar5416_desc *ads = AR5416DESC(ds);
333 struct ar5416_desc *last_ads = AR5416DESC(lastds);
334 u32 ds_ctl0;
336 if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
337 ds_ctl0 = ads->ds_ctl0;
339 if (flags & ATH9K_TXDESC_RTSENA) {
340 ds_ctl0 &= ~AR_CTSEnable;
341 ds_ctl0 |= AR_RTSEnable;
342 } else {
343 ds_ctl0 &= ~AR_RTSEnable;
344 ds_ctl0 |= AR_CTSEnable;
347 ads->ds_ctl0 = ds_ctl0;
348 } else {
349 ads->ds_ctl0 =
350 (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
353 ads->ds_ctl2 = set11nTries(series, 0)
354 | set11nTries(series, 1)
355 | set11nTries(series, 2)
356 | set11nTries(series, 3)
357 | (durUpdateEn ? AR_DurUpdateEna : 0)
358 | SM(0, AR_BurstDur);
360 ads->ds_ctl3 = set11nRate(series, 0)
361 | set11nRate(series, 1)
362 | set11nRate(series, 2)
363 | set11nRate(series, 3);
365 ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
366 | set11nPktDurRTSCTS(series, 1);
368 ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
369 | set11nPktDurRTSCTS(series, 3);
371 ads->ds_ctl7 = set11nRateFlags(series, 0)
372 | set11nRateFlags(series, 1)
373 | set11nRateFlags(series, 2)
374 | set11nRateFlags(series, 3)
375 | SM(rtsctsRate, AR_RTSCTSRate);
376 last_ads->ds_ctl2 = ads->ds_ctl2;
377 last_ads->ds_ctl3 = ads->ds_ctl3;
380 void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
381 u32 aggrLen)
383 struct ar5416_desc *ads = AR5416DESC(ds);
385 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
386 ads->ds_ctl6 &= ~AR_AggrLen;
387 ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
390 void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
391 u32 numDelims)
393 struct ar5416_desc *ads = AR5416DESC(ds);
394 unsigned int ctl6;
396 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
398 ctl6 = ads->ds_ctl6;
399 ctl6 &= ~AR_PadDelim;
400 ctl6 |= SM(numDelims, AR_PadDelim);
401 ads->ds_ctl6 = ctl6;
404 void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
406 struct ar5416_desc *ads = AR5416DESC(ds);
408 ads->ds_ctl1 |= AR_IsAggr;
409 ads->ds_ctl1 &= ~AR_MoreAggr;
410 ads->ds_ctl6 &= ~AR_PadDelim;
413 void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
415 struct ar5416_desc *ads = AR5416DESC(ds);
417 ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
420 void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
421 u32 burstDuration)
423 struct ar5416_desc *ads = AR5416DESC(ds);
425 ads->ds_ctl2 &= ~AR_BurstDur;
426 ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
429 void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
430 u32 vmf)
432 struct ar5416_desc *ads = AR5416DESC(ds);
434 if (vmf)
435 ads->ds_ctl0 |= AR_VirtMoreFrag;
436 else
437 ads->ds_ctl0 &= ~AR_VirtMoreFrag;
440 void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
442 *txqs &= ah->intr_txqs;
443 ah->intr_txqs &= ~(*txqs);
446 bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
447 const struct ath9k_tx_queue_info *qinfo)
449 u32 cw;
450 struct ath9k_hw_capabilities *pCap = &ah->caps;
451 struct ath9k_tx_queue_info *qi;
453 if (q >= pCap->total_queues) {
454 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
455 "invalid queue: %u\n", q);
456 return false;
459 qi = &ah->txq[q];
460 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
461 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
462 "inactive queue: %u\n", q);
463 return false;
466 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
468 qi->tqi_ver = qinfo->tqi_ver;
469 qi->tqi_subtype = qinfo->tqi_subtype;
470 qi->tqi_qflags = qinfo->tqi_qflags;
471 qi->tqi_priority = qinfo->tqi_priority;
472 if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
473 qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
474 else
475 qi->tqi_aifs = INIT_AIFS;
476 if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
477 cw = min(qinfo->tqi_cwmin, 1024U);
478 qi->tqi_cwmin = 1;
479 while (qi->tqi_cwmin < cw)
480 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
481 } else
482 qi->tqi_cwmin = qinfo->tqi_cwmin;
483 if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
484 cw = min(qinfo->tqi_cwmax, 1024U);
485 qi->tqi_cwmax = 1;
486 while (qi->tqi_cwmax < cw)
487 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
488 } else
489 qi->tqi_cwmax = INIT_CWMAX;
491 if (qinfo->tqi_shretry != 0)
492 qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
493 else
494 qi->tqi_shretry = INIT_SH_RETRY;
495 if (qinfo->tqi_lgretry != 0)
496 qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
497 else
498 qi->tqi_lgretry = INIT_LG_RETRY;
499 qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
500 qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
501 qi->tqi_burstTime = qinfo->tqi_burstTime;
502 qi->tqi_readyTime = qinfo->tqi_readyTime;
504 switch (qinfo->tqi_subtype) {
505 case ATH9K_WME_UPSD:
506 if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
507 qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
508 break;
509 default:
510 break;
513 return true;
516 bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
517 struct ath9k_tx_queue_info *qinfo)
519 struct ath9k_hw_capabilities *pCap = &ah->caps;
520 struct ath9k_tx_queue_info *qi;
522 if (q >= pCap->total_queues) {
523 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
524 "invalid queue: %u\n", q);
525 return false;
528 qi = &ah->txq[q];
529 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
530 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
531 "inactive queue: %u\n", q);
532 return false;
535 qinfo->tqi_qflags = qi->tqi_qflags;
536 qinfo->tqi_ver = qi->tqi_ver;
537 qinfo->tqi_subtype = qi->tqi_subtype;
538 qinfo->tqi_qflags = qi->tqi_qflags;
539 qinfo->tqi_priority = qi->tqi_priority;
540 qinfo->tqi_aifs = qi->tqi_aifs;
541 qinfo->tqi_cwmin = qi->tqi_cwmin;
542 qinfo->tqi_cwmax = qi->tqi_cwmax;
543 qinfo->tqi_shretry = qi->tqi_shretry;
544 qinfo->tqi_lgretry = qi->tqi_lgretry;
545 qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
546 qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
547 qinfo->tqi_burstTime = qi->tqi_burstTime;
548 qinfo->tqi_readyTime = qi->tqi_readyTime;
550 return true;
553 int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
554 const struct ath9k_tx_queue_info *qinfo)
556 struct ath9k_tx_queue_info *qi;
557 struct ath9k_hw_capabilities *pCap = &ah->caps;
558 int q;
560 switch (type) {
561 case ATH9K_TX_QUEUE_BEACON:
562 q = pCap->total_queues - 1;
563 break;
564 case ATH9K_TX_QUEUE_CAB:
565 q = pCap->total_queues - 2;
566 break;
567 case ATH9K_TX_QUEUE_PSPOLL:
568 q = 1;
569 break;
570 case ATH9K_TX_QUEUE_UAPSD:
571 q = pCap->total_queues - 3;
572 break;
573 case ATH9K_TX_QUEUE_DATA:
574 for (q = 0; q < pCap->total_queues; q++)
575 if (ah->txq[q].tqi_type ==
576 ATH9K_TX_QUEUE_INACTIVE)
577 break;
578 if (q == pCap->total_queues) {
579 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
580 "No available TX queue\n");
581 return -1;
583 break;
584 default:
585 DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n",
586 type);
587 return -1;
590 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
592 qi = &ah->txq[q];
593 if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
594 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
595 "TX queue: %u already active\n", q);
596 return -1;
598 memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
599 qi->tqi_type = type;
600 if (qinfo == NULL) {
601 qi->tqi_qflags =
602 TXQ_FLAG_TXOKINT_ENABLE
603 | TXQ_FLAG_TXERRINT_ENABLE
604 | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
605 qi->tqi_aifs = INIT_AIFS;
606 qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
607 qi->tqi_cwmax = INIT_CWMAX;
608 qi->tqi_shretry = INIT_SH_RETRY;
609 qi->tqi_lgretry = INIT_LG_RETRY;
610 qi->tqi_physCompBuf = 0;
611 } else {
612 qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
613 (void) ath9k_hw_set_txq_props(ah, q, qinfo);
616 return q;
619 bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
621 struct ath9k_hw_capabilities *pCap = &ah->caps;
622 struct ath9k_tx_queue_info *qi;
624 if (q >= pCap->total_queues) {
625 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
626 "invalid queue: %u\n", q);
627 return false;
629 qi = &ah->txq[q];
630 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
631 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
632 "inactive queue: %u\n", q);
633 return false;
636 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
638 qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
639 ah->txok_interrupt_mask &= ~(1 << q);
640 ah->txerr_interrupt_mask &= ~(1 << q);
641 ah->txdesc_interrupt_mask &= ~(1 << q);
642 ah->txeol_interrupt_mask &= ~(1 << q);
643 ah->txurn_interrupt_mask &= ~(1 << q);
644 ath9k_hw_set_txq_interrupts(ah, qi);
646 return true;
649 bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
651 struct ath9k_hw_capabilities *pCap = &ah->caps;
652 struct ath9k_channel *chan = ah->curchan;
653 struct ath9k_tx_queue_info *qi;
654 u32 cwMin, chanCwMin, value;
656 if (q >= pCap->total_queues) {
657 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
658 "invalid queue: %u\n", q);
659 return false;
662 qi = &ah->txq[q];
663 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
664 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
665 "inactive queue: %u\n", q);
666 return true;
669 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
671 if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
672 if (chan && IS_CHAN_B(chan))
673 chanCwMin = INIT_CWMIN_11B;
674 else
675 chanCwMin = INIT_CWMIN;
677 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
678 } else
679 cwMin = qi->tqi_cwmin;
681 REG_WRITE(ah, AR_DLCL_IFS(q),
682 SM(cwMin, AR_D_LCL_IFS_CWMIN) |
683 SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
684 SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
686 REG_WRITE(ah, AR_DRETRY_LIMIT(q),
687 SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
688 SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
689 SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
691 REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
692 REG_WRITE(ah, AR_DMISC(q),
693 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
695 if (qi->tqi_cbrPeriod) {
696 REG_WRITE(ah, AR_QCBRCFG(q),
697 SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
698 SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
699 REG_WRITE(ah, AR_QMISC(q),
700 REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
701 (qi->tqi_cbrOverflowLimit ?
702 AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
704 if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
705 REG_WRITE(ah, AR_QRDYTIMECFG(q),
706 SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
707 AR_Q_RDYTIMECFG_EN);
710 REG_WRITE(ah, AR_DCHNTIME(q),
711 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
712 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
714 if (qi->tqi_burstTime
715 && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
716 REG_WRITE(ah, AR_QMISC(q),
717 REG_READ(ah, AR_QMISC(q)) |
718 AR_Q_MISC_RDYTIME_EXP_POLICY);
722 if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
723 REG_WRITE(ah, AR_DMISC(q),
724 REG_READ(ah, AR_DMISC(q)) |
725 AR_D_MISC_POST_FR_BKOFF_DIS);
727 if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
728 REG_WRITE(ah, AR_DMISC(q),
729 REG_READ(ah, AR_DMISC(q)) |
730 AR_D_MISC_FRAG_BKOFF_EN);
732 switch (qi->tqi_type) {
733 case ATH9K_TX_QUEUE_BEACON:
734 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
735 | AR_Q_MISC_FSP_DBA_GATED
736 | AR_Q_MISC_BEACON_USE
737 | AR_Q_MISC_CBR_INCR_DIS1);
739 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
740 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
741 AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
742 | AR_D_MISC_BEACON_USE
743 | AR_D_MISC_POST_FR_BKOFF_DIS);
744 break;
745 case ATH9K_TX_QUEUE_CAB:
746 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
747 | AR_Q_MISC_FSP_DBA_GATED
748 | AR_Q_MISC_CBR_INCR_DIS1
749 | AR_Q_MISC_CBR_INCR_DIS0);
750 value = (qi->tqi_readyTime -
751 (ah->config.sw_beacon_response_time -
752 ah->config.dma_beacon_response_time) -
753 ah->config.additional_swba_backoff) * 1024;
754 REG_WRITE(ah, AR_QRDYTIMECFG(q),
755 value | AR_Q_RDYTIMECFG_EN);
756 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
757 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
758 AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
759 break;
760 case ATH9K_TX_QUEUE_PSPOLL:
761 REG_WRITE(ah, AR_QMISC(q),
762 REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
763 break;
764 case ATH9K_TX_QUEUE_UAPSD:
765 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
766 AR_D_MISC_POST_FR_BKOFF_DIS);
767 break;
768 default:
769 break;
772 if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
773 REG_WRITE(ah, AR_DMISC(q),
774 REG_READ(ah, AR_DMISC(q)) |
775 SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
776 AR_D_MISC_ARB_LOCKOUT_CNTRL) |
777 AR_D_MISC_POST_FR_BKOFF_DIS);
780 if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
781 ah->txok_interrupt_mask |= 1 << q;
782 else
783 ah->txok_interrupt_mask &= ~(1 << q);
784 if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
785 ah->txerr_interrupt_mask |= 1 << q;
786 else
787 ah->txerr_interrupt_mask &= ~(1 << q);
788 if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
789 ah->txdesc_interrupt_mask |= 1 << q;
790 else
791 ah->txdesc_interrupt_mask &= ~(1 << q);
792 if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
793 ah->txeol_interrupt_mask |= 1 << q;
794 else
795 ah->txeol_interrupt_mask &= ~(1 << q);
796 if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
797 ah->txurn_interrupt_mask |= 1 << q;
798 else
799 ah->txurn_interrupt_mask &= ~(1 << q);
800 ath9k_hw_set_txq_interrupts(ah, qi);
802 return true;
805 int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
806 u32 pa, struct ath_desc *nds, u64 tsf)
808 struct ar5416_desc ads;
809 struct ar5416_desc *adsp = AR5416DESC(ds);
810 u32 phyerr;
812 if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
813 return -EINPROGRESS;
815 ads.u.rx = adsp->u.rx;
817 ds->ds_rxstat.rs_status = 0;
818 ds->ds_rxstat.rs_flags = 0;
820 ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
821 ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
823 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
824 ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD;
825 ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD;
826 ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD;
827 ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD;
828 ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD;
829 ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD;
830 ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD;
831 } else {
832 ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
833 ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
834 AR_RxRSSIAnt00);
835 ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
836 AR_RxRSSIAnt01);
837 ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
838 AR_RxRSSIAnt02);
839 ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4,
840 AR_RxRSSIAnt10);
841 ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4,
842 AR_RxRSSIAnt11);
843 ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4,
844 AR_RxRSSIAnt12);
846 if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
847 ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
848 else
849 ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
851 ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
852 ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
854 ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
855 ds->ds_rxstat.rs_moreaggr =
856 (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
857 ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
858 ds->ds_rxstat.rs_flags =
859 (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
860 ds->ds_rxstat.rs_flags |=
861 (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
863 if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
864 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
865 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
866 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
867 if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
868 ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
870 if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
871 if (ads.ds_rxstatus8 & AR_CRCErr)
872 ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
873 else if (ads.ds_rxstatus8 & AR_PHYErr) {
874 ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
875 phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
876 ds->ds_rxstat.rs_phyerr = phyerr;
877 } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
878 ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
879 else if (ads.ds_rxstatus8 & AR_MichaelErr)
880 ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
883 return 0;
886 void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
887 u32 size, u32 flags)
889 struct ar5416_desc *ads = AR5416DESC(ds);
890 struct ath9k_hw_capabilities *pCap = &ah->caps;
892 ads->ds_ctl1 = size & AR_BufLen;
893 if (flags & ATH9K_RXDESC_INTREQ)
894 ads->ds_ctl1 |= AR_RxIntrReq;
896 ads->ds_rxstatus8 &= ~AR_RxDone;
897 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
898 memset(&(ads->u), 0, sizeof(ads->u));
901 bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
903 u32 reg;
905 if (set) {
906 REG_SET_BIT(ah, AR_DIAG_SW,
907 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
909 if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
910 0, AH_WAIT_TIMEOUT)) {
911 REG_CLR_BIT(ah, AR_DIAG_SW,
912 (AR_DIAG_RX_DIS |
913 AR_DIAG_RX_ABORT));
915 reg = REG_READ(ah, AR_OBS_BUS_1);
916 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
917 "RX failed to go idle in 10 ms RXSM=0x%x\n", reg);
919 return false;
921 } else {
922 REG_CLR_BIT(ah, AR_DIAG_SW,
923 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
926 return true;
929 void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
931 REG_WRITE(ah, AR_RXDP, rxdp);
934 void ath9k_hw_rxena(struct ath_hw *ah)
936 REG_WRITE(ah, AR_CR, AR_CR_RXE);
939 void ath9k_hw_startpcureceive(struct ath_hw *ah)
941 ath9k_enable_mib_counters(ah);
943 ath9k_ani_reset(ah);
945 REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
948 void ath9k_hw_stoppcurecv(struct ath_hw *ah)
950 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
952 ath9k_hw_disable_mib_counters(ah);
955 bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
957 #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
958 #define AH_RX_TIME_QUANTUM 100 /* usec */
960 int i;
962 REG_WRITE(ah, AR_CR, AR_CR_RXD);
964 /* Wait for rx enable bit to go low */
965 for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
966 if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
967 break;
968 udelay(AH_TIME_QUANTUM);
971 if (i == 0) {
972 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
973 "DMA failed to stop in %d ms "
974 "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
975 AH_RX_STOP_DMA_TIMEOUT / 1000,
976 REG_READ(ah, AR_CR),
977 REG_READ(ah, AR_DIAG_SW));
978 return false;
979 } else {
980 return true;
983 #undef AH_RX_TIME_QUANTUM
984 #undef AH_RX_STOP_DMA_TIMEOUT