Merge branch 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze
[linux-2.6] / drivers / net / wireless / ath9k / mac.c
1 /*
2  * Copyright (c) 2008-2009 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
17 #include "ath9k.h"
18
19 static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
20                                         struct ath9k_tx_queue_info *qi)
21 {
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);
27
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);
36 }
37
38 u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
39 {
40         return REG_READ(ah, AR_QTXDP(q));
41 }
42
43 bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
44 {
45         REG_WRITE(ah, AR_QTXDP(q), txdp);
46
47         return true;
48 }
49
50 bool ath9k_hw_txstart(struct ath_hw *ah, u32 q)
51 {
52         DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q);
53
54         REG_WRITE(ah, AR_Q_TXE, 1 << q);
55
56         return true;
57 }
58
59 u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
60 {
61         u32 npend;
62
63         npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
64         if (npend == 0) {
65
66                 if (REG_READ(ah, AR_Q_TXE) & (1 << q))
67                         npend = 1;
68         }
69
70         return npend;
71 }
72
73 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
74 {
75         u32 txcfg, curLevel, newLevel;
76         enum ath9k_int omask;
77
78         if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD)
79                 return false;
80
81         omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
82
83         txcfg = REG_READ(ah, AR_TXCFG);
84         curLevel = MS(txcfg, AR_FTRIG);
85         newLevel = curLevel;
86         if (bIncTrigLevel) {
87                 if (curLevel < MAX_TX_FIFO_THRESHOLD)
88                         newLevel++;
89         } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
90                 newLevel--;
91         if (newLevel != curLevel)
92                 REG_WRITE(ah, AR_TXCFG,
93                           (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
94
95         ath9k_hw_set_interrupts(ah, omask);
96
97         ah->tx_trig_level = newLevel;
98
99         return newLevel != curLevel;
100 }
101
102 bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
103 {
104 #define ATH9K_TX_STOP_DMA_TIMEOUT       4000    /* usec */
105 #define ATH9K_TIME_QUANTUM              100     /* usec */
106
107         struct ath9k_hw_capabilities *pCap = &ah->caps;
108         struct ath9k_tx_queue_info *qi;
109         u32 tsfLow, j, wait;
110         u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
111
112         if (q >= pCap->total_queues) {
113                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
114                 return false;
115         }
116
117         qi = &ah->txq[q];
118         if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
119                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
120                 return false;
121         }
122
123         REG_WRITE(ah, AR_Q_TXD, 1 << q);
124
125         for (wait = wait_time; wait != 0; wait--) {
126                 if (ath9k_hw_numtxpending(ah, q) == 0)
127                         break;
128                 udelay(ATH9K_TIME_QUANTUM);
129         }
130
131         if (ath9k_hw_numtxpending(ah, q)) {
132                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
133                         "%s: Num of pending TX Frames %d on Q %d\n",
134                         __func__, ath9k_hw_numtxpending(ah, q), q);
135
136                 for (j = 0; j < 2; j++) {
137                         tsfLow = REG_READ(ah, AR_TSF_L32);
138                         REG_WRITE(ah, AR_QUIET2,
139                                   SM(10, AR_QUIET2_QUIET_DUR));
140                         REG_WRITE(ah, AR_QUIET_PERIOD, 100);
141                         REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
142                         REG_SET_BIT(ah, AR_TIMER_MODE,
143                                        AR_QUIET_TIMER_EN);
144
145                         if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
146                                 break;
147
148                         DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
149                                 "TSF have moved while trying to set "
150                                 "quiet time TSF: 0x%08x\n", tsfLow);
151                 }
152
153                 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
154
155                 udelay(200);
156                 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
157
158                 wait = wait_time;
159                 while (ath9k_hw_numtxpending(ah, q)) {
160                         if ((--wait) == 0) {
161                                 DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
162                                         "Failed to stop Tx DMA in 100 "
163                                         "msec after killing last frame\n");
164                                 break;
165                         }
166                         udelay(ATH9K_TIME_QUANTUM);
167                 }
168
169                 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
170         }
171
172         REG_WRITE(ah, AR_Q_TXD, 0);
173         return wait != 0;
174
175 #undef ATH9K_TX_STOP_DMA_TIMEOUT
176 #undef ATH9K_TIME_QUANTUM
177 }
178
179 bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
180                          u32 segLen, bool firstSeg,
181                          bool lastSeg, const struct ath_desc *ds0)
182 {
183         struct ar5416_desc *ads = AR5416DESC(ds);
184
185         if (firstSeg) {
186                 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
187         } else if (lastSeg) {
188                 ads->ds_ctl0 = 0;
189                 ads->ds_ctl1 = segLen;
190                 ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
191                 ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
192         } else {
193                 ads->ds_ctl0 = 0;
194                 ads->ds_ctl1 = segLen | AR_TxMore;
195                 ads->ds_ctl2 = 0;
196                 ads->ds_ctl3 = 0;
197         }
198         ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
199         ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
200         ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
201         ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
202         ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
203
204         return true;
205 }
206
207 void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
208 {
209         struct ar5416_desc *ads = AR5416DESC(ds);
210
211         ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
212         ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
213         ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
214         ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
215         ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
216 }
217
218 int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
219 {
220         struct ar5416_desc *ads = AR5416DESC(ds);
221
222         if ((ads->ds_txstatus9 & AR_TxDone) == 0)
223                 return -EINPROGRESS;
224
225         ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
226         ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
227         ds->ds_txstat.ts_status = 0;
228         ds->ds_txstat.ts_flags = 0;
229
230         if (ads->ds_txstatus1 & AR_ExcessiveRetries)
231                 ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
232         if (ads->ds_txstatus1 & AR_Filtered)
233                 ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
234         if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
235                 ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
236                 ath9k_hw_updatetxtriglevel(ah, true);
237         }
238         if (ads->ds_txstatus9 & AR_TxOpExceeded)
239                 ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
240         if (ads->ds_txstatus1 & AR_TxTimerExpired)
241                 ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
242
243         if (ads->ds_txstatus1 & AR_DescCfgErr)
244                 ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
245         if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
246                 ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
247                 ath9k_hw_updatetxtriglevel(ah, true);
248         }
249         if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
250                 ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
251                 ath9k_hw_updatetxtriglevel(ah, true);
252         }
253         if (ads->ds_txstatus0 & AR_TxBaStatus) {
254                 ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
255                 ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
256                 ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
257         }
258
259         ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
260         switch (ds->ds_txstat.ts_rateindex) {
261         case 0:
262                 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
263                 break;
264         case 1:
265                 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
266                 break;
267         case 2:
268                 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
269                 break;
270         case 3:
271                 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
272                 break;
273         }
274
275         ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
276         ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
277         ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
278         ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
279         ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
280         ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
281         ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
282         ds->ds_txstat.evm0 = ads->AR_TxEVM0;
283         ds->ds_txstat.evm1 = ads->AR_TxEVM1;
284         ds->ds_txstat.evm2 = ads->AR_TxEVM2;
285         ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
286         ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
287         ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
288         ds->ds_txstat.ts_antenna = 0;
289
290         return 0;
291 }
292
293 void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
294                             u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
295                             u32 keyIx, enum ath9k_key_type keyType, u32 flags)
296 {
297         struct ar5416_desc *ads = AR5416DESC(ds);
298
299         txPower += ah->txpower_indexoffset;
300         if (txPower > 63)
301                 txPower = 63;
302
303         ads->ds_ctl0 = (pktLen & AR_FrameLen)
304                 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
305                 | SM(txPower, AR_XmitPower)
306                 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
307                 | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
308                 | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
309                 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
310
311         ads->ds_ctl1 =
312                 (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
313                 | SM(type, AR_FrameType)
314                 | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
315                 | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
316                 | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
317
318         ads->ds_ctl6 = SM(keyType, AR_EncrType);
319
320         if (AR_SREV_9285(ah)) {
321                 ads->ds_ctl8 = 0;
322                 ads->ds_ctl9 = 0;
323                 ads->ds_ctl10 = 0;
324                 ads->ds_ctl11 = 0;
325         }
326 }
327
328 void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
329                                   struct ath_desc *lastds,
330                                   u32 durUpdateEn, u32 rtsctsRate,
331                                   u32 rtsctsDuration,
332                                   struct ath9k_11n_rate_series series[],
333                                   u32 nseries, u32 flags)
334 {
335         struct ar5416_desc *ads = AR5416DESC(ds);
336         struct ar5416_desc *last_ads = AR5416DESC(lastds);
337         u32 ds_ctl0;
338
339         if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
340                 ds_ctl0 = ads->ds_ctl0;
341
342                 if (flags & ATH9K_TXDESC_RTSENA) {
343                         ds_ctl0 &= ~AR_CTSEnable;
344                         ds_ctl0 |= AR_RTSEnable;
345                 } else {
346                         ds_ctl0 &= ~AR_RTSEnable;
347                         ds_ctl0 |= AR_CTSEnable;
348                 }
349
350                 ads->ds_ctl0 = ds_ctl0;
351         } else {
352                 ads->ds_ctl0 =
353                         (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
354         }
355
356         ads->ds_ctl2 = set11nTries(series, 0)
357                 | set11nTries(series, 1)
358                 | set11nTries(series, 2)
359                 | set11nTries(series, 3)
360                 | (durUpdateEn ? AR_DurUpdateEna : 0)
361                 | SM(0, AR_BurstDur);
362
363         ads->ds_ctl3 = set11nRate(series, 0)
364                 | set11nRate(series, 1)
365                 | set11nRate(series, 2)
366                 | set11nRate(series, 3);
367
368         ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
369                 | set11nPktDurRTSCTS(series, 1);
370
371         ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
372                 | set11nPktDurRTSCTS(series, 3);
373
374         ads->ds_ctl7 = set11nRateFlags(series, 0)
375                 | set11nRateFlags(series, 1)
376                 | set11nRateFlags(series, 2)
377                 | set11nRateFlags(series, 3)
378                 | SM(rtsctsRate, AR_RTSCTSRate);
379         last_ads->ds_ctl2 = ads->ds_ctl2;
380         last_ads->ds_ctl3 = ads->ds_ctl3;
381 }
382
383 void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
384                                 u32 aggrLen)
385 {
386         struct ar5416_desc *ads = AR5416DESC(ds);
387
388         ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
389         ads->ds_ctl6 &= ~AR_AggrLen;
390         ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
391 }
392
393 void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
394                                  u32 numDelims)
395 {
396         struct ar5416_desc *ads = AR5416DESC(ds);
397         unsigned int ctl6;
398
399         ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
400
401         ctl6 = ads->ds_ctl6;
402         ctl6 &= ~AR_PadDelim;
403         ctl6 |= SM(numDelims, AR_PadDelim);
404         ads->ds_ctl6 = ctl6;
405 }
406
407 void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
408 {
409         struct ar5416_desc *ads = AR5416DESC(ds);
410
411         ads->ds_ctl1 |= AR_IsAggr;
412         ads->ds_ctl1 &= ~AR_MoreAggr;
413         ads->ds_ctl6 &= ~AR_PadDelim;
414 }
415
416 void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
417 {
418         struct ar5416_desc *ads = AR5416DESC(ds);
419
420         ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
421 }
422
423 void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
424                                    u32 burstDuration)
425 {
426         struct ar5416_desc *ads = AR5416DESC(ds);
427
428         ads->ds_ctl2 &= ~AR_BurstDur;
429         ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
430 }
431
432 void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
433                                      u32 vmf)
434 {
435         struct ar5416_desc *ads = AR5416DESC(ds);
436
437         if (vmf)
438                 ads->ds_ctl0 |= AR_VirtMoreFrag;
439         else
440                 ads->ds_ctl0 &= ~AR_VirtMoreFrag;
441 }
442
443 void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
444 {
445         *txqs &= ah->intr_txqs;
446         ah->intr_txqs &= ~(*txqs);
447 }
448
449 bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
450                             const struct ath9k_tx_queue_info *qinfo)
451 {
452         u32 cw;
453         struct ath9k_hw_capabilities *pCap = &ah->caps;
454         struct ath9k_tx_queue_info *qi;
455
456         if (q >= pCap->total_queues) {
457                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
458                 return false;
459         }
460
461         qi = &ah->txq[q];
462         if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
463                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
464                 return false;
465         }
466
467         DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %p\n", qi);
468
469         qi->tqi_ver = qinfo->tqi_ver;
470         qi->tqi_subtype = qinfo->tqi_subtype;
471         qi->tqi_qflags = qinfo->tqi_qflags;
472         qi->tqi_priority = qinfo->tqi_priority;
473         if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
474                 qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
475         else
476                 qi->tqi_aifs = INIT_AIFS;
477         if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
478                 cw = min(qinfo->tqi_cwmin, 1024U);
479                 qi->tqi_cwmin = 1;
480                 while (qi->tqi_cwmin < cw)
481                         qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
482         } else
483                 qi->tqi_cwmin = qinfo->tqi_cwmin;
484         if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
485                 cw = min(qinfo->tqi_cwmax, 1024U);
486                 qi->tqi_cwmax = 1;
487                 while (qi->tqi_cwmax < cw)
488                         qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
489         } else
490                 qi->tqi_cwmax = INIT_CWMAX;
491
492         if (qinfo->tqi_shretry != 0)
493                 qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
494         else
495                 qi->tqi_shretry = INIT_SH_RETRY;
496         if (qinfo->tqi_lgretry != 0)
497                 qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
498         else
499                 qi->tqi_lgretry = INIT_LG_RETRY;
500         qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
501         qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
502         qi->tqi_burstTime = qinfo->tqi_burstTime;
503         qi->tqi_readyTime = qinfo->tqi_readyTime;
504
505         switch (qinfo->tqi_subtype) {
506         case ATH9K_WME_UPSD:
507                 if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
508                         qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
509                 break;
510         default:
511                 break;
512         }
513
514         return true;
515 }
516
517 bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
518                             struct ath9k_tx_queue_info *qinfo)
519 {
520         struct ath9k_hw_capabilities *pCap = &ah->caps;
521         struct ath9k_tx_queue_info *qi;
522
523         if (q >= pCap->total_queues) {
524                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
525                 return false;
526         }
527
528         qi = &ah->txq[q];
529         if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
530                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
531                 return false;
532         }
533
534         qinfo->tqi_qflags = qi->tqi_qflags;
535         qinfo->tqi_ver = qi->tqi_ver;
536         qinfo->tqi_subtype = qi->tqi_subtype;
537         qinfo->tqi_qflags = qi->tqi_qflags;
538         qinfo->tqi_priority = qi->tqi_priority;
539         qinfo->tqi_aifs = qi->tqi_aifs;
540         qinfo->tqi_cwmin = qi->tqi_cwmin;
541         qinfo->tqi_cwmax = qi->tqi_cwmax;
542         qinfo->tqi_shretry = qi->tqi_shretry;
543         qinfo->tqi_lgretry = qi->tqi_lgretry;
544         qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
545         qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
546         qinfo->tqi_burstTime = qi->tqi_burstTime;
547         qinfo->tqi_readyTime = qi->tqi_readyTime;
548
549         return true;
550 }
551
552 int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
553                           const struct ath9k_tx_queue_info *qinfo)
554 {
555         struct ath9k_tx_queue_info *qi;
556         struct ath9k_hw_capabilities *pCap = &ah->caps;
557         int q;
558
559         switch (type) {
560         case ATH9K_TX_QUEUE_BEACON:
561                 q = pCap->total_queues - 1;
562                 break;
563         case ATH9K_TX_QUEUE_CAB:
564                 q = pCap->total_queues - 2;
565                 break;
566         case ATH9K_TX_QUEUE_PSPOLL:
567                 q = 1;
568                 break;
569         case ATH9K_TX_QUEUE_UAPSD:
570                 q = pCap->total_queues - 3;
571                 break;
572         case ATH9K_TX_QUEUE_DATA:
573                 for (q = 0; q < pCap->total_queues; q++)
574                         if (ah->txq[q].tqi_type ==
575                             ATH9K_TX_QUEUE_INACTIVE)
576                                 break;
577                 if (q == pCap->total_queues) {
578                         DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
579                                 "no available tx queue\n");
580                         return -1;
581                 }
582                 break;
583         default:
584                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "bad tx queue type %u\n", type);
585                 return -1;
586         }
587
588         DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q);
589
590         qi = &ah->txq[q];
591         if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
592                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
593                         "tx queue %u already active\n", q);
594                 return -1;
595         }
596         memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
597         qi->tqi_type = type;
598         if (qinfo == NULL) {
599                 qi->tqi_qflags =
600                         TXQ_FLAG_TXOKINT_ENABLE
601                         | TXQ_FLAG_TXERRINT_ENABLE
602                         | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
603                 qi->tqi_aifs = INIT_AIFS;
604                 qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
605                 qi->tqi_cwmax = INIT_CWMAX;
606                 qi->tqi_shretry = INIT_SH_RETRY;
607                 qi->tqi_lgretry = INIT_LG_RETRY;
608                 qi->tqi_physCompBuf = 0;
609         } else {
610                 qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
611                 (void) ath9k_hw_set_txq_props(ah, q, qinfo);
612         }
613
614         return q;
615 }
616
617 bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
618 {
619         struct ath9k_hw_capabilities *pCap = &ah->caps;
620         struct ath9k_tx_queue_info *qi;
621
622         if (q >= pCap->total_queues) {
623                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
624                 return false;
625         }
626         qi = &ah->txq[q];
627         if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
628                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q);
629                 return false;
630         }
631
632         DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "release queue %u\n", q);
633
634         qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
635         ah->txok_interrupt_mask &= ~(1 << q);
636         ah->txerr_interrupt_mask &= ~(1 << q);
637         ah->txdesc_interrupt_mask &= ~(1 << q);
638         ah->txeol_interrupt_mask &= ~(1 << q);
639         ah->txurn_interrupt_mask &= ~(1 << q);
640         ath9k_hw_set_txq_interrupts(ah, qi);
641
642         return true;
643 }
644
645 bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
646 {
647         struct ath9k_hw_capabilities *pCap = &ah->caps;
648         struct ath9k_channel *chan = ah->curchan;
649         struct ath9k_tx_queue_info *qi;
650         u32 cwMin, chanCwMin, value;
651
652         if (q >= pCap->total_queues) {
653                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
654                 return false;
655         }
656
657         qi = &ah->txq[q];
658         if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
659                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q);
660                 return true;
661         }
662
663         DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "reset queue %u\n", q);
664
665         if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
666                 if (chan && IS_CHAN_B(chan))
667                         chanCwMin = INIT_CWMIN_11B;
668                 else
669                         chanCwMin = INIT_CWMIN;
670
671                 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
672         } else
673                 cwMin = qi->tqi_cwmin;
674
675         REG_WRITE(ah, AR_DLCL_IFS(q),
676                   SM(cwMin, AR_D_LCL_IFS_CWMIN) |
677                   SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
678                   SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
679
680         REG_WRITE(ah, AR_DRETRY_LIMIT(q),
681                   SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
682                   SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
683                   SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
684
685         REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
686         REG_WRITE(ah, AR_DMISC(q),
687                   AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
688
689         if (qi->tqi_cbrPeriod) {
690                 REG_WRITE(ah, AR_QCBRCFG(q),
691                           SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
692                           SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
693                 REG_WRITE(ah, AR_QMISC(q),
694                           REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
695                           (qi->tqi_cbrOverflowLimit ?
696                            AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
697         }
698         if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
699                 REG_WRITE(ah, AR_QRDYTIMECFG(q),
700                           SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
701                           AR_Q_RDYTIMECFG_EN);
702         }
703
704         REG_WRITE(ah, AR_DCHNTIME(q),
705                   SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
706                   (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
707
708         if (qi->tqi_burstTime
709             && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
710                 REG_WRITE(ah, AR_QMISC(q),
711                           REG_READ(ah, AR_QMISC(q)) |
712                           AR_Q_MISC_RDYTIME_EXP_POLICY);
713
714         }
715
716         if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
717                 REG_WRITE(ah, AR_DMISC(q),
718                           REG_READ(ah, AR_DMISC(q)) |
719                           AR_D_MISC_POST_FR_BKOFF_DIS);
720         }
721         if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
722                 REG_WRITE(ah, AR_DMISC(q),
723                           REG_READ(ah, AR_DMISC(q)) |
724                           AR_D_MISC_FRAG_BKOFF_EN);
725         }
726         switch (qi->tqi_type) {
727         case ATH9K_TX_QUEUE_BEACON:
728                 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
729                           | AR_Q_MISC_FSP_DBA_GATED
730                           | AR_Q_MISC_BEACON_USE
731                           | AR_Q_MISC_CBR_INCR_DIS1);
732
733                 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
734                           | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
735                              AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
736                           | AR_D_MISC_BEACON_USE
737                           | AR_D_MISC_POST_FR_BKOFF_DIS);
738                 break;
739         case ATH9K_TX_QUEUE_CAB:
740                 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
741                           | AR_Q_MISC_FSP_DBA_GATED
742                           | AR_Q_MISC_CBR_INCR_DIS1
743                           | AR_Q_MISC_CBR_INCR_DIS0);
744                 value = (qi->tqi_readyTime -
745                          (ah->config.sw_beacon_response_time -
746                           ah->config.dma_beacon_response_time) -
747                          ah->config.additional_swba_backoff) * 1024;
748                 REG_WRITE(ah, AR_QRDYTIMECFG(q),
749                           value | AR_Q_RDYTIMECFG_EN);
750                 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
751                           | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
752                              AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
753                 break;
754         case ATH9K_TX_QUEUE_PSPOLL:
755                 REG_WRITE(ah, AR_QMISC(q),
756                           REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
757                 break;
758         case ATH9K_TX_QUEUE_UAPSD:
759                 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
760                           AR_D_MISC_POST_FR_BKOFF_DIS);
761                 break;
762         default:
763                 break;
764         }
765
766         if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
767                 REG_WRITE(ah, AR_DMISC(q),
768                           REG_READ(ah, AR_DMISC(q)) |
769                           SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
770                              AR_D_MISC_ARB_LOCKOUT_CNTRL) |
771                           AR_D_MISC_POST_FR_BKOFF_DIS);
772         }
773
774         if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
775                 ah->txok_interrupt_mask |= 1 << q;
776         else
777                 ah->txok_interrupt_mask &= ~(1 << q);
778         if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
779                 ah->txerr_interrupt_mask |= 1 << q;
780         else
781                 ah->txerr_interrupt_mask &= ~(1 << q);
782         if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
783                 ah->txdesc_interrupt_mask |= 1 << q;
784         else
785                 ah->txdesc_interrupt_mask &= ~(1 << q);
786         if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
787                 ah->txeol_interrupt_mask |= 1 << q;
788         else
789                 ah->txeol_interrupt_mask &= ~(1 << q);
790         if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
791                 ah->txurn_interrupt_mask |= 1 << q;
792         else
793                 ah->txurn_interrupt_mask &= ~(1 << q);
794         ath9k_hw_set_txq_interrupts(ah, qi);
795
796         return true;
797 }
798
799 int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
800                         u32 pa, struct ath_desc *nds, u64 tsf)
801 {
802         struct ar5416_desc ads;
803         struct ar5416_desc *adsp = AR5416DESC(ds);
804         u32 phyerr;
805
806         if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
807                 return -EINPROGRESS;
808
809         ads.u.rx = adsp->u.rx;
810
811         ds->ds_rxstat.rs_status = 0;
812         ds->ds_rxstat.rs_flags = 0;
813
814         ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
815         ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
816
817         ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
818         ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
819         ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
820         ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
821         ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
822         ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
823         ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
824         if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
825                 ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
826         else
827                 ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
828
829         ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
830         ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
831
832         ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
833         ds->ds_rxstat.rs_moreaggr =
834                 (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
835         ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
836         ds->ds_rxstat.rs_flags =
837                 (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
838         ds->ds_rxstat.rs_flags |=
839                 (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
840
841         if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
842                 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
843         if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
844                 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
845         if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
846                 ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
847
848         if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
849                 if (ads.ds_rxstatus8 & AR_CRCErr)
850                         ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
851                 else if (ads.ds_rxstatus8 & AR_PHYErr) {
852                         ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
853                         phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
854                         ds->ds_rxstat.rs_phyerr = phyerr;
855                 } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
856                         ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
857                 else if (ads.ds_rxstatus8 & AR_MichaelErr)
858                         ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
859         }
860
861         return 0;
862 }
863
864 bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
865                           u32 size, u32 flags)
866 {
867         struct ar5416_desc *ads = AR5416DESC(ds);
868         struct ath9k_hw_capabilities *pCap = &ah->caps;
869
870         ads->ds_ctl1 = size & AR_BufLen;
871         if (flags & ATH9K_RXDESC_INTREQ)
872                 ads->ds_ctl1 |= AR_RxIntrReq;
873
874         ads->ds_rxstatus8 &= ~AR_RxDone;
875         if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
876                 memset(&(ads->u), 0, sizeof(ads->u));
877
878         return true;
879 }
880
881 bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
882 {
883         u32 reg;
884
885         if (set) {
886                 REG_SET_BIT(ah, AR_DIAG_SW,
887                             (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
888
889                 if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE,
890                                    0, AH_WAIT_TIMEOUT)) {
891                         REG_CLR_BIT(ah, AR_DIAG_SW,
892                                     (AR_DIAG_RX_DIS |
893                                      AR_DIAG_RX_ABORT));
894
895                         reg = REG_READ(ah, AR_OBS_BUS_1);
896                         DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
897                                 "rx failed to go idle in 10 ms RXSM=0x%x\n", reg);
898
899                         return false;
900                 }
901         } else {
902                 REG_CLR_BIT(ah, AR_DIAG_SW,
903                             (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
904         }
905
906         return true;
907 }
908
909 void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
910 {
911         REG_WRITE(ah, AR_RXDP, rxdp);
912 }
913
914 void ath9k_hw_rxena(struct ath_hw *ah)
915 {
916         REG_WRITE(ah, AR_CR, AR_CR_RXE);
917 }
918
919 void ath9k_hw_startpcureceive(struct ath_hw *ah)
920 {
921         ath9k_enable_mib_counters(ah);
922
923         ath9k_ani_reset(ah);
924
925         REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
926 }
927
928 void ath9k_hw_stoppcurecv(struct ath_hw *ah)
929 {
930         REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
931
932         ath9k_hw_disable_mib_counters(ah);
933 }
934
935 bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
936 {
937 #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
938 #define AH_RX_TIME_QUANTUM     100     /* usec */
939
940         int i;
941
942         REG_WRITE(ah, AR_CR, AR_CR_RXD);
943
944         /* Wait for rx enable bit to go low */
945         for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
946                 if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
947                         break;
948                 udelay(AH_TIME_QUANTUM);
949         }
950
951         if (i == 0) {
952                 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
953                         "dma failed to stop in %d ms "
954                         "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
955                         AH_RX_STOP_DMA_TIMEOUT / 1000,
956                         REG_READ(ah, AR_CR),
957                         REG_READ(ah, AR_DIAG_SW));
958                 return false;
959         } else {
960                 return true;
961         }
962
963 #undef AH_RX_TIME_QUANTUM
964 #undef AH_RX_STOP_DMA_TIMEOUT
965 }