ath5k: fix hardware queue index assignment
[pandora-kernel.git] / drivers / net / wireless / ath / ath5k / qcu.c
1 /*
2  * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3  * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  */
18
19 /********************************************\
20 Queue Control Unit, DFS Control Unit Functions
21 \********************************************/
22
23 #include "ath5k.h"
24 #include "reg.h"
25 #include "debug.h"
26
27
28 /******************\
29 * Helper functions *
30 \******************/
31
32 /*
33  * Get number of pending frames
34  * for a specific queue [5211+]
35  */
36 u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
37 {
38         u32 pending;
39         AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
40
41         /* Return if queue is declared inactive */
42         if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
43                 return false;
44
45         /* XXX: How about AR5K_CFG_TXCNT ? */
46         if (ah->ah_version == AR5K_AR5210)
47                 return false;
48
49         pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
50         pending &= AR5K_QCU_STS_FRMPENDCNT;
51
52         /* It's possible to have no frames pending even if TXE
53          * is set. To indicate that q has not stopped return
54          * true */
55         if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
56                 return true;
57
58         return pending;
59 }
60
61 /*
62  * Set a transmit queue inactive
63  */
64 void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
65 {
66         if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
67                 return;
68
69         /* This queue will be skipped in further operations */
70         ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
71         /*For SIMR setup*/
72         AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
73 }
74
75 /*
76  * Make sure cw is a power of 2 minus 1 and smaller than 1024
77  */
78 static u16 ath5k_cw_validate(u16 cw_req)
79 {
80         u32 cw = 1;
81         cw_req = min(cw_req, (u16)1023);
82
83         while (cw < cw_req)
84                 cw = (cw << 1) | 1;
85
86         return cw;
87 }
88
89 /*
90  * Get properties for a transmit queue
91  */
92 int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
93                 struct ath5k_txq_info *queue_info)
94 {
95         memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
96         return 0;
97 }
98
99 /*
100  * Set properties for a transmit queue
101  */
102 int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
103                                 const struct ath5k_txq_info *qinfo)
104 {
105         struct ath5k_txq_info *qi;
106
107         AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
108
109         qi = &ah->ah_txq[queue];
110
111         if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE)
112                 return -EIO;
113
114         /* copy and validate values */
115         qi->tqi_type = qinfo->tqi_type;
116         qi->tqi_subtype = qinfo->tqi_subtype;
117         qi->tqi_flags = qinfo->tqi_flags;
118         /*
119          * According to the docs: Although the AIFS field is 8 bit wide,
120          * the maximum supported value is 0xFC. Setting it higher than that
121          * will cause the DCU to hang.
122          */
123         qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC);
124         qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min);
125         qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max);
126         qi->tqi_cbr_period = qinfo->tqi_cbr_period;
127         qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit;
128         qi->tqi_burst_time = qinfo->tqi_burst_time;
129         qi->tqi_ready_time = qinfo->tqi_ready_time;
130
131         /*XXX: Is this supported on 5210 ?*/
132         /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/
133         if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA &&
134                 ((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
135                  (qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
136              qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
137                 qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
138
139         return 0;
140 }
141
142 /*
143  * Initialize a transmit queue
144  */
145 int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
146                 struct ath5k_txq_info *queue_info)
147 {
148         unsigned int queue;
149         int ret;
150
151         /*
152          * Get queue by type
153          */
154         /* 5210 only has 2 queues */
155         if (ah->ah_capabilities.cap_queues.q_tx_num == 2) {
156                 switch (queue_type) {
157                 case AR5K_TX_QUEUE_DATA:
158                         queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
159                         break;
160                 case AR5K_TX_QUEUE_BEACON:
161                 case AR5K_TX_QUEUE_CAB:
162                         queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
163                         break;
164                 default:
165                         return -EINVAL;
166                 }
167         } else {
168                 switch (queue_type) {
169                 case AR5K_TX_QUEUE_DATA:
170                         queue = queue_info->tqi_subtype;
171                         break;
172                 case AR5K_TX_QUEUE_UAPSD:
173                         queue = AR5K_TX_QUEUE_ID_UAPSD;
174                         break;
175                 case AR5K_TX_QUEUE_BEACON:
176                         queue = AR5K_TX_QUEUE_ID_BEACON;
177                         break;
178                 case AR5K_TX_QUEUE_CAB:
179                         queue = AR5K_TX_QUEUE_ID_CAB;
180                         break;
181                 default:
182                         return -EINVAL;
183                 }
184         }
185
186         /*
187          * Setup internal queue structure
188          */
189         memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
190         ah->ah_txq[queue].tqi_type = queue_type;
191
192         if (queue_info != NULL) {
193                 queue_info->tqi_type = queue_type;
194                 ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info);
195                 if (ret)
196                         return ret;
197         }
198
199         /*
200          * We use ah_txq_status to hold a temp value for
201          * the Secondary interrupt mask registers on 5211+
202          * check out ath5k_hw_reset_tx_queue
203          */
204         AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
205
206         return queue;
207 }
208
209
210 /*******************************\
211 * Single QCU/DCU initialization *
212 \*******************************/
213
214 /*
215  * Set tx retry limits on DCU
216  */
217 void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
218                                   unsigned int queue)
219 {
220         /* Single data queue on AR5210 */
221         if (ah->ah_version == AR5K_AR5210) {
222                 struct ath5k_txq_info *tq = &ah->ah_txq[queue];
223
224                 if (queue > 0)
225                         return;
226
227                 ath5k_hw_reg_write(ah,
228                         (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
229                         | AR5K_REG_SM(ah->ah_retry_long,
230                                       AR5K_NODCU_RETRY_LMT_SLG_RETRY)
231                         | AR5K_REG_SM(ah->ah_retry_short,
232                                       AR5K_NODCU_RETRY_LMT_SSH_RETRY)
233                         | AR5K_REG_SM(ah->ah_retry_long,
234                                       AR5K_NODCU_RETRY_LMT_LG_RETRY)
235                         | AR5K_REG_SM(ah->ah_retry_short,
236                                       AR5K_NODCU_RETRY_LMT_SH_RETRY),
237                         AR5K_NODCU_RETRY_LMT);
238         /* DCU on AR5211+ */
239         } else {
240                 ath5k_hw_reg_write(ah,
241                         AR5K_REG_SM(ah->ah_retry_long,
242                                     AR5K_DCU_RETRY_LMT_RTS)
243                         | AR5K_REG_SM(ah->ah_retry_long,
244                                       AR5K_DCU_RETRY_LMT_STA_RTS)
245                         | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short),
246                                       AR5K_DCU_RETRY_LMT_STA_DATA),
247                         AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
248         }
249 }
250
251 /**
252  * ath5k_hw_reset_tx_queue - Initialize a single hw queue
253  *
254  * @ah The &struct ath5k_hw
255  * @queue The hw queue number
256  *
257  * Set DFS properties for the given transmit queue on DCU
258  * and configures all queue-specific parameters.
259  */
260 int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
261 {
262         struct ath5k_txq_info *tq = &ah->ah_txq[queue];
263
264         AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
265
266         tq = &ah->ah_txq[queue];
267
268         /* Skip if queue inactive or if we are on AR5210
269          * that doesn't have QCU/DCU */
270         if ((ah->ah_version == AR5K_AR5210) ||
271         (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE))
272                 return 0;
273
274         /*
275          * Set contention window (cw_min/cw_max)
276          * and arbitrated interframe space (aifs)...
277          */
278         ath5k_hw_reg_write(ah,
279                 AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
280                 AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
281                 AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
282                 AR5K_QUEUE_DFS_LOCAL_IFS(queue));
283
284         /*
285          * Set tx retry limits for this queue
286          */
287         ath5k_hw_set_tx_retry_limits(ah, queue);
288
289
290         /*
291          * Set misc registers
292          */
293
294         /* Enable DCU to wait for next fragment from QCU */
295         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
296                                 AR5K_DCU_MISC_FRAG_WAIT);
297
298         /* On Maui and Spirit use the global seqnum on DCU */
299         if (ah->ah_mac_version < AR5K_SREV_AR5211)
300                 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
301                                         AR5K_DCU_MISC_SEQNUM_CTL);
302
303         /* Constant bit rate period */
304         if (tq->tqi_cbr_period) {
305                 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
306                                         AR5K_QCU_CBRCFG_INTVAL) |
307                                         AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
308                                         AR5K_QCU_CBRCFG_ORN_THRES),
309                                         AR5K_QUEUE_CBRCFG(queue));
310
311                 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
312                                         AR5K_QCU_MISC_FRSHED_CBR);
313
314                 if (tq->tqi_cbr_overflow_limit)
315                         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
316                                         AR5K_QCU_MISC_CBR_THRES_ENABLE);
317         }
318
319         /* Ready time interval */
320         if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB))
321                 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
322                                         AR5K_QCU_RDYTIMECFG_INTVAL) |
323                                         AR5K_QCU_RDYTIMECFG_ENABLE,
324                                         AR5K_QUEUE_RDYTIMECFG(queue));
325
326         if (tq->tqi_burst_time) {
327                 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
328                                         AR5K_DCU_CHAN_TIME_DUR) |
329                                         AR5K_DCU_CHAN_TIME_ENABLE,
330                                         AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
331
332                 if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
333                         AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
334                                         AR5K_QCU_MISC_RDY_VEOL_POLICY);
335         }
336
337         /* Enable/disable Post frame backoff */
338         if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
339                 ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
340                                         AR5K_QUEUE_DFS_MISC(queue));
341
342         /* Enable/disable fragmentation burst backoff */
343         if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
344                 ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
345                                         AR5K_QUEUE_DFS_MISC(queue));
346
347         /*
348          * Set registers by queue type
349          */
350         switch (tq->tqi_type) {
351         case AR5K_TX_QUEUE_BEACON:
352                 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
353                                 AR5K_QCU_MISC_FRSHED_DBA_GT |
354                                 AR5K_QCU_MISC_CBREXP_BCN_DIS |
355                                 AR5K_QCU_MISC_BCN_ENABLE);
356
357                 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
358                                 (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
359                                 AR5K_DCU_MISC_ARBLOCK_CTL_S) |
360                                 AR5K_DCU_MISC_ARBLOCK_IGNORE |
361                                 AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
362                                 AR5K_DCU_MISC_BCN_ENABLE);
363                 break;
364
365         case AR5K_TX_QUEUE_CAB:
366                 /* XXX: use BCN_SENT_GT, if we can figure out how */
367                 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
368                                         AR5K_QCU_MISC_FRSHED_DBA_GT |
369                                         AR5K_QCU_MISC_CBREXP_DIS |
370                                         AR5K_QCU_MISC_CBREXP_BCN_DIS);
371
372                 ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
373                                         (AR5K_TUNE_SW_BEACON_RESP -
374                                         AR5K_TUNE_DMA_BEACON_RESP) -
375                                 AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
376                                         AR5K_QCU_RDYTIMECFG_ENABLE,
377                                         AR5K_QUEUE_RDYTIMECFG(queue));
378
379                 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
380                                         (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
381                                         AR5K_DCU_MISC_ARBLOCK_CTL_S));
382                 break;
383
384         case AR5K_TX_QUEUE_UAPSD:
385                 AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
386                                         AR5K_QCU_MISC_CBREXP_DIS);
387                 break;
388
389         case AR5K_TX_QUEUE_DATA:
390         default:
391                         break;
392         }
393
394         /* TODO: Handle frame compression */
395
396         /*
397          * Enable interrupts for this tx queue
398          * in the secondary interrupt mask registers
399          */
400         if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
401                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
402
403         if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
404                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
405
406         if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
407                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
408
409         if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
410                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
411
412         if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
413                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
414
415         if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
416                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
417
418         if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
419                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
420
421         if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
422                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
423
424         if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
425                 AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
426
427         /* Update secondary interrupt mask registers */
428
429         /* Filter out inactive queues */
430         ah->ah_txq_imr_txok &= ah->ah_txq_status;
431         ah->ah_txq_imr_txerr &= ah->ah_txq_status;
432         ah->ah_txq_imr_txurn &= ah->ah_txq_status;
433         ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
434         ah->ah_txq_imr_txeol &= ah->ah_txq_status;
435         ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
436         ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
437         ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
438         ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
439
440         ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
441                                         AR5K_SIMR0_QCU_TXOK) |
442                                         AR5K_REG_SM(ah->ah_txq_imr_txdesc,
443                                         AR5K_SIMR0_QCU_TXDESC),
444                                         AR5K_SIMR0);
445
446         ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
447                                         AR5K_SIMR1_QCU_TXERR) |
448                                         AR5K_REG_SM(ah->ah_txq_imr_txeol,
449                                         AR5K_SIMR1_QCU_TXEOL),
450                                         AR5K_SIMR1);
451
452         /* Update SIMR2 but don't overwrite rest simr2 settings */
453         AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
454         AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
455                                 AR5K_REG_SM(ah->ah_txq_imr_txurn,
456                                 AR5K_SIMR2_QCU_TXURN));
457
458         ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
459                                 AR5K_SIMR3_QCBRORN) |
460                                 AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
461                                 AR5K_SIMR3_QCBRURN),
462                                 AR5K_SIMR3);
463
464         ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
465                                 AR5K_SIMR4_QTRIG), AR5K_SIMR4);
466
467         /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
468         ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
469                                 AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
470
471         /* No queue has TXNOFRM enabled, disable the interrupt
472          * by setting AR5K_TXNOFRM to zero */
473         if (ah->ah_txq_imr_nofrm == 0)
474                 ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
475
476         /* Set QCU mask for this DCU to save power */
477         AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
478
479         return 0;
480 }
481
482
483 /**************************\
484 * Global QCU/DCU functions *
485 \**************************/
486
487 /**
488  * ath5k_hw_set_ifs_intervals  - Set global inter-frame spaces on DCU
489  *
490  * @ah The &struct ath5k_hw
491  * @slot_time Slot time in us
492  *
493  * Sets the global IFS intervals on DCU (also works on AR5210) for
494  * the given slot time and the current bwmode.
495  */
496 int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
497 {
498         struct ieee80211_channel *channel = ah->ah_current_channel;
499         struct ieee80211_rate *rate;
500         u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
501         u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
502
503         if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
504                 return -EINVAL;
505
506         sifs = ath5k_hw_get_default_sifs(ah);
507         sifs_clock = ath5k_hw_htoclock(ah, sifs - 2);
508
509         /* EIFS
510          * Txtime of ack at lowest rate + SIFS + DIFS
511          * (DIFS = SIFS + 2 * Slot time)
512          *
513          * Note: HAL has some predefined values for EIFS
514          * Turbo:   (37 + 2 * 6)
515          * Default: (74 + 2 * 9)
516          * Half:    (149 + 2 * 13)
517          * Quarter: (298 + 2 * 21)
518          *
519          * (74 + 2 * 6) for AR5210 default and turbo !
520          *
521          * According to the formula we have
522          * ack_tx_time = 25 for turbo and
523          * ack_tx_time = 42.5 * clock multiplier
524          * for default/half/quarter.
525          *
526          * This can't be right, 42 is what we would get
527          * from ath5k_hw_get_frame_dur_for_bwmode or
528          * ieee80211_generic_frame_duration for zero frame
529          * length and without SIFS !
530          *
531          * Also we have different lowest rate for 802.11a
532          */
533         if (channel->band == IEEE80211_BAND_5GHZ)
534                 rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
535         else
536                 rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
537
538         ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false);
539
540         /* ack_tx_time includes an SIFS already */
541         eifs = ack_tx_time + sifs + 2 * slot_time;
542         eifs_clock = ath5k_hw_htoclock(ah, eifs);
543
544         /* Set IFS settings on AR5210 */
545         if (ah->ah_version == AR5K_AR5210) {
546                 u32 pifs, pifs_clock, difs, difs_clock;
547
548                 /* Set slot time */
549                 ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
550
551                 /* Set EIFS */
552                 eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS);
553
554                 /* PIFS = Slot time + SIFS */
555                 pifs = slot_time + sifs;
556                 pifs_clock = ath5k_hw_htoclock(ah, pifs);
557                 pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS);
558
559                 /* DIFS = SIFS + 2 * Slot time */
560                 difs = sifs + 2 * slot_time;
561                 difs_clock = ath5k_hw_htoclock(ah, difs);
562
563                 /* Set SIFS/DIFS */
564                 ath5k_hw_reg_write(ah, (difs_clock <<
565                                 AR5K_IFS0_DIFS_S) | sifs_clock,
566                                 AR5K_IFS0);
567
568                 /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */
569                 ath5k_hw_reg_write(ah, pifs_clock | eifs_clock |
570                                 (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S),
571                                 AR5K_IFS1);
572
573                 return 0;
574         }
575
576         /* Set IFS slot time */
577         ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
578
579         /* Set EIFS interval */
580         ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS);
581
582         /* Set SIFS interval in usecs */
583         AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
584                                 AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC,
585                                 sifs);
586
587         /* Set SIFS interval in clock cycles */
588         ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
589
590         return 0;
591 }
592
593
594 int ath5k_hw_init_queues(struct ath5k_hw *ah)
595 {
596         int i, ret;
597
598         /* TODO: HW Compression support for data queues */
599         /* TODO: Burst prefetch for data queues */
600
601         /*
602          * Reset queues and start beacon timers at the end of the reset routine
603          * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
604          * Note: If we want we can assign multiple qcus on one dcu.
605          */
606         if (ah->ah_version != AR5K_AR5210)
607                 for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
608                         ret = ath5k_hw_reset_tx_queue(ah, i);
609                         if (ret) {
610                                 ATH5K_ERR(ah,
611                                         "failed to reset TX queue #%d\n", i);
612                                 return ret;
613                         }
614                 }
615         else
616                 /* No QCU/DCU on AR5210, just set tx
617                  * retry limits. We set IFS parameters
618                  * on ath5k_hw_set_ifs_intervals */
619                 ath5k_hw_set_tx_retry_limits(ah, 0);
620
621         /* Set the turbo flag when operating on 40MHz */
622         if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
623                 AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
624                                 AR5K_DCU_GBL_IFS_MISC_TURBO_MODE);
625
626         /* If we didn't set IFS timings through
627          * ath5k_hw_set_coverage_class make sure
628          * we set them here */
629         if (!ah->ah_coverage_class) {
630                 unsigned int slot_time = ath5k_hw_get_default_slottime(ah);
631                 ath5k_hw_set_ifs_intervals(ah, slot_time);
632         }
633
634         return 0;
635 }