1 | /* |
---|
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> |
---|
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> |
---|
4 | * |
---|
5 | * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>. |
---|
6 | * |
---|
7 | * Permission to use, copy, modify, and distribute this software for any |
---|
8 | * purpose with or without fee is hereby granted, provided that the above |
---|
9 | * copyright notice and this permission notice appear in all copies. |
---|
10 | * |
---|
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
---|
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
---|
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
---|
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
---|
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
---|
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
---|
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
---|
18 | * |
---|
19 | */ |
---|
20 | |
---|
21 | FILE_LICENCE ( MIT ); |
---|
22 | |
---|
23 | /********************************************\ |
---|
24 | Queue Control Unit, DFS Control Unit Functions |
---|
25 | \********************************************/ |
---|
26 | |
---|
27 | #include "ath5k.h" |
---|
28 | #include "reg.h" |
---|
29 | #include "base.h" |
---|
30 | |
---|
31 | /* |
---|
32 | * Set properties for a transmit queue |
---|
33 | */ |
---|
34 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, |
---|
35 | const struct ath5k_txq_info *queue_info) |
---|
36 | { |
---|
37 | if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE) |
---|
38 | return -EIO; |
---|
39 | |
---|
40 | memcpy(&ah->ah_txq, queue_info, sizeof(struct ath5k_txq_info)); |
---|
41 | |
---|
42 | /*XXX: Is this supported on 5210 ?*/ |
---|
43 | if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && |
---|
44 | ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || |
---|
45 | (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || |
---|
46 | queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) |
---|
47 | ah->ah_txq.tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; |
---|
48 | |
---|
49 | return 0; |
---|
50 | } |
---|
51 | |
---|
52 | /* |
---|
53 | * Initialize a transmit queue |
---|
54 | */ |
---|
55 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, |
---|
56 | struct ath5k_txq_info *queue_info) |
---|
57 | { |
---|
58 | unsigned int queue; |
---|
59 | int ret; |
---|
60 | |
---|
61 | /* We only use one queue */ |
---|
62 | queue = 0; |
---|
63 | |
---|
64 | /* |
---|
65 | * Setup internal queue structure |
---|
66 | */ |
---|
67 | memset(&ah->ah_txq, 0, sizeof(struct ath5k_txq_info)); |
---|
68 | ah->ah_txq.tqi_type = queue_type; |
---|
69 | |
---|
70 | if (queue_info != NULL) { |
---|
71 | queue_info->tqi_type = queue_type; |
---|
72 | ret = ath5k_hw_set_tx_queueprops(ah, queue_info); |
---|
73 | if (ret) |
---|
74 | return ret; |
---|
75 | } |
---|
76 | |
---|
77 | /* |
---|
78 | * We use ah_txq_status to hold a temp value for |
---|
79 | * the Secondary interrupt mask registers on 5211+ |
---|
80 | * check out ath5k_hw_reset_tx_queue |
---|
81 | */ |
---|
82 | AR5K_Q_ENABLE_BITS(ah->ah_txq_status, 0); |
---|
83 | |
---|
84 | return 0; |
---|
85 | } |
---|
86 | |
---|
87 | /* |
---|
88 | * Set a transmit queue inactive |
---|
89 | */ |
---|
90 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah) |
---|
91 | { |
---|
92 | /* This queue will be skipped in further operations */ |
---|
93 | ah->ah_txq.tqi_type = AR5K_TX_QUEUE_INACTIVE; |
---|
94 | /*For SIMR setup*/ |
---|
95 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, 0); |
---|
96 | } |
---|
97 | |
---|
98 | /* |
---|
99 | * Set DFS properties for a transmit queue on DCU |
---|
100 | */ |
---|
101 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah) |
---|
102 | { |
---|
103 | u32 cw_min, cw_max, retry_lg, retry_sh; |
---|
104 | struct ath5k_txq_info *tq = &ah->ah_txq; |
---|
105 | const int queue = 0; |
---|
106 | |
---|
107 | tq = &ah->ah_txq; |
---|
108 | |
---|
109 | if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) |
---|
110 | return 0; |
---|
111 | |
---|
112 | if (ah->ah_version == AR5K_AR5210) { |
---|
113 | /* Only handle data queues, others will be ignored */ |
---|
114 | if (tq->tqi_type != AR5K_TX_QUEUE_DATA) |
---|
115 | return 0; |
---|
116 | |
---|
117 | /* Set Slot time */ |
---|
118 | ath5k_hw_reg_write(ah, ah->ah_turbo ? |
---|
119 | AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, |
---|
120 | AR5K_SLOT_TIME); |
---|
121 | /* Set ACK_CTS timeout */ |
---|
122 | ath5k_hw_reg_write(ah, ah->ah_turbo ? |
---|
123 | AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : |
---|
124 | AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); |
---|
125 | /* Set Transmit Latency */ |
---|
126 | ath5k_hw_reg_write(ah, ah->ah_turbo ? |
---|
127 | AR5K_INIT_TRANSMIT_LATENCY_TURBO : |
---|
128 | AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); |
---|
129 | |
---|
130 | /* Set IFS0 */ |
---|
131 | if (ah->ah_turbo) { |
---|
132 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + |
---|
133 | (ah->ah_aifs + tq->tqi_aifs) * |
---|
134 | AR5K_INIT_SLOT_TIME_TURBO) << |
---|
135 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, |
---|
136 | AR5K_IFS0); |
---|
137 | } else { |
---|
138 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + |
---|
139 | (ah->ah_aifs + tq->tqi_aifs) * |
---|
140 | AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | |
---|
141 | AR5K_INIT_SIFS, AR5K_IFS0); |
---|
142 | } |
---|
143 | |
---|
144 | /* Set IFS1 */ |
---|
145 | ath5k_hw_reg_write(ah, ah->ah_turbo ? |
---|
146 | AR5K_INIT_PROTO_TIME_CNTRL_TURBO : |
---|
147 | AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); |
---|
148 | /* Set AR5K_PHY_SETTLING */ |
---|
149 | ath5k_hw_reg_write(ah, ah->ah_turbo ? |
---|
150 | (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) |
---|
151 | | 0x38 : |
---|
152 | (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) |
---|
153 | | 0x1C, |
---|
154 | AR5K_PHY_SETTLING); |
---|
155 | /* Set Frame Control Register */ |
---|
156 | ath5k_hw_reg_write(ah, ah->ah_turbo ? |
---|
157 | (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | |
---|
158 | AR5K_PHY_TURBO_SHORT | 0x2020) : |
---|
159 | (AR5K_PHY_FRAME_CTL_INI | 0x1020), |
---|
160 | AR5K_PHY_FRAME_CTL_5210); |
---|
161 | } |
---|
162 | |
---|
163 | /* |
---|
164 | * Calculate cwmin/max by channel mode |
---|
165 | */ |
---|
166 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; |
---|
167 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; |
---|
168 | ah->ah_aifs = AR5K_TUNE_AIFS; |
---|
169 | /*XR is only supported on 5212*/ |
---|
170 | if (IS_CHAN_XR(ah->ah_current_channel) && |
---|
171 | ah->ah_version == AR5K_AR5212) { |
---|
172 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; |
---|
173 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; |
---|
174 | ah->ah_aifs = AR5K_TUNE_AIFS_XR; |
---|
175 | /*B mode is not supported on 5210*/ |
---|
176 | } else if (IS_CHAN_B(ah->ah_current_channel) && |
---|
177 | ah->ah_version != AR5K_AR5210) { |
---|
178 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; |
---|
179 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; |
---|
180 | ah->ah_aifs = AR5K_TUNE_AIFS_11B; |
---|
181 | } |
---|
182 | |
---|
183 | cw_min = 1; |
---|
184 | while (cw_min < ah->ah_cw_min) |
---|
185 | cw_min = (cw_min << 1) | 1; |
---|
186 | |
---|
187 | cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : |
---|
188 | ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); |
---|
189 | cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : |
---|
190 | ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); |
---|
191 | |
---|
192 | /* |
---|
193 | * Calculate and set retry limits |
---|
194 | */ |
---|
195 | if (ah->ah_software_retry) { |
---|
196 | /* XXX Need to test this */ |
---|
197 | retry_lg = ah->ah_limit_tx_retries; |
---|
198 | retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? |
---|
199 | AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; |
---|
200 | } else { |
---|
201 | retry_lg = AR5K_INIT_LG_RETRY; |
---|
202 | retry_sh = AR5K_INIT_SH_RETRY; |
---|
203 | } |
---|
204 | |
---|
205 | /*No QCU/DCU [5210]*/ |
---|
206 | if (ah->ah_version == AR5K_AR5210) { |
---|
207 | ath5k_hw_reg_write(ah, |
---|
208 | (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) |
---|
209 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, |
---|
210 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) |
---|
211 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, |
---|
212 | AR5K_NODCU_RETRY_LMT_SSH_RETRY) |
---|
213 | | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) |
---|
214 | | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), |
---|
215 | AR5K_NODCU_RETRY_LMT); |
---|
216 | } else { |
---|
217 | /*QCU/DCU [5211+]*/ |
---|
218 | ath5k_hw_reg_write(ah, |
---|
219 | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, |
---|
220 | AR5K_DCU_RETRY_LMT_SLG_RETRY) | |
---|
221 | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, |
---|
222 | AR5K_DCU_RETRY_LMT_SSH_RETRY) | |
---|
223 | AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | |
---|
224 | AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), |
---|
225 | AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); |
---|
226 | |
---|
227 | /*===Rest is also for QCU/DCU only [5211+]===*/ |
---|
228 | |
---|
229 | /* |
---|
230 | * Set initial content window (cw_min/cw_max) |
---|
231 | * and arbitrated interframe space (aifs)... |
---|
232 | */ |
---|
233 | ath5k_hw_reg_write(ah, |
---|
234 | AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | |
---|
235 | AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | |
---|
236 | AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, |
---|
237 | AR5K_DCU_LCL_IFS_AIFS), |
---|
238 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); |
---|
239 | |
---|
240 | /* |
---|
241 | * Set misc registers |
---|
242 | */ |
---|
243 | /* Enable DCU early termination for this queue */ |
---|
244 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
---|
245 | AR5K_QCU_MISC_DCU_EARLY); |
---|
246 | |
---|
247 | /* Enable DCU to wait for next fragment from QCU */ |
---|
248 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), |
---|
249 | AR5K_DCU_MISC_FRAG_WAIT); |
---|
250 | |
---|
251 | /* On Maui and Spirit use the global seqnum on DCU */ |
---|
252 | if (ah->ah_mac_version < AR5K_SREV_AR5211) |
---|
253 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), |
---|
254 | AR5K_DCU_MISC_SEQNUM_CTL); |
---|
255 | |
---|
256 | if (tq->tqi_cbr_period) { |
---|
257 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, |
---|
258 | AR5K_QCU_CBRCFG_INTVAL) | |
---|
259 | AR5K_REG_SM(tq->tqi_cbr_overflow_limit, |
---|
260 | AR5K_QCU_CBRCFG_ORN_THRES), |
---|
261 | AR5K_QUEUE_CBRCFG(queue)); |
---|
262 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
---|
263 | AR5K_QCU_MISC_FRSHED_CBR); |
---|
264 | if (tq->tqi_cbr_overflow_limit) |
---|
265 | AR5K_REG_ENABLE_BITS(ah, |
---|
266 | AR5K_QUEUE_MISC(queue), |
---|
267 | AR5K_QCU_MISC_CBR_THRES_ENABLE); |
---|
268 | } |
---|
269 | |
---|
270 | if (tq->tqi_ready_time && |
---|
271 | (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB)) |
---|
272 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, |
---|
273 | AR5K_QCU_RDYTIMECFG_INTVAL) | |
---|
274 | AR5K_QCU_RDYTIMECFG_ENABLE, |
---|
275 | AR5K_QUEUE_RDYTIMECFG(queue)); |
---|
276 | |
---|
277 | if (tq->tqi_burst_time) { |
---|
278 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, |
---|
279 | AR5K_DCU_CHAN_TIME_DUR) | |
---|
280 | AR5K_DCU_CHAN_TIME_ENABLE, |
---|
281 | AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); |
---|
282 | |
---|
283 | if (tq->tqi_flags |
---|
284 | & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) |
---|
285 | AR5K_REG_ENABLE_BITS(ah, |
---|
286 | AR5K_QUEUE_MISC(queue), |
---|
287 | AR5K_QCU_MISC_RDY_VEOL_POLICY); |
---|
288 | } |
---|
289 | |
---|
290 | if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) |
---|
291 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, |
---|
292 | AR5K_QUEUE_DFS_MISC(queue)); |
---|
293 | |
---|
294 | if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) |
---|
295 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, |
---|
296 | AR5K_QUEUE_DFS_MISC(queue)); |
---|
297 | |
---|
298 | /* TODO: Handle frame compression */ |
---|
299 | |
---|
300 | /* |
---|
301 | * Enable interrupts for this tx queue |
---|
302 | * in the secondary interrupt mask registers |
---|
303 | */ |
---|
304 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) |
---|
305 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); |
---|
306 | |
---|
307 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) |
---|
308 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); |
---|
309 | |
---|
310 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) |
---|
311 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); |
---|
312 | |
---|
313 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) |
---|
314 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); |
---|
315 | |
---|
316 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) |
---|
317 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); |
---|
318 | |
---|
319 | if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) |
---|
320 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); |
---|
321 | |
---|
322 | if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) |
---|
323 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); |
---|
324 | |
---|
325 | if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) |
---|
326 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); |
---|
327 | |
---|
328 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) |
---|
329 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); |
---|
330 | |
---|
331 | /* Update secondary interrupt mask registers */ |
---|
332 | |
---|
333 | /* Filter out inactive queues */ |
---|
334 | ah->ah_txq_imr_txok &= ah->ah_txq_status; |
---|
335 | ah->ah_txq_imr_txerr &= ah->ah_txq_status; |
---|
336 | ah->ah_txq_imr_txurn &= ah->ah_txq_status; |
---|
337 | ah->ah_txq_imr_txdesc &= ah->ah_txq_status; |
---|
338 | ah->ah_txq_imr_txeol &= ah->ah_txq_status; |
---|
339 | ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; |
---|
340 | ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; |
---|
341 | ah->ah_txq_imr_qtrig &= ah->ah_txq_status; |
---|
342 | ah->ah_txq_imr_nofrm &= ah->ah_txq_status; |
---|
343 | |
---|
344 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, |
---|
345 | AR5K_SIMR0_QCU_TXOK) | |
---|
346 | AR5K_REG_SM(ah->ah_txq_imr_txdesc, |
---|
347 | AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); |
---|
348 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, |
---|
349 | AR5K_SIMR1_QCU_TXERR) | |
---|
350 | AR5K_REG_SM(ah->ah_txq_imr_txeol, |
---|
351 | AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); |
---|
352 | /* Update simr2 but don't overwrite rest simr2 settings */ |
---|
353 | AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); |
---|
354 | AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, |
---|
355 | AR5K_REG_SM(ah->ah_txq_imr_txurn, |
---|
356 | AR5K_SIMR2_QCU_TXURN)); |
---|
357 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, |
---|
358 | AR5K_SIMR3_QCBRORN) | |
---|
359 | AR5K_REG_SM(ah->ah_txq_imr_cbrurn, |
---|
360 | AR5K_SIMR3_QCBRURN), AR5K_SIMR3); |
---|
361 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, |
---|
362 | AR5K_SIMR4_QTRIG), AR5K_SIMR4); |
---|
363 | /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ |
---|
364 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, |
---|
365 | AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); |
---|
366 | /* No queue has TXNOFRM enabled, disable the interrupt |
---|
367 | * by setting AR5K_TXNOFRM to zero */ |
---|
368 | if (ah->ah_txq_imr_nofrm == 0) |
---|
369 | ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); |
---|
370 | |
---|
371 | /* Set QCU mask for this DCU to save power */ |
---|
372 | AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); |
---|
373 | } |
---|
374 | |
---|
375 | return 0; |
---|
376 | } |
---|
377 | |
---|
378 | /* |
---|
379 | * Set slot time on DCU |
---|
380 | */ |
---|
381 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) |
---|
382 | { |
---|
383 | if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) |
---|
384 | return -EINVAL; |
---|
385 | |
---|
386 | if (ah->ah_version == AR5K_AR5210) |
---|
387 | ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, |
---|
388 | ah->ah_turbo), AR5K_SLOT_TIME); |
---|
389 | else |
---|
390 | ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); |
---|
391 | |
---|
392 | return 0; |
---|
393 | } |
---|
394 | |
---|