blob: 0391813befd10975ee1b057e5ad83be15b918754 [file] [log] [blame]
Nick Kossifidisc6e387a2008-08-29 22:45:39 +03001/*
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
Nick Kossifidis9320b5c42010-11-23 20:36:45 +020029
30/************************\
31* TX Control descriptors *
32\************************/
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030033
34/*
35 * Initialize the 2-word tx control descriptor on 5210/5211
36 */
37static int
38ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
Benoit Papillault8127fbd2010-02-27 23:05:26 +010039 unsigned int pkt_len, unsigned int hdr_len, int padsize,
40 enum ath5k_pkt_type type,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030041 unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
42 unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
43 unsigned int rtscts_rate, unsigned int rtscts_duration)
44{
45 u32 frame_type;
46 struct ath5k_hw_2w_tx_ctl *tx_ctl;
47 unsigned int frame_len;
48
49 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
50
51 /*
52 * Validate input
53 * - Zero retries don't make sense.
54 * - A zero rate will put the HW into a mode where it continously sends
55 * noise on the channel, so it is important to avoid this.
56 */
57 if (unlikely(tx_tries0 == 0)) {
58 ATH5K_ERR(ah->ah_sc, "zero retries\n");
59 WARN_ON(1);
60 return -EINVAL;
61 }
62 if (unlikely(tx_rate0 == 0)) {
63 ATH5K_ERR(ah->ah_sc, "zero rate\n");
64 WARN_ON(1);
65 return -EINVAL;
66 }
67
68 /* Clear descriptor */
69 memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
70
71 /* Setup control descriptor */
72
73 /* Verify and set frame length */
74
75 /* remove padding we might have added before */
Benoit Papillault8127fbd2010-02-27 23:05:26 +010076 frame_len = pkt_len - padsize + FCS_LEN;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030077
78 if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
79 return -EINVAL;
80
81 tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
82
83 /* Verify and set buffer length */
84
85 /* NB: beacon's BufLen must be a multiple of 4 bytes */
86 if (type == AR5K_PKT_TYPE_BEACON)
87 pkt_len = roundup(pkt_len, 4);
88
89 if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
90 return -EINVAL;
91
92 tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
93
94 /*
Bruno Randolf1884a362010-06-16 19:12:28 +090095 * Verify and set header length (only 5210)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030096 */
97 if (ah->ah_version == AR5K_AR5210) {
Bruno Randolf03417bc2010-06-16 19:12:17 +090098 if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +030099 return -EINVAL;
100 tx_ctl->tx_control_0 |=
Bruno Randolf03417bc2010-06-16 19:12:17 +0900101 AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300102 }
103
Benoit Papillault8127fbd2010-02-27 23:05:26 +0100104 /*Differences between 5210-5211*/
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300105 if (ah->ah_version == AR5K_AR5210) {
106 switch (type) {
107 case AR5K_PKT_TYPE_BEACON:
108 case AR5K_PKT_TYPE_PROBE_RESP:
109 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
110 case AR5K_PKT_TYPE_PIFS:
111 frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
112 default:
Bruno Randolf2237e922010-06-16 19:12:22 +0900113 frame_type = type;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300114 }
115
116 tx_ctl->tx_control_0 |=
Bruno Randolf03417bc2010-06-16 19:12:17 +0900117 AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210) |
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300118 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
119
120 } else {
121 tx_ctl->tx_control_0 |=
122 AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
123 AR5K_REG_SM(antenna_mode,
124 AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
125 tx_ctl->tx_control_1 |=
Bruno Randolf03417bc2010-06-16 19:12:17 +0900126 AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300127 }
Bruno Randolf1884a362010-06-16 19:12:28 +0900128
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300129#define _TX_FLAGS(_c, _flag) \
130 if (flags & AR5K_TXDESC_##_flag) { \
131 tx_ctl->tx_control_##_c |= \
132 AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
133 }
Bruno Randolf1884a362010-06-16 19:12:28 +0900134#define _TX_FLAGS_5211(_c, _flag) \
135 if (flags & AR5K_TXDESC_##_flag) { \
136 tx_ctl->tx_control_##_c |= \
137 AR5K_2W_TX_DESC_CTL##_c##_##_flag##_5211; \
138 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300139 _TX_FLAGS(0, CLRDMASK);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300140 _TX_FLAGS(0, INTREQ);
141 _TX_FLAGS(0, RTSENA);
Bruno Randolf1884a362010-06-16 19:12:28 +0900142
143 if (ah->ah_version == AR5K_AR5211) {
144 _TX_FLAGS_5211(0, VEOL);
145 _TX_FLAGS_5211(1, NOACK);
146 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300147
148#undef _TX_FLAGS
Bruno Randolf1884a362010-06-16 19:12:28 +0900149#undef _TX_FLAGS_5211
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300150
151 /*
152 * WEP crap
153 */
154 if (key_index != AR5K_TXKEYIX_INVALID) {
155 tx_ctl->tx_control_0 |=
156 AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
157 tx_ctl->tx_control_1 |=
158 AR5K_REG_SM(key_index,
Bruno Randolf03417bc2010-06-16 19:12:17 +0900159 AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300160 }
161
162 /*
163 * RTS/CTS Duration [5210 ?]
164 */
165 if ((ah->ah_version == AR5K_AR5210) &&
166 (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
167 tx_ctl->tx_control_1 |= rtscts_duration &
Bruno Randolf03417bc2010-06-16 19:12:17 +0900168 AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300169
170 return 0;
171}
172
173/*
174 * Initialize the 4-word tx control descriptor on 5212
175 */
176static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
177 struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
Benoit Papillault8127fbd2010-02-27 23:05:26 +0100178 int padsize,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300179 enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
180 unsigned int tx_tries0, unsigned int key_index,
181 unsigned int antenna_mode, unsigned int flags,
182 unsigned int rtscts_rate,
183 unsigned int rtscts_duration)
184{
185 struct ath5k_hw_4w_tx_ctl *tx_ctl;
186 unsigned int frame_len;
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200187 u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300188
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300189 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
190
191 /*
192 * Validate input
193 * - Zero retries don't make sense.
194 * - A zero rate will put the HW into a mode where it continously sends
195 * noise on the channel, so it is important to avoid this.
196 */
197 if (unlikely(tx_tries0 == 0)) {
198 ATH5K_ERR(ah->ah_sc, "zero retries\n");
199 WARN_ON(1);
200 return -EINVAL;
201 }
202 if (unlikely(tx_rate0 == 0)) {
203 ATH5K_ERR(ah->ah_sc, "zero rate\n");
204 WARN_ON(1);
205 return -EINVAL;
206 }
207
Nick Kossifidis8f655dd2009-03-15 22:20:35 +0200208 tx_power += ah->ah_txpower.txp_offset;
209 if (tx_power > AR5K_TUNE_MAX_TXPOWER)
210 tx_power = AR5K_TUNE_MAX_TXPOWER;
211
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300212 /* Clear descriptor */
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200213 memset(&desc->ud.ds_tx5212.tx_stat, 0,
214 sizeof(desc->ud.ds_tx5212.tx_stat));
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300215
216 /* Setup control descriptor */
217
218 /* Verify and set frame length */
219
220 /* remove padding we might have added before */
Benoit Papillault8127fbd2010-02-27 23:05:26 +0100221 frame_len = pkt_len - padsize + FCS_LEN;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300222
223 if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
224 return -EINVAL;
225
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200226 txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300227
228 /* Verify and set buffer length */
229
230 /* NB: beacon's BufLen must be a multiple of 4 bytes */
231 if (type == AR5K_PKT_TYPE_BEACON)
232 pkt_len = roundup(pkt_len, 4);
233
234 if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
235 return -EINVAL;
236
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200237 txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300238
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200239 txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
240 AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
241 txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
242 txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
243 txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300244
245#define _TX_FLAGS(_c, _flag) \
246 if (flags & AR5K_TXDESC_##_flag) { \
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200247 txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300248 }
249
250 _TX_FLAGS(0, CLRDMASK);
251 _TX_FLAGS(0, VEOL);
252 _TX_FLAGS(0, INTREQ);
253 _TX_FLAGS(0, RTSENA);
254 _TX_FLAGS(0, CTSENA);
255 _TX_FLAGS(1, NOACK);
256
257#undef _TX_FLAGS
258
259 /*
260 * WEP crap
261 */
262 if (key_index != AR5K_TXKEYIX_INVALID) {
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200263 txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
264 txctl1 |= AR5K_REG_SM(key_index,
Bruno Randolf03417bc2010-06-16 19:12:17 +0900265 AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300266 }
267
268 /*
269 * RTS/CTS
270 */
271 if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
272 if ((flags & AR5K_TXDESC_RTSENA) &&
273 (flags & AR5K_TXDESC_CTSENA))
274 return -EINVAL;
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200275 txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
276 txctl3 |= AR5K_REG_SM(rtscts_rate,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300277 AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
278 }
279
Felix Fietkauc5e0a882011-04-10 18:32:13 +0200280 tx_ctl->tx_control_0 = txctl0;
281 tx_ctl->tx_control_1 = txctl1;
282 tx_ctl->tx_control_2 = txctl2;
283 tx_ctl->tx_control_3 = txctl3;
284
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300285 return 0;
286}
287
288/*
289 * Initialize a 4-word multi rate retry tx control descriptor on 5212
290 */
Bruno Randolfa6668192010-06-16 19:12:01 +0900291int
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300292ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
293 unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
294 u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
295{
296 struct ath5k_hw_4w_tx_ctl *tx_ctl;
297
Bruno Randolfa6668192010-06-16 19:12:01 +0900298 /* no mrr support for cards older than 5212 */
299 if (ah->ah_version < AR5K_AR5212)
300 return 0;
301
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300302 /*
303 * Rates can be 0 as long as the retry count is 0 too.
304 * A zero rate and nonzero retry count will put the HW into a mode where
305 * it continously sends noise on the channel, so it is important to
306 * avoid this.
307 */
308 if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
309 (tx_rate2 == 0 && tx_tries2 != 0) ||
310 (tx_rate3 == 0 && tx_tries3 != 0))) {
311 ATH5K_ERR(ah->ah_sc, "zero rate\n");
312 WARN_ON(1);
313 return -EINVAL;
314 }
315
316 if (ah->ah_version == AR5K_AR5212) {
317 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
318
319#define _XTX_TRIES(_n) \
320 if (tx_tries##_n) { \
321 tx_ctl->tx_control_2 |= \
322 AR5K_REG_SM(tx_tries##_n, \
323 AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
324 tx_ctl->tx_control_3 |= \
325 AR5K_REG_SM(tx_rate##_n, \
326 AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
327 }
328
329 _XTX_TRIES(1);
330 _XTX_TRIES(2);
331 _XTX_TRIES(3);
332
333#undef _XTX_TRIES
334
335 return 1;
336 }
337
338 return 0;
339}
340
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200341
342/***********************\
343* TX Status descriptors *
344\***********************/
345
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300346/*
347 * Proccess the tx status descriptor on 5210/5211
348 */
349static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
350 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
351{
352 struct ath5k_hw_2w_tx_ctl *tx_ctl;
353 struct ath5k_hw_tx_status *tx_status;
354
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300355 tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
356 tx_status = &desc->ud.ds_tx5210.tx_stat;
357
358 /* No frame has been send or error */
359 if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
360 return -EINPROGRESS;
361
362 /*
363 * Get descriptor status
364 */
365 ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
366 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
367 ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
368 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
Felix Fietkaued895082011-04-10 18:32:17 +0200369 ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300370 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
371 /*TODO: ts->ts_virtcol + test*/
372 ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
373 AR5K_DESC_TX_STATUS1_SEQ_NUM);
374 ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
375 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
376 ts->ts_antenna = 1;
377 ts->ts_status = 0;
Felix Fietkau2f7fe872008-10-05 18:05:48 +0200378 ts->ts_final_idx = 0;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300379
380 if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
381 if (tx_status->tx_status_0 &
382 AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
383 ts->ts_status |= AR5K_TXERR_XRETRY;
384
385 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
386 ts->ts_status |= AR5K_TXERR_FIFO;
387
388 if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
389 ts->ts_status |= AR5K_TXERR_FILT;
390 }
391
392 return 0;
393}
394
395/*
396 * Proccess a tx status descriptor on 5212
397 */
398static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
399 struct ath5k_desc *desc, struct ath5k_tx_status *ts)
400{
401 struct ath5k_hw_4w_tx_ctl *tx_ctl;
402 struct ath5k_hw_tx_status *tx_status;
Felix Fietkaued895082011-04-10 18:32:17 +0200403 u32 txstat0, txstat1;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300404
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300405 tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
406 tx_status = &desc->ud.ds_tx5212.tx_stat;
407
Felix Fietkaub161b892011-04-10 18:32:15 +0200408 txstat1 = ACCESS_ONCE(tx_status->tx_status_1);
409
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300410 /* No frame has been send or error */
Felix Fietkaub161b892011-04-10 18:32:15 +0200411 if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE)))
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300412 return -EINPROGRESS;
413
Felix Fietkaub161b892011-04-10 18:32:15 +0200414 txstat0 = ACCESS_ONCE(tx_status->tx_status_0);
Felix Fietkaub161b892011-04-10 18:32:15 +0200415
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300416 /*
417 * Get descriptor status
418 */
Felix Fietkaub161b892011-04-10 18:32:15 +0200419 ts->ts_tstamp = AR5K_REG_MS(txstat0,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300420 AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
Felix Fietkaub161b892011-04-10 18:32:15 +0200421 ts->ts_shortretry = AR5K_REG_MS(txstat0,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300422 AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
Felix Fietkaued895082011-04-10 18:32:17 +0200423 ts->ts_final_retry = AR5K_REG_MS(txstat0,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300424 AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
Felix Fietkaub161b892011-04-10 18:32:15 +0200425 ts->ts_seqnum = AR5K_REG_MS(txstat1,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300426 AR5K_DESC_TX_STATUS1_SEQ_NUM);
Felix Fietkaub161b892011-04-10 18:32:15 +0200427 ts->ts_rssi = AR5K_REG_MS(txstat1,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300428 AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
Felix Fietkaub161b892011-04-10 18:32:15 +0200429 ts->ts_antenna = (txstat1 &
Bruno Randolf03417bc2010-06-16 19:12:17 +0900430 AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300431 ts->ts_status = 0;
432
Felix Fietkaub161b892011-04-10 18:32:15 +0200433 ts->ts_final_idx = AR5K_REG_MS(txstat1,
Bruno Randolf03417bc2010-06-16 19:12:17 +0900434 AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212);
Felix Fietkau2f7fe872008-10-05 18:05:48 +0200435
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300436 /* TX error */
Felix Fietkaub161b892011-04-10 18:32:15 +0200437 if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
438 if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300439 ts->ts_status |= AR5K_TXERR_XRETRY;
440
Felix Fietkaub161b892011-04-10 18:32:15 +0200441 if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300442 ts->ts_status |= AR5K_TXERR_FIFO;
443
Felix Fietkaub161b892011-04-10 18:32:15 +0200444 if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300445 ts->ts_status |= AR5K_TXERR_FILT;
446 }
447
448 return 0;
449}
450
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200451
452/****************\
453* RX Descriptors *
454\****************/
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300455
456/*
457 * Initialize an rx control descriptor
458 */
Bruno Randolfa6668192010-06-16 19:12:01 +0900459int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
460 u32 size, unsigned int flags)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300461{
462 struct ath5k_hw_rx_ctl *rx_ctl;
463
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300464 rx_ctl = &desc->ud.ds_rx.rx_ctl;
465
466 /*
467 * Clear the descriptor
468 * If we don't clean the status descriptor,
469 * while scanning we get too many results,
470 * most of them virtual, after some secs
471 * of scanning system hangs. M.F.
472 */
473 memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
474
Bruno Randolf87861232010-06-16 19:12:34 +0900475 if (unlikely(size & ~AR5K_DESC_RX_CTL1_BUF_LEN))
476 return -EINVAL;
477
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300478 /* Setup descriptor */
479 rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300480
481 if (flags & AR5K_RXDESC_INTREQ)
482 rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
483
484 return 0;
485}
486
487/*
488 * Proccess the rx status descriptor on 5210/5211
489 */
490static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
491 struct ath5k_desc *desc, struct ath5k_rx_status *rs)
492{
493 struct ath5k_hw_rx_status *rx_status;
494
Bruno Randolf62412a82010-06-16 19:12:12 +0900495 rx_status = &desc->ud.ds_rx.rx_stat;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300496
497 /* No frame received / not ready */
498 if (unlikely(!(rx_status->rx_status_1 &
Bruno Randolf87861232010-06-16 19:12:34 +0900499 AR5K_5210_RX_DESC_STATUS1_DONE)))
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300500 return -EINPROGRESS;
501
Bruno Randolf87861232010-06-16 19:12:34 +0900502 memset(rs, 0, sizeof(struct ath5k_rx_status));
503
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300504 /*
505 * Frame receive status
506 */
507 rs->rs_datalen = rx_status->rx_status_0 &
508 AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
509 rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
510 AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
511 rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
512 AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
Bob Copelandc7930332008-11-03 22:14:00 -0500513 rs->rs_more = !!(rx_status->rx_status_0 &
514 AR5K_5210_RX_DESC_STATUS0_MORE);
Bruno Randolf87861232010-06-16 19:12:34 +0900515 /* TODO: this timestamp is 13 bit, later on we assume 15 bit!
516 * also the HAL code for 5210 says the timestamp is bits [10..22] of the
517 * TSF, and extends the timestamp here to 15 bit.
518 * we need to check on 5210...
519 */
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300520 rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
521 AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
Bruno Randolf1884a362010-06-16 19:12:28 +0900522
523 if (ah->ah_version == AR5K_AR5211)
524 rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
525 AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211);
526 else
527 rs->rs_antenna = (rx_status->rx_status_0 &
528 AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210)
529 ? 2 : 1;
530
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300531 /*
532 * Key table status
533 */
534 if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
535 rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
536 AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
537 else
538 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
539
540 /*
541 * Receive/descriptor errors
542 */
543 if (!(rx_status->rx_status_1 &
Bruno Randolf87861232010-06-16 19:12:34 +0900544 AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300545 if (rx_status->rx_status_1 &
546 AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
547 rs->rs_status |= AR5K_RXERR_CRC;
548
Bruno Randolf87861232010-06-16 19:12:34 +0900549 /* only on 5210 */
550 if ((ah->ah_version == AR5K_AR5210) &&
551 (rx_status->rx_status_1 &
552 AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210))
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300553 rs->rs_status |= AR5K_RXERR_FIFO;
554
555 if (rx_status->rx_status_1 &
556 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
557 rs->rs_status |= AR5K_RXERR_PHY;
Bruno Randolf87861232010-06-16 19:12:34 +0900558 rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300559 AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
560 }
561
562 if (rx_status->rx_status_1 &
563 AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
564 rs->rs_status |= AR5K_RXERR_DECRYPT;
565 }
566
567 return 0;
568}
569
570/*
571 * Proccess the rx status descriptor on 5212
572 */
573static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
Bruno Randolf28471092010-06-16 19:12:07 +0900574 struct ath5k_desc *desc,
575 struct ath5k_rx_status *rs)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300576{
577 struct ath5k_hw_rx_status *rx_status;
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200578 u32 rxstat0, rxstat1;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300579
Bruno Randolf62412a82010-06-16 19:12:12 +0900580 rx_status = &desc->ud.ds_rx.rx_stat;
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200581 rxstat1 = ACCESS_ONCE(rx_status->rx_status_1);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300582
583 /* No frame received / not ready */
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200584 if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE)))
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300585 return -EINPROGRESS;
586
Bruno Randolf87861232010-06-16 19:12:34 +0900587 memset(rs, 0, sizeof(struct ath5k_rx_status));
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200588 rxstat0 = ACCESS_ONCE(rx_status->rx_status_0);
Bruno Randolf87861232010-06-16 19:12:34 +0900589
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300590 /*
591 * Frame receive status
592 */
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200593 rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
594 rs->rs_rssi = AR5K_REG_MS(rxstat0,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300595 AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200596 rs->rs_rate = AR5K_REG_MS(rxstat0,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300597 AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200598 rs->rs_antenna = AR5K_REG_MS(rxstat0,
Bob Copelandc7930332008-11-03 22:14:00 -0500599 AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200600 rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE);
601 rs->rs_tstamp = AR5K_REG_MS(rxstat1,
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300602 AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300603
604 /*
605 * Key table status
606 */
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200607 if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
608 rs->rs_keyix = AR5K_REG_MS(rxstat1,
Bruno Randolf28471092010-06-16 19:12:07 +0900609 AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300610 else
611 rs->rs_keyix = AR5K_RXKEYIX_INVALID;
612
613 /*
614 * Receive/descriptor errors
615 */
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200616 if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
617 if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300618 rs->rs_status |= AR5K_RXERR_CRC;
619
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200620 if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300621 rs->rs_status |= AR5K_RXERR_PHY;
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200622 rs->rs_phyerr = AR5K_REG_MS(rxstat1,
Bruno Randolf62412a82010-06-16 19:12:12 +0900623 AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE);
Bruno Randolf6a0076e2010-06-16 19:12:39 +0900624 if (!ah->ah_capabilities.cap_has_phyerr_counters)
625 ath5k_ani_phy_error_report(ah, rs->rs_phyerr);
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300626 }
627
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200628 if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300629 rs->rs_status |= AR5K_RXERR_DECRYPT;
630
Felix Fietkaub2fd97d2011-04-10 18:32:16 +0200631 if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300632 rs->rs_status |= AR5K_RXERR_MIC;
633 }
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300634 return 0;
635}
636
Nick Kossifidis9320b5c42010-11-23 20:36:45 +0200637
638/********\
639* Attach *
640\********/
641
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300642/*
643 * Init function pointers inside ath5k_hw struct
644 */
645int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
646{
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300647 if (ah->ah_version == AR5K_AR5212) {
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300648 ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300649 ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300650 ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
Bruno Randolfa6668192010-06-16 19:12:01 +0900651 } else if (ah->ah_version <= AR5K_AR5211) {
652 ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
653 ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300654 ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
Bruno Randolfa6668192010-06-16 19:12:01 +0900655 } else
656 return -ENOTSUPP;
Nick Kossifidisc6e387a2008-08-29 22:45:39 +0300657 return 0;
658}