qcu.c (d4bbf7e7759afc172e2bfbc5c416324590049cdd) qcu.c (c47faa364cfb249d5d7670fb7293a6f9acd8aa9e)
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/********************************************\
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/********************************************\
20Queue Control Unit, DFS Control Unit Functions
20Queue Control Unit, DCF Control Unit Functions
21\********************************************/
22
23#include "ath5k.h"
24#include "reg.h"
25#include "debug.h"
26
21\********************************************/
22
23#include "ath5k.h"
24#include "reg.h"
25#include "debug.h"
26
27/**
28 * DOC: Queue Control Unit (QCU)/DCF Control Unit (DCU) functions
29 *
30 * Here we setup parameters for the 12 available TX queues. Note that
31 * on the various registers we can usually only map the first 10 of them so
32 * basically we have 10 queues to play with. Each queue has a matching
33 * QCU that controls when the queue will get triggered and multiple QCUs
34 * can be mapped to a single DCU that controls the various DFS parameters
35 * for the various queues. In our setup we have a 1:1 mapping between QCUs
36 * and DCUs allowing us to have different DFS settings for each queue.
37 *
38 * When a frame goes into a TX queue, QCU decides when it'll trigger a
39 * transmission based on various criteria (such as how many data we have inside
40 * it's buffer or -if it's a beacon queue- if it's time to fire up the queue
41 * based on TSF etc), DCU adds backoff, IFSes etc and then a scheduler
42 * (arbitrator) decides the priority of each QCU based on it's configuration
43 * (e.g. beacons are always transmitted when they leave DCU bypassing all other
44 * frames from other queues waiting to be transmitted). After a frame leaves
45 * the DCU it goes to PCU for further processing and then to PHY for
46 * the actual transmission.
47 */
27
48
49
28/******************\
29* Helper functions *
30\******************/
31
50/******************\
51* Helper functions *
52\******************/
53
32/*
33 * Get number of pending frames
34 * for a specific queue [5211+]
54/**
55 * ath5k_hw_num_tx_pending() - Get number of pending frames for a given queue
56 * @ah: The &struct ath5k_hw
57 * @queue: The hw queue number
35 */
58 */
36u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
59u32
60ath5k_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

--- 8 unchanged lines hidden (view full) ---

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 u32 pending;
63 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
64
65 /* Return if queue is declared inactive */
66 if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
67 return false;
68

--- 8 unchanged lines hidden (view full) ---

77 * is set. To indicate that q has not stopped return
78 * true */
79 if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
80 return true;
81
82 return pending;
83}
84
61/*
62 * Set a transmit queue inactive
85/**
86 * ath5k_hw_release_tx_queue() - Set a transmit queue inactive
87 * @ah: The &struct ath5k_hw
88 * @queue: The hw queue number
63 */
89 */
64void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
90void
91ath5k_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
92{
93 if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
94 return;
95
96 /* This queue will be skipped in further operations */
97 ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
98 /*For SIMR setup*/
99 AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
100}
101
75/*
102/**
103 * ath5k_cw_validate() - Make sure the given cw is valid
104 * @cw_req: The contention window value to check
105 *
76 * Make sure cw is a power of 2 minus 1 and smaller than 1024
77 */
106 * Make sure cw is a power of 2 minus 1 and smaller than 1024
107 */
78static u16 ath5k_cw_validate(u16 cw_req)
108static u16
109ath5k_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
110{
111 u32 cw = 1;
112 cw_req = min(cw_req, (u16)1023);
113
114 while (cw < cw_req)
115 cw = (cw << 1) | 1;
116
117 return cw;
118}
119
89/*
90 * Get properties for a transmit queue
120/**
121 * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue
122 * @ah: The &struct ath5k_hw
123 * @queue: The hw queue number
124 * @queue_info: The &struct ath5k_txq_info to fill
91 */
125 */
92int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
126int
127ath5k_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
128 struct ath5k_txq_info *queue_info)
129{
130 memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
131 return 0;
132}
133
99/*
100 * Set properties for a transmit queue
134/**
135 * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue
136 * @ah: The &struct ath5k_hw
137 * @queue: The hw queue number
138 * @qinfo: The &struct ath5k_txq_info to use
139 *
140 * Returns 0 on success or -EIO if queue is inactive
101 */
141 */
102int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
142int
143ath5k_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

--- 23 unchanged lines hidden (view full) ---

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
144 const struct ath5k_txq_info *qinfo)
145{
146 struct ath5k_txq_info *qi;
147
148 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
149
150 qi = &ah->ah_txq[queue];
151

--- 23 unchanged lines hidden (view full) ---

175 ((qinfo->tqi_subtype == AR5K_WME_AC_VI) ||
176 (qinfo->tqi_subtype == AR5K_WME_AC_VO))) ||
177 qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD)
178 qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
179
180 return 0;
181}
182
142/*
143 * Initialize a transmit queue
183/**
184 * ath5k_hw_setup_tx_queue() - Initialize a transmit queue
185 * @ah: The &struct ath5k_hw
186 * @queue_type: One of enum ath5k_tx_queue
187 * @queue_info: The &struct ath5k_txq_info to use
188 *
189 * Returns 0 on success, -EINVAL on invalid arguments
144 */
190 */
145int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
191int
192ath5k_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 */

--- 58 unchanged lines hidden (view full) ---

212 return queue;
213}
214
215
216/*******************************\
217* Single QCU/DCU initialization *
218\*******************************/
219
193 struct ath5k_txq_info *queue_info)
194{
195 unsigned int queue;
196 int ret;
197
198 /*
199 * Get queue by type
200 */

--- 58 unchanged lines hidden (view full) ---

259 return queue;
260}
261
262
263/*******************************\
264* Single QCU/DCU initialization *
265\*******************************/
266
220/*
221 * Set tx retry limits on DCU
267/**
268 * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU
269 * @ah: The &struct ath5k_hw
270 * @queue: The hw queue number
271 *
272 * This function is used when initializing a queue, to set
273 * retry limits based on ah->ah_retry_* and the chipset used.
222 */
274 */
223void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
275void
276ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
224 unsigned int queue)
225{
226 /* Single data queue on AR5210 */
227 if (ah->ah_version == AR5K_AR5210) {
228 struct ath5k_txq_info *tq = &ah->ah_txq[queue];
229
230 if (queue > 0)
231 return;

--- 18 unchanged lines hidden (view full) ---

250 AR5K_DCU_RETRY_LMT_STA_RTS)
251 | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short),
252 AR5K_DCU_RETRY_LMT_STA_DATA),
253 AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
254 }
255}
256
257/**
277 unsigned int queue)
278{
279 /* Single data queue on AR5210 */
280 if (ah->ah_version == AR5K_AR5210) {
281 struct ath5k_txq_info *tq = &ah->ah_txq[queue];
282
283 if (queue > 0)
284 return;

--- 18 unchanged lines hidden (view full) ---

303 AR5K_DCU_RETRY_LMT_STA_RTS)
304 | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short),
305 AR5K_DCU_RETRY_LMT_STA_DATA),
306 AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
307 }
308}
309
310/**
258 * ath5k_hw_reset_tx_queue - Initialize a single hw queue
311 * ath5k_hw_reset_tx_queue() - Initialize a single hw queue
312 * @ah: The &struct ath5k_hw
313 * @queue: The hw queue number
259 *
314 *
260 * @ah The &struct ath5k_hw
261 * @queue The hw queue number
262 *
263 * Set DFS properties for the given transmit queue on DCU
264 * and configures all queue-specific parameters.
265 */
315 * Set DFS properties for the given transmit queue on DCU
316 * and configures all queue-specific parameters.
317 */
266int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
318int
319ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
267{
268 struct ath5k_txq_info *tq = &ah->ah_txq[queue];
269
270 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
271
272 tq = &ah->ah_txq[queue];
273
274 /* Skip if queue inactive or if we are on AR5210

--- 211 unchanged lines hidden (view full) ---

486}
487
488
489/**************************\
490* Global QCU/DCU functions *
491\**************************/
492
493/**
320{
321 struct ath5k_txq_info *tq = &ah->ah_txq[queue];
322
323 AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
324
325 tq = &ah->ah_txq[queue];
326
327 /* Skip if queue inactive or if we are on AR5210

--- 211 unchanged lines hidden (view full) ---

539}
540
541
542/**************************\
543* Global QCU/DCU functions *
544\**************************/
545
546/**
494 * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU
547 * ath5k_hw_set_ifs_intervals() - Set global inter-frame spaces on DCU
548 * @ah: The &struct ath5k_hw
549 * @slot_time: Slot time in us
495 *
550 *
496 * @ah The &struct ath5k_hw
497 * @slot_time Slot time in us
498 *
499 * Sets the global IFS intervals on DCU (also works on AR5210) for
500 * the given slot time and the current bwmode.
501 */
502int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
503{
504 struct ieee80211_channel *channel = ah->ah_current_channel;
505 struct ieee80211_rate *rate;
506 u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;

--- 85 unchanged lines hidden (view full) ---

592
593 /* Set SIFS interval in clock cycles */
594 ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
595
596 return 0;
597}
598
599
551 * Sets the global IFS intervals on DCU (also works on AR5210) for
552 * the given slot time and the current bwmode.
553 */
554int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
555{
556 struct ieee80211_channel *channel = ah->ah_current_channel;
557 struct ieee80211_rate *rate;
558 u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;

--- 85 unchanged lines hidden (view full) ---

644
645 /* Set SIFS interval in clock cycles */
646 ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
647
648 return 0;
649}
650
651
600int ath5k_hw_init_queues(struct ath5k_hw *ah)
652/**
653 * ath5k_hw_init_queues() - Initialize tx queues
654 * @ah: The &struct ath5k_hw
655 *
656 * Initializes all tx queues based on information on
657 * ah->ah_txq* set by the driver
658 */
659int
660ath5k_hw_init_queues(struct ath5k_hw *ah)
601{
602 int i, ret;
603
604 /* TODO: HW Compression support for data queues */
605 /* TODO: Burst prefetch for data queues */
606
607 /*
608 * Reset queues and start beacon timers at the end of the reset routine

--- 33 unchanged lines hidden ---
661{
662 int i, ret;
663
664 /* TODO: HW Compression support for data queues */
665 /* TODO: Burst prefetch for data queues */
666
667 /*
668 * Reset queues and start beacon timers at the end of the reset routine

--- 33 unchanged lines hidden ---