aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/desc.c
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi.org>2008-08-29 15:45:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-05 16:15:24 -0400
commitc6e387a214f4b2c4bd48020409e366c133385d98 (patch)
tree11fd58fd71e113a62d05f6f191771ca3d7d544f0 /drivers/net/wireless/ath5k/desc.c
parentfa9abe050d0a018b888fce61a4353afab17b0860 (diff)
ath5k: HW code cleanup
* No code changes... * Split hw.c to multiple files for better maintenance and add some documentation on each file code is going to grow soon (eeprom.c for example is going to get much stuff currently developed on ath_info) so it's better this way. * Rename following functions to maintain naming scheme: ah_setup_xtx_desc -> ah_setup_mrr_tx_desc (Because xtx doesn't say much, it's actually a multi-rate-retry tx descriptor) ath5k_hw_put_tx/rx_buf - > ath5k_hw_set_tx/rxdp ath5k_hw_get_tx/rx_buf -> ath5k_hw_get_tx/rxdp (We don't put any "buf" we set descriptor pointers on hw) ath5k_hw_tx_start -> ath5k_hw_start_tx_dma ath5k_hw_start_rx -> ath5k_hw_start_rx_dma ath5k_hw_stop_pcu_recv -> ath5k_hw_stop_rx_pcu (It's easier this way to identify them, we also have ath5k_hw_start_rx_pcu which completes the set) ath5k_hw_set_intr -> ath5k_hw_set_imr (As in get_isr we set imr here, not "intr") * Move ath5k_hw_setup_rx_desc on ah->ah_setup_rx_desc so we can include support for different rx descriptors in the future * Further cleanups so that checkpatch doesn't complain (only some > 80 col warnings for eeprom.h and reg.h as usual due to comments) Tested on 5211 and 5213 cards and works ok. Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Acked-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k/desc.c')
-rw-r--r--drivers/net/wireless/ath5k/desc.c667
1 files changed, 667 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c
new file mode 100644
index 000000000000..d45b90a6e06c
--- /dev/null
+++ b/drivers/net/wireless/ath5k/desc.c
@@ -0,0 +1,667 @@
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20/******************************\
21 Hardware Descriptor Functions
22\******************************/
23
24#include "ath5k.h"
25#include "reg.h"
26#include "debug.h"
27#include "base.h"
28
29/*
30 * TX Descriptors
31 */
32
33/*
34 * Initialize the 2-word tx control descriptor on 5210/5211
35 */
36static int
37ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
38 unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
39 unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
40 unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
41 unsigned int rtscts_rate, unsigned int rtscts_duration)
42{
43 u32 frame_type;
44 struct ath5k_hw_2w_tx_ctl *tx_ctl;
45 unsigned int frame_len;
46
47 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
48
49 /*
50 * Validate input
51 * - Zero retries don't make sense.
52 * - A zero rate will put the HW into a mode where it continously sends
53 * noise on the channel, so it is important to avoid this.
54 */
55 if (unlikely(tx_tries0 == 0)) {
56 ATH5K_ERR(ah->ah_sc, "zero retries\n");
57 WARN_ON(1);
58 return -EINVAL;
59 }
60 if (unlikely(tx_rate0 == 0)) {
61 ATH5K_ERR(ah->ah_sc, "zero rate\n");
62 WARN_ON(1);
63 return -EINVAL;
64 }
65
66 /* Clear descriptor */
67 memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
68
69 /* Setup control descriptor */
70
71 /* Verify and set frame length */
72
73 /* remove padding we might have added before */
74 frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
75
76 if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
77 return -EINVAL;
78
79 tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
80
81 /* Verify and set buffer length */
82
83 /* NB: beacon's BufLen must be a multiple of 4 bytes */
84 if (type == AR5K_PKT_TYPE_BEACON)
85 pkt_len = roundup(pkt_len, 4);
86
87 if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
88 return -EINVAL;
89
90 tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
91
92 /*
93 * Verify and set header length
94 * XXX: I only found that on 5210 code, does it work on 5211 ?
95 */
96 if (ah->ah_version == AR5K_AR5210) {
97 if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
98 return -EINVAL;
99 tx_ctl->tx_control_0 |=
100 AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
101 }
102
103 /*Diferences between 5210-5211*/
104 if (ah->ah_version == AR5K_AR5210) {
105 switch (type) {
106 case AR5K_PKT_TYPE_BEACON:
107 case AR5K_PKT_TYPE_PROBE_RESP:
108 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
109 case AR5K_PKT_TYPE_PIFS:
110 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
111 default:
112 frame_type = type /*<< 2 ?*/;
113 }
114
115 tx_ctl->tx_control_0 |=
116 AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
117 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
118
119 } else {
120 tx_ctl->tx_control_0 |=
121 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
122 AR5K_REG_SM(antenna_mode,
123 AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
124 tx_ctl->tx_control_1 |=
125 AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
126 }
127#define _TX_FLAGS(_c, _flag) \
128 if (flags & AR5K_TXDESC_##_flag) { \
129 tx_ctl->tx_control_##_c |= \
130 AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
131 }
132
133 _TX_FLAGS(0, CLRDMASK);
134 _TX_FLAGS(0, VEOL);
135 _TX_FLAGS(0, INTREQ);
136 _TX_FLAGS(0, RTSENA);
137 _TX_FLAGS(1, NOACK);
138
139#undef _TX_FLAGS
140
141 /*
142 * WEP crap
143 */
144 if (key_index != AR5K_TXKEYIX_INVALID) {
145 tx_ctl->tx_control_0 |=
146 AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
147 tx_ctl->tx_control_1 |=
148 AR5K_REG_SM(key_index,
149 AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
150 }
151
152 /*
153 * RTS/CTS Duration [5210 ?]
154 */
155 if ((ah->ah_version == AR5K_AR5210) &&
156 (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
157 tx_ctl->tx_control_1 |= rtscts_duration &
158 AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
159
160 return 0;
161}
162
163/*
164 * Initialize the 4-word tx control descriptor on 5212
165 */
166static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
167 struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
168 enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
169 unsigned int tx_tries0, unsigned int key_index,
170 unsigned int antenna_mode, unsigned int flags,
171 unsigned int rtscts_rate,
172 unsigned int rtscts_duration)
173{
174 struct ath5k_hw_4w_tx_ctl *tx_ctl;
175 unsigned int frame_len;
176
177 ATH5K_TRACE(ah->ah_sc);
178 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
179
180 /*
181 * Validate input
182 * - Zero retries don't make sense.
183 * - A zero rate will put the HW into a mode where it continously sends
184 * noise on the channel, so it is important to avoid this.
185 */
186 if (unlikely(tx_tries0 == 0)) {
187 ATH5K_ERR(ah->ah_sc, "zero retries\n");
188 WARN_ON(1);
189 return -EINVAL;
190 }
191 if (unlikely(tx_rate0 == 0)) {
192 ATH5K_ERR(ah->ah_sc, "zero rate\n");
193 WARN_ON(1);
194 return -EINVAL;
195 }
196
197 /* Clear descriptor */
198 memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
199
200 /* Setup control descriptor */
201
202 /* Verify and set frame length */
203
204 /* remove padding we might have added before */
205 frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
206
207 if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
208 return -EINVAL;
209
210 tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
211
212 /* Verify and set buffer length */
213
214 /* NB: beacon's BufLen must be a multiple of 4 bytes */
215 if (type == AR5K_PKT_TYPE_BEACON)
216 pkt_len = roundup(pkt_len, 4);
217
218 if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
219 return -EINVAL;
220
221 tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
222
223 tx_ctl->tx_control_0 |=
224 AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
225 AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
226 tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
227 AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
228 tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
229 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
230 tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
231
232#define _TX_FLAGS(_c, _flag) \
233 if (flags & AR5K_TXDESC_##_flag) { \
234 tx_ctl->tx_control_##_c |= \
235 AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
236 }
237
238 _TX_FLAGS(0, CLRDMASK);
239 _TX_FLAGS(0, VEOL);
240 _TX_FLAGS(0, INTREQ);
241 _TX_FLAGS(0, RTSENA);
242 _TX_FLAGS(0, CTSENA);
243 _TX_FLAGS(1, NOACK);
244
245#undef _TX_FLAGS
246
247 /*
248 * WEP crap
249 */
250 if (key_index != AR5K_TXKEYIX_INVALID) {
251 tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
252 tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
253 AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
254 }
255
256 /*
257 * RTS/CTS
258 */
259 if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
260 if ((flags & AR5K_TXDESC_RTSENA) &&
261 (flags & AR5K_TXDESC_CTSENA))
262 return -EINVAL;
263 tx_ctl->tx_control_2 |= rtscts_duration &
264 AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
265 tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
266 AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
267 }
268
269 return 0;
270}
271
272/*
273 * Initialize a 4-word multi rate retry tx control descriptor on 5212
274 */
275static int
276ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
277 unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
278 u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
279{
280 struct ath5k_hw_4w_tx_ctl *tx_ctl;
281
282 /*
283 * Rates can be 0 as long as the retry count is 0 too.
284 * A zero rate and nonzero retry count will put the HW into a mode where
285 * it continously sends noise on the channel, so it is important to
286 * avoid this.
287 */
288 if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
289 (tx_rate2 == 0 && tx_tries2 != 0) ||
290 (tx_rate3 == 0 && tx_tries3 != 0))) {
291 ATH5K_ERR(ah->ah_sc, "zero rate\n");
292 WARN_ON(1);
293 return -EINVAL;
294 }
295
296 if (ah->ah_version == AR5K_AR5212) {
297 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
298
299#define _XTX_TRIES(_n) \
300 if (tx_tries##_n) { \
301 tx_ctl->tx_control_2 |= \
302 AR5K_REG_SM(tx_tries##_n, \
303 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
304 tx_ctl->tx_control_3 |= \
305 AR5K_REG_SM(tx_rate##_n, \
306 AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
307 }
308
309 _XTX_TRIES(1);
310 _XTX_TRIES(2);
311 _XTX_TRIES(3);
312
313#undef _XTX_TRIES
314
315 return 1;
316 }
317
318 return 0;
319}
320
321/*
322 * Proccess the tx status descriptor on 5210/5211
323 */
324static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
325 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
326{
327 struct ath5k_hw_2w_tx_ctl *tx_ctl;
328 struct ath5k_hw_tx_status *tx_status;
329
330 ATH5K_TRACE(ah->ah_sc);
331
332 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
333 tx_status = &desc->ud.ds_tx5210.tx_stat;
334
335 /* No frame has been send or error */
336 if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
337 return -EINPROGRESS;
338
339 /*
340 * Get descriptor status
341 */
342 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
343 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
344 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
345 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
346 ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
347 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
348 /*TODO: ts->ts_virtcol + test*/
349 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
350 AR5K_DESC_TX_STATUS1_SEQ_NUM);
351 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
352 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
353 ts->ts_antenna = 1;
354 ts->ts_status = 0;
355 ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
356 AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
357
358 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
359 if (tx_status->tx_status_0 &
360 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
361 ts->ts_status |= AR5K_TXERR_XRETRY;
362
363 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
364 ts->ts_status |= AR5K_TXERR_FIFO;
365
366 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
367 ts->ts_status |= AR5K_TXERR_FILT;
368 }
369
370 return 0;
371}
372
373/*
374 * Proccess a tx status descriptor on 5212
375 */
376static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
377 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
378{
379 struct ath5k_hw_4w_tx_ctl *tx_ctl;
380 struct ath5k_hw_tx_status *tx_status;
381
382 ATH5K_TRACE(ah->ah_sc);
383
384 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
385 tx_status = &desc->ud.ds_tx5212.tx_stat;
386
387 /* No frame has been send or error */
388 if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE)))
389 return -EINPROGRESS;
390
391 /*
392 * Get descriptor status
393 */
394 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
395 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
396 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
397 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
398 ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
399 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
400 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
401 AR5K_DESC_TX_STATUS1_SEQ_NUM);
402 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
403 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
404 ts->ts_antenna = (tx_status->tx_status_1 &
405 AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
406 ts->ts_status = 0;
407
408 switch (AR5K_REG_MS(tx_status->tx_status_1,
409 AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
410 case 0:
411 ts->ts_rate = tx_ctl->tx_control_3 &
412 AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
413 break;
414 case 1:
415 ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
416 AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
417 ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
418 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
419 break;
420 case 2:
421 ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
422 AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
423 ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
424 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
425 break;
426 case 3:
427 ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
428 AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
429 ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
430 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
431 break;
432 }
433
434 /* TX error */
435 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
436 if (tx_status->tx_status_0 &
437 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
438 ts->ts_status |= AR5K_TXERR_XRETRY;
439
440 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
441 ts->ts_status |= AR5K_TXERR_FIFO;
442
443 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
444 ts->ts_status |= AR5K_TXERR_FILT;
445 }
446
447 return 0;
448}
449
450/*
451 * RX Descriptors
452 */
453
454/*
455 * Initialize an rx control descriptor
456 */
457static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
458 u32 size, unsigned int flags)
459{
460 struct ath5k_hw_rx_ctl *rx_ctl;
461
462 ATH5K_TRACE(ah->ah_sc);
463 rx_ctl = &desc->ud.ds_rx.rx_ctl;
464
465 /*
466 * Clear the descriptor
467 * If we don't clean the status descriptor,
468 * while scanning we get too many results,
469 * most of them virtual, after some secs
470 * of scanning system hangs. M.F.
471 */
472 memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
473
474 /* Setup descriptor */
475 rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
476 if (unlikely(rx_ctl->rx_control_1 != size))
477 return -EINVAL;
478
479 if (flags & AR5K_RXDESC_INTREQ)
480 rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
481
482 return 0;
483}
484
485/*
486 * Proccess the rx status descriptor on 5210/5211
487 */
488static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
489 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
490{
491 struct ath5k_hw_rx_status *rx_status;
492
493 rx_status = &desc->ud.ds_rx.u.rx_stat;
494
495 /* No frame received / not ready */
496 if (unlikely(!(rx_status->rx_status_1 &
497 AR5K_5210_RX_DESC_STATUS1_DONE)))
498 return -EINPROGRESS;
499
500 /*
501 * Frame receive status
502 */
503 rs->rs_datalen = rx_status->rx_status_0 &
504 AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
505 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
506 AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
507 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
508 AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
509 rs->rs_antenna = rx_status->rx_status_0 &
510 AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
511 rs->rs_more = rx_status->rx_status_0 &
512 AR5K_5210_RX_DESC_STATUS0_MORE;
513 /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
514 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
515 AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
516 rs->rs_status = 0;
517 rs->rs_phyerr = 0;
518
519 /*
520 * Key table status
521 */
522 if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
523 rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
524 AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
525 else
526 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
527
528 /*
529 * Receive/descriptor errors
530 */
531 if (!(rx_status->rx_status_1 &
532 AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
533 if (rx_status->rx_status_1 &
534 AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
535 rs->rs_status |= AR5K_RXERR_CRC;
536
537 if (rx_status->rx_status_1 &
538 AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
539 rs->rs_status |= AR5K_RXERR_FIFO;
540
541 if (rx_status->rx_status_1 &
542 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
543 rs->rs_status |= AR5K_RXERR_PHY;
544 rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
545 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
546 }
547
548 if (rx_status->rx_status_1 &
549 AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
550 rs->rs_status |= AR5K_RXERR_DECRYPT;
551 }
552
553 return 0;
554}
555
556/*
557 * Proccess the rx status descriptor on 5212
558 */
559static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
560 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
561{
562 struct ath5k_hw_rx_status *rx_status;
563 struct ath5k_hw_rx_error *rx_err;
564
565 ATH5K_TRACE(ah->ah_sc);
566 rx_status = &desc->ud.ds_rx.u.rx_stat;
567
568 /* Overlay on error */
569 rx_err = &desc->ud.ds_rx.u.rx_err;
570
571 /* No frame received / not ready */
572 if (unlikely(!(rx_status->rx_status_1 &
573 AR5K_5212_RX_DESC_STATUS1_DONE)))
574 return -EINPROGRESS;
575
576 /*
577 * Frame receive status
578 */
579 rs->rs_datalen = rx_status->rx_status_0 &
580 AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
581 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
582 AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
583 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
584 AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
585 rs->rs_antenna = rx_status->rx_status_0 &
586 AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
587 rs->rs_more = rx_status->rx_status_0 &
588 AR5K_5212_RX_DESC_STATUS0_MORE;
589 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
590 AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
591 rs->rs_status = 0;
592 rs->rs_phyerr = 0;
593
594 /*
595 * Key table status
596 */
597 if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
598 rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
599 AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
600 else
601 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
602
603 /*
604 * Receive/descriptor errors
605 */
606 if (!(rx_status->rx_status_1 &
607 AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
608 if (rx_status->rx_status_1 &
609 AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
610 rs->rs_status |= AR5K_RXERR_CRC;
611
612 if (rx_status->rx_status_1 &
613 AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
614 rs->rs_status |= AR5K_RXERR_PHY;
615 rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
616 AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
617 }
618
619 if (rx_status->rx_status_1 &
620 AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
621 rs->rs_status |= AR5K_RXERR_DECRYPT;
622
623 if (rx_status->rx_status_1 &
624 AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
625 rs->rs_status |= AR5K_RXERR_MIC;
626 }
627
628 return 0;
629}
630
631/*
632 * Init function pointers inside ath5k_hw struct
633 */
634int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
635{
636
637 if (ah->ah_version != AR5K_AR5210 &&
638 ah->ah_version != AR5K_AR5211 &&
639 ah->ah_version != AR5K_AR5212)
640 return -ENOTSUPP;
641
642 /* XXX: What is this magic value and where is it used ? */
643 if (ah->ah_version == AR5K_AR5212)
644 ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
645 else if (ah->ah_version == AR5K_AR5211)
646 ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
647
648 if (ah->ah_version == AR5K_AR5212) {
649 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
650 ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
651 ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc;
652 ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
653 } else {
654 ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
655 ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
656 ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc;
657 ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
658 }
659
660 if (ah->ah_version == AR5K_AR5212)
661 ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
662 else if (ah->ah_version <= AR5K_AR5211)
663 ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
664
665 return 0;
666}
667