1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3*4882a593Smuzhiyun * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4*4882a593Smuzhiyun * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Permission to use, copy, modify, and distribute this software for any
7*4882a593Smuzhiyun * purpose with or without fee is hereby granted, provided that the above
8*4882a593Smuzhiyun * copyright notice and this permission notice appear in all copies.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*4882a593Smuzhiyun * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*4882a593Smuzhiyun * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*4882a593Smuzhiyun * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*4882a593Smuzhiyun * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*4882a593Smuzhiyun * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*4882a593Smuzhiyun * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /******************************\
21*4882a593Smuzhiyun Hardware Descriptor Functions
22*4882a593Smuzhiyun \******************************/
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include "ath5k.h"
27*4882a593Smuzhiyun #include "reg.h"
28*4882a593Smuzhiyun #include "debug.h"
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /**
32*4882a593Smuzhiyun * DOC: Hardware descriptor functions
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * Here we handle the processing of the low-level hw descriptors
35*4882a593Smuzhiyun * that hw reads and writes via DMA for each TX and RX attempt (that means
36*4882a593Smuzhiyun * we can also have descriptors for failed TX/RX tries). We have two kind of
37*4882a593Smuzhiyun * descriptors for RX and TX, control descriptors tell the hw how to send or
38*4882a593Smuzhiyun * receive a packet where to read/write it from/to etc and status descriptors
39*4882a593Smuzhiyun * that contain information about how the packet was sent or received (errors
40*4882a593Smuzhiyun * included).
41*4882a593Smuzhiyun *
42*4882a593Smuzhiyun * Descriptor format is not exactly the same for each MAC chip version so we
43*4882a593Smuzhiyun * have function pointers on &struct ath5k_hw we initialize at runtime based on
44*4882a593Smuzhiyun * the chip used.
45*4882a593Smuzhiyun */
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /************************\
49*4882a593Smuzhiyun * TX Control descriptors *
50*4882a593Smuzhiyun \************************/
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /**
53*4882a593Smuzhiyun * ath5k_hw_setup_2word_tx_desc() - Initialize a 2-word tx control descriptor
54*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
55*4882a593Smuzhiyun * @desc: The &struct ath5k_desc
56*4882a593Smuzhiyun * @pkt_len: Frame length in bytes
57*4882a593Smuzhiyun * @hdr_len: Header length in bytes (only used on AR5210)
58*4882a593Smuzhiyun * @padsize: Any padding we've added to the frame length
59*4882a593Smuzhiyun * @type: One of enum ath5k_pkt_type
60*4882a593Smuzhiyun * @tx_power: Tx power in 0.5dB steps
61*4882a593Smuzhiyun * @tx_rate0: HW idx for transmission rate
62*4882a593Smuzhiyun * @tx_tries0: Max number of retransmissions
63*4882a593Smuzhiyun * @key_index: Index on key table to use for encryption
64*4882a593Smuzhiyun * @antenna_mode: Which antenna to use (0 for auto)
65*4882a593Smuzhiyun * @flags: One of AR5K_TXDESC_* flags (desc.h)
66*4882a593Smuzhiyun * @rtscts_rate: HW idx for RTS/CTS transmission rate
67*4882a593Smuzhiyun * @rtscts_duration: What to put on duration field on the header of RTS/CTS
68*4882a593Smuzhiyun *
69*4882a593Smuzhiyun * Internal function to initialize a 2-Word TX control descriptor
70*4882a593Smuzhiyun * found on AR5210 and AR5211 MACs chips.
71*4882a593Smuzhiyun *
72*4882a593Smuzhiyun * Returns 0 on success or -EINVAL on false input
73*4882a593Smuzhiyun */
74*4882a593Smuzhiyun static int
ath5k_hw_setup_2word_tx_desc(struct ath5k_hw * ah,struct ath5k_desc * desc,unsigned int pkt_len,unsigned int hdr_len,int padsize,enum ath5k_pkt_type type,unsigned int tx_power,unsigned int tx_rate0,unsigned int tx_tries0,unsigned int key_index,unsigned int antenna_mode,unsigned int flags,unsigned int rtscts_rate,unsigned int rtscts_duration)75*4882a593Smuzhiyun ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah,
76*4882a593Smuzhiyun struct ath5k_desc *desc,
77*4882a593Smuzhiyun unsigned int pkt_len, unsigned int hdr_len,
78*4882a593Smuzhiyun int padsize,
79*4882a593Smuzhiyun enum ath5k_pkt_type type,
80*4882a593Smuzhiyun unsigned int tx_power,
81*4882a593Smuzhiyun unsigned int tx_rate0, unsigned int tx_tries0,
82*4882a593Smuzhiyun unsigned int key_index,
83*4882a593Smuzhiyun unsigned int antenna_mode,
84*4882a593Smuzhiyun unsigned int flags,
85*4882a593Smuzhiyun unsigned int rtscts_rate, unsigned int rtscts_duration)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun u32 frame_type;
88*4882a593Smuzhiyun struct ath5k_hw_2w_tx_ctl *tx_ctl;
89*4882a593Smuzhiyun unsigned int frame_len;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /*
94*4882a593Smuzhiyun * Validate input
95*4882a593Smuzhiyun * - Zero retries don't make sense.
96*4882a593Smuzhiyun * - A zero rate will put the HW into a mode where it continuously sends
97*4882a593Smuzhiyun * noise on the channel, so it is important to avoid this.
98*4882a593Smuzhiyun */
99*4882a593Smuzhiyun if (unlikely(tx_tries0 == 0)) {
100*4882a593Smuzhiyun ATH5K_ERR(ah, "zero retries\n");
101*4882a593Smuzhiyun WARN_ON(1);
102*4882a593Smuzhiyun return -EINVAL;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun if (unlikely(tx_rate0 == 0)) {
105*4882a593Smuzhiyun ATH5K_ERR(ah, "zero rate\n");
106*4882a593Smuzhiyun WARN_ON(1);
107*4882a593Smuzhiyun return -EINVAL;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /* Clear descriptor */
111*4882a593Smuzhiyun memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /* Setup control descriptor */
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* Verify and set frame length */
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /* remove padding we might have added before */
118*4882a593Smuzhiyun frame_len = pkt_len - padsize + FCS_LEN;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
121*4882a593Smuzhiyun return -EINVAL;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /* Verify and set buffer length */
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /* NB: beacon's BufLen must be a multiple of 4 bytes */
128*4882a593Smuzhiyun if (type == AR5K_PKT_TYPE_BEACON)
129*4882a593Smuzhiyun pkt_len = roundup(pkt_len, 4);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
132*4882a593Smuzhiyun return -EINVAL;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun * Verify and set header length (only 5210)
138*4882a593Smuzhiyun */
139*4882a593Smuzhiyun if (ah->ah_version == AR5K_AR5210) {
140*4882a593Smuzhiyun if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210)
141*4882a593Smuzhiyun return -EINVAL;
142*4882a593Smuzhiyun tx_ctl->tx_control_0 |=
143*4882a593Smuzhiyun AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /*Differences between 5210-5211*/
147*4882a593Smuzhiyun if (ah->ah_version == AR5K_AR5210) {
148*4882a593Smuzhiyun switch (type) {
149*4882a593Smuzhiyun case AR5K_PKT_TYPE_BEACON:
150*4882a593Smuzhiyun case AR5K_PKT_TYPE_PROBE_RESP:
151*4882a593Smuzhiyun frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
152*4882a593Smuzhiyun break;
153*4882a593Smuzhiyun case AR5K_PKT_TYPE_PIFS:
154*4882a593Smuzhiyun frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
155*4882a593Smuzhiyun break;
156*4882a593Smuzhiyun default:
157*4882a593Smuzhiyun frame_type = type;
158*4882a593Smuzhiyun break;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun tx_ctl->tx_control_0 |=
162*4882a593Smuzhiyun AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210) |
163*4882a593Smuzhiyun AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun } else {
166*4882a593Smuzhiyun tx_ctl->tx_control_0 |=
167*4882a593Smuzhiyun AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
168*4882a593Smuzhiyun AR5K_REG_SM(antenna_mode,
169*4882a593Smuzhiyun AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
170*4882a593Smuzhiyun tx_ctl->tx_control_1 |=
171*4882a593Smuzhiyun AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211);
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun #define _TX_FLAGS(_c, _flag) \
175*4882a593Smuzhiyun if (flags & AR5K_TXDESC_##_flag) { \
176*4882a593Smuzhiyun tx_ctl->tx_control_##_c |= \
177*4882a593Smuzhiyun AR5K_2W_TX_DESC_CTL##_c##_##_flag; \
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun #define _TX_FLAGS_5211(_c, _flag) \
180*4882a593Smuzhiyun if (flags & AR5K_TXDESC_##_flag) { \
181*4882a593Smuzhiyun tx_ctl->tx_control_##_c |= \
182*4882a593Smuzhiyun AR5K_2W_TX_DESC_CTL##_c##_##_flag##_5211; \
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun _TX_FLAGS(0, CLRDMASK);
185*4882a593Smuzhiyun _TX_FLAGS(0, INTREQ);
186*4882a593Smuzhiyun _TX_FLAGS(0, RTSENA);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if (ah->ah_version == AR5K_AR5211) {
189*4882a593Smuzhiyun _TX_FLAGS_5211(0, VEOL);
190*4882a593Smuzhiyun _TX_FLAGS_5211(1, NOACK);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun #undef _TX_FLAGS
194*4882a593Smuzhiyun #undef _TX_FLAGS_5211
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /*
197*4882a593Smuzhiyun * WEP crap
198*4882a593Smuzhiyun */
199*4882a593Smuzhiyun if (key_index != AR5K_TXKEYIX_INVALID) {
200*4882a593Smuzhiyun tx_ctl->tx_control_0 |=
201*4882a593Smuzhiyun AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
202*4882a593Smuzhiyun tx_ctl->tx_control_1 |=
203*4882a593Smuzhiyun AR5K_REG_SM(key_index,
204*4882a593Smuzhiyun AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX);
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /*
208*4882a593Smuzhiyun * RTS/CTS Duration [5210 ?]
209*4882a593Smuzhiyun */
210*4882a593Smuzhiyun if ((ah->ah_version == AR5K_AR5210) &&
211*4882a593Smuzhiyun (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
212*4882a593Smuzhiyun tx_ctl->tx_control_1 |= rtscts_duration &
213*4882a593Smuzhiyun AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun return 0;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun /**
219*4882a593Smuzhiyun * ath5k_hw_setup_4word_tx_desc() - Initialize a 4-word tx control descriptor
220*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
221*4882a593Smuzhiyun * @desc: The &struct ath5k_desc
222*4882a593Smuzhiyun * @pkt_len: Frame length in bytes
223*4882a593Smuzhiyun * @hdr_len: Header length in bytes (only used on AR5210)
224*4882a593Smuzhiyun * @padsize: Any padding we've added to the frame length
225*4882a593Smuzhiyun * @type: One of enum ath5k_pkt_type
226*4882a593Smuzhiyun * @tx_power: Tx power in 0.5dB steps
227*4882a593Smuzhiyun * @tx_rate0: HW idx for transmission rate
228*4882a593Smuzhiyun * @tx_tries0: Max number of retransmissions
229*4882a593Smuzhiyun * @key_index: Index on key table to use for encryption
230*4882a593Smuzhiyun * @antenna_mode: Which antenna to use (0 for auto)
231*4882a593Smuzhiyun * @flags: One of AR5K_TXDESC_* flags (desc.h)
232*4882a593Smuzhiyun * @rtscts_rate: HW idx for RTS/CTS transmission rate
233*4882a593Smuzhiyun * @rtscts_duration: What to put on duration field on the header of RTS/CTS
234*4882a593Smuzhiyun *
235*4882a593Smuzhiyun * Internal function to initialize a 4-Word TX control descriptor
236*4882a593Smuzhiyun * found on AR5212 and later MACs chips.
237*4882a593Smuzhiyun *
238*4882a593Smuzhiyun * Returns 0 on success or -EINVAL on false input
239*4882a593Smuzhiyun */
240*4882a593Smuzhiyun static int
ath5k_hw_setup_4word_tx_desc(struct ath5k_hw * ah,struct ath5k_desc * desc,unsigned int pkt_len,unsigned int hdr_len,int padsize,enum ath5k_pkt_type type,unsigned int tx_power,unsigned int tx_rate0,unsigned int tx_tries0,unsigned int key_index,unsigned int antenna_mode,unsigned int flags,unsigned int rtscts_rate,unsigned int rtscts_duration)241*4882a593Smuzhiyun ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
242*4882a593Smuzhiyun struct ath5k_desc *desc,
243*4882a593Smuzhiyun unsigned int pkt_len, unsigned int hdr_len,
244*4882a593Smuzhiyun int padsize,
245*4882a593Smuzhiyun enum ath5k_pkt_type type,
246*4882a593Smuzhiyun unsigned int tx_power,
247*4882a593Smuzhiyun unsigned int tx_rate0, unsigned int tx_tries0,
248*4882a593Smuzhiyun unsigned int key_index,
249*4882a593Smuzhiyun unsigned int antenna_mode,
250*4882a593Smuzhiyun unsigned int flags,
251*4882a593Smuzhiyun unsigned int rtscts_rate, unsigned int rtscts_duration)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun struct ath5k_hw_4w_tx_ctl *tx_ctl;
254*4882a593Smuzhiyun unsigned int frame_len;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /*
257*4882a593Smuzhiyun * Use local variables for these to reduce load/store access on
258*4882a593Smuzhiyun * uncached memory
259*4882a593Smuzhiyun */
260*4882a593Smuzhiyun u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun /*
265*4882a593Smuzhiyun * Validate input
266*4882a593Smuzhiyun * - Zero retries don't make sense.
267*4882a593Smuzhiyun * - A zero rate will put the HW into a mode where it continuously sends
268*4882a593Smuzhiyun * noise on the channel, so it is important to avoid this.
269*4882a593Smuzhiyun */
270*4882a593Smuzhiyun if (unlikely(tx_tries0 == 0)) {
271*4882a593Smuzhiyun ATH5K_ERR(ah, "zero retries\n");
272*4882a593Smuzhiyun WARN_ON(1);
273*4882a593Smuzhiyun return -EINVAL;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun if (unlikely(tx_rate0 == 0)) {
276*4882a593Smuzhiyun ATH5K_ERR(ah, "zero rate\n");
277*4882a593Smuzhiyun WARN_ON(1);
278*4882a593Smuzhiyun return -EINVAL;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun tx_power += ah->ah_txpower.txp_offset;
282*4882a593Smuzhiyun if (tx_power > AR5K_TUNE_MAX_TXPOWER)
283*4882a593Smuzhiyun tx_power = AR5K_TUNE_MAX_TXPOWER;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* Clear descriptor status area */
286*4882a593Smuzhiyun memset(&desc->ud.ds_tx5212.tx_stat, 0,
287*4882a593Smuzhiyun sizeof(desc->ud.ds_tx5212.tx_stat));
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* Setup control descriptor */
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun /* Verify and set frame length */
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun /* remove padding we might have added before */
294*4882a593Smuzhiyun frame_len = pkt_len - padsize + FCS_LEN;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
297*4882a593Smuzhiyun return -EINVAL;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* Verify and set buffer length */
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* NB: beacon's BufLen must be a multiple of 4 bytes */
304*4882a593Smuzhiyun if (type == AR5K_PKT_TYPE_BEACON)
305*4882a593Smuzhiyun pkt_len = roundup(pkt_len, 4);
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
308*4882a593Smuzhiyun return -EINVAL;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
313*4882a593Smuzhiyun AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
314*4882a593Smuzhiyun txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
315*4882a593Smuzhiyun txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
316*4882a593Smuzhiyun txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun #define _TX_FLAGS(_c, _flag) \
319*4882a593Smuzhiyun if (flags & AR5K_TXDESC_##_flag) { \
320*4882a593Smuzhiyun txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun _TX_FLAGS(0, CLRDMASK);
324*4882a593Smuzhiyun _TX_FLAGS(0, VEOL);
325*4882a593Smuzhiyun _TX_FLAGS(0, INTREQ);
326*4882a593Smuzhiyun _TX_FLAGS(0, RTSENA);
327*4882a593Smuzhiyun _TX_FLAGS(0, CTSENA);
328*4882a593Smuzhiyun _TX_FLAGS(1, NOACK);
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun #undef _TX_FLAGS
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun /*
333*4882a593Smuzhiyun * WEP crap
334*4882a593Smuzhiyun */
335*4882a593Smuzhiyun if (key_index != AR5K_TXKEYIX_INVALID) {
336*4882a593Smuzhiyun txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
337*4882a593Smuzhiyun txctl1 |= AR5K_REG_SM(key_index,
338*4882a593Smuzhiyun AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun /*
342*4882a593Smuzhiyun * RTS/CTS
343*4882a593Smuzhiyun */
344*4882a593Smuzhiyun if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
345*4882a593Smuzhiyun if ((flags & AR5K_TXDESC_RTSENA) &&
346*4882a593Smuzhiyun (flags & AR5K_TXDESC_CTSENA))
347*4882a593Smuzhiyun return -EINVAL;
348*4882a593Smuzhiyun txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
349*4882a593Smuzhiyun txctl3 |= AR5K_REG_SM(rtscts_rate,
350*4882a593Smuzhiyun AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun tx_ctl->tx_control_0 = txctl0;
354*4882a593Smuzhiyun tx_ctl->tx_control_1 = txctl1;
355*4882a593Smuzhiyun tx_ctl->tx_control_2 = txctl2;
356*4882a593Smuzhiyun tx_ctl->tx_control_3 = txctl3;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun return 0;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun /**
362*4882a593Smuzhiyun * ath5k_hw_setup_mrr_tx_desc() - Initialize an MRR tx control descriptor
363*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
364*4882a593Smuzhiyun * @desc: The &struct ath5k_desc
365*4882a593Smuzhiyun * @tx_rate1: HW idx for rate used on transmission series 1
366*4882a593Smuzhiyun * @tx_tries1: Max number of retransmissions for transmission series 1
367*4882a593Smuzhiyun * @tx_rate2: HW idx for rate used on transmission series 2
368*4882a593Smuzhiyun * @tx_tries2: Max number of retransmissions for transmission series 2
369*4882a593Smuzhiyun * @tx_rate3: HW idx for rate used on transmission series 3
370*4882a593Smuzhiyun * @tx_tries3: Max number of retransmissions for transmission series 3
371*4882a593Smuzhiyun *
372*4882a593Smuzhiyun * Multi rate retry (MRR) tx control descriptors are available only on AR5212
373*4882a593Smuzhiyun * MACs, they are part of the normal 4-word tx control descriptor (see above)
374*4882a593Smuzhiyun * but we handle them through a separate function for better abstraction.
375*4882a593Smuzhiyun *
376*4882a593Smuzhiyun * Returns 0 on success or -EINVAL on invalid input
377*4882a593Smuzhiyun */
378*4882a593Smuzhiyun int
ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw * ah,struct ath5k_desc * desc,u_int tx_rate1,u_int tx_tries1,u_int tx_rate2,u_int tx_tries2,u_int tx_rate3,u_int tx_tries3)379*4882a593Smuzhiyun ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah,
380*4882a593Smuzhiyun struct ath5k_desc *desc,
381*4882a593Smuzhiyun u_int tx_rate1, u_int tx_tries1,
382*4882a593Smuzhiyun u_int tx_rate2, u_int tx_tries2,
383*4882a593Smuzhiyun u_int tx_rate3, u_int tx_tries3)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun struct ath5k_hw_4w_tx_ctl *tx_ctl;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /* no mrr support for cards older than 5212 */
388*4882a593Smuzhiyun if (ah->ah_version < AR5K_AR5212)
389*4882a593Smuzhiyun return 0;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /*
392*4882a593Smuzhiyun * Rates can be 0 as long as the retry count is 0 too.
393*4882a593Smuzhiyun * A zero rate and nonzero retry count will put the HW into a mode where
394*4882a593Smuzhiyun * it continuously sends noise on the channel, so it is important to
395*4882a593Smuzhiyun * avoid this.
396*4882a593Smuzhiyun */
397*4882a593Smuzhiyun if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
398*4882a593Smuzhiyun (tx_rate2 == 0 && tx_tries2 != 0) ||
399*4882a593Smuzhiyun (tx_rate3 == 0 && tx_tries3 != 0))) {
400*4882a593Smuzhiyun ATH5K_ERR(ah, "zero rate\n");
401*4882a593Smuzhiyun WARN_ON(1);
402*4882a593Smuzhiyun return -EINVAL;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun if (ah->ah_version == AR5K_AR5212) {
406*4882a593Smuzhiyun tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun #define _XTX_TRIES(_n) \
409*4882a593Smuzhiyun if (tx_tries##_n) { \
410*4882a593Smuzhiyun tx_ctl->tx_control_2 |= \
411*4882a593Smuzhiyun AR5K_REG_SM(tx_tries##_n, \
412*4882a593Smuzhiyun AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
413*4882a593Smuzhiyun tx_ctl->tx_control_3 |= \
414*4882a593Smuzhiyun AR5K_REG_SM(tx_rate##_n, \
415*4882a593Smuzhiyun AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun _XTX_TRIES(1);
419*4882a593Smuzhiyun _XTX_TRIES(2);
420*4882a593Smuzhiyun _XTX_TRIES(3);
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun #undef _XTX_TRIES
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun return 1;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun return 0;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun /***********************\
432*4882a593Smuzhiyun * TX Status descriptors *
433*4882a593Smuzhiyun \***********************/
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun /**
436*4882a593Smuzhiyun * ath5k_hw_proc_2word_tx_status() - Process a tx status descriptor on 5210/1
437*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
438*4882a593Smuzhiyun * @desc: The &struct ath5k_desc
439*4882a593Smuzhiyun * @ts: The &struct ath5k_tx_status
440*4882a593Smuzhiyun */
441*4882a593Smuzhiyun static int
ath5k_hw_proc_2word_tx_status(struct ath5k_hw * ah,struct ath5k_desc * desc,struct ath5k_tx_status * ts)442*4882a593Smuzhiyun ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
443*4882a593Smuzhiyun struct ath5k_desc *desc,
444*4882a593Smuzhiyun struct ath5k_tx_status *ts)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun struct ath5k_hw_tx_status *tx_status;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun tx_status = &desc->ud.ds_tx5210.tx_stat;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun /* No frame has been send or error */
451*4882a593Smuzhiyun if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
452*4882a593Smuzhiyun return -EINPROGRESS;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun /*
455*4882a593Smuzhiyun * Get descriptor status
456*4882a593Smuzhiyun */
457*4882a593Smuzhiyun ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
458*4882a593Smuzhiyun AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
459*4882a593Smuzhiyun ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
460*4882a593Smuzhiyun AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
461*4882a593Smuzhiyun ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0,
462*4882a593Smuzhiyun AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
463*4882a593Smuzhiyun /*TODO: ts->ts_virtcol + test*/
464*4882a593Smuzhiyun ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
465*4882a593Smuzhiyun AR5K_DESC_TX_STATUS1_SEQ_NUM);
466*4882a593Smuzhiyun ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
467*4882a593Smuzhiyun AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
468*4882a593Smuzhiyun ts->ts_antenna = 1;
469*4882a593Smuzhiyun ts->ts_status = 0;
470*4882a593Smuzhiyun ts->ts_final_idx = 0;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
473*4882a593Smuzhiyun if (tx_status->tx_status_0 &
474*4882a593Smuzhiyun AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
475*4882a593Smuzhiyun ts->ts_status |= AR5K_TXERR_XRETRY;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
478*4882a593Smuzhiyun ts->ts_status |= AR5K_TXERR_FIFO;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
481*4882a593Smuzhiyun ts->ts_status |= AR5K_TXERR_FILT;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun return 0;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun /**
488*4882a593Smuzhiyun * ath5k_hw_proc_4word_tx_status() - Process a tx status descriptor on 5212
489*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
490*4882a593Smuzhiyun * @desc: The &struct ath5k_desc
491*4882a593Smuzhiyun * @ts: The &struct ath5k_tx_status
492*4882a593Smuzhiyun */
493*4882a593Smuzhiyun static int
ath5k_hw_proc_4word_tx_status(struct ath5k_hw * ah,struct ath5k_desc * desc,struct ath5k_tx_status * ts)494*4882a593Smuzhiyun ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
495*4882a593Smuzhiyun struct ath5k_desc *desc,
496*4882a593Smuzhiyun struct ath5k_tx_status *ts)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun struct ath5k_hw_tx_status *tx_status;
499*4882a593Smuzhiyun u32 txstat0, txstat1;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun tx_status = &desc->ud.ds_tx5212.tx_stat;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun txstat1 = READ_ONCE(tx_status->tx_status_1);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun /* No frame has been send or error */
506*4882a593Smuzhiyun if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE)))
507*4882a593Smuzhiyun return -EINPROGRESS;
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun txstat0 = READ_ONCE(tx_status->tx_status_0);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun /*
512*4882a593Smuzhiyun * Get descriptor status
513*4882a593Smuzhiyun */
514*4882a593Smuzhiyun ts->ts_tstamp = AR5K_REG_MS(txstat0,
515*4882a593Smuzhiyun AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
516*4882a593Smuzhiyun ts->ts_shortretry = AR5K_REG_MS(txstat0,
517*4882a593Smuzhiyun AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
518*4882a593Smuzhiyun ts->ts_final_retry = AR5K_REG_MS(txstat0,
519*4882a593Smuzhiyun AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
520*4882a593Smuzhiyun ts->ts_seqnum = AR5K_REG_MS(txstat1,
521*4882a593Smuzhiyun AR5K_DESC_TX_STATUS1_SEQ_NUM);
522*4882a593Smuzhiyun ts->ts_rssi = AR5K_REG_MS(txstat1,
523*4882a593Smuzhiyun AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
524*4882a593Smuzhiyun ts->ts_antenna = (txstat1 &
525*4882a593Smuzhiyun AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1;
526*4882a593Smuzhiyun ts->ts_status = 0;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun ts->ts_final_idx = AR5K_REG_MS(txstat1,
529*4882a593Smuzhiyun AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212);
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun /* TX error */
532*4882a593Smuzhiyun if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
533*4882a593Smuzhiyun if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
534*4882a593Smuzhiyun ts->ts_status |= AR5K_TXERR_XRETRY;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
537*4882a593Smuzhiyun ts->ts_status |= AR5K_TXERR_FIFO;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED)
540*4882a593Smuzhiyun ts->ts_status |= AR5K_TXERR_FILT;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun return 0;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /****************\
548*4882a593Smuzhiyun * RX Descriptors *
549*4882a593Smuzhiyun \****************/
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun /**
552*4882a593Smuzhiyun * ath5k_hw_setup_rx_desc() - Initialize an rx control descriptor
553*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
554*4882a593Smuzhiyun * @desc: The &struct ath5k_desc
555*4882a593Smuzhiyun * @size: RX buffer length in bytes
556*4882a593Smuzhiyun * @flags: One of AR5K_RXDESC_* flags
557*4882a593Smuzhiyun */
558*4882a593Smuzhiyun int
ath5k_hw_setup_rx_desc(struct ath5k_hw * ah,struct ath5k_desc * desc,u32 size,unsigned int flags)559*4882a593Smuzhiyun ath5k_hw_setup_rx_desc(struct ath5k_hw *ah,
560*4882a593Smuzhiyun struct ath5k_desc *desc,
561*4882a593Smuzhiyun u32 size, unsigned int flags)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun struct ath5k_hw_rx_ctl *rx_ctl;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun rx_ctl = &desc->ud.ds_rx.rx_ctl;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun /*
568*4882a593Smuzhiyun * Clear the descriptor
569*4882a593Smuzhiyun * If we don't clean the status descriptor,
570*4882a593Smuzhiyun * while scanning we get too many results,
571*4882a593Smuzhiyun * most of them virtual, after some secs
572*4882a593Smuzhiyun * of scanning system hangs. M.F.
573*4882a593Smuzhiyun */
574*4882a593Smuzhiyun memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun if (unlikely(size & ~AR5K_DESC_RX_CTL1_BUF_LEN))
577*4882a593Smuzhiyun return -EINVAL;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun /* Setup descriptor */
580*4882a593Smuzhiyun rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun if (flags & AR5K_RXDESC_INTREQ)
583*4882a593Smuzhiyun rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun return 0;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun /**
589*4882a593Smuzhiyun * ath5k_hw_proc_5210_rx_status() - Process the rx status descriptor on 5210/1
590*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
591*4882a593Smuzhiyun * @desc: The &struct ath5k_desc
592*4882a593Smuzhiyun * @rs: The &struct ath5k_rx_status
593*4882a593Smuzhiyun *
594*4882a593Smuzhiyun * Internal function used to process an RX status descriptor
595*4882a593Smuzhiyun * on AR5210/5211 MAC.
596*4882a593Smuzhiyun *
597*4882a593Smuzhiyun * Returns 0 on success or -EINPROGRESS in case we haven't received the who;e
598*4882a593Smuzhiyun * frame yet.
599*4882a593Smuzhiyun */
600*4882a593Smuzhiyun static int
ath5k_hw_proc_5210_rx_status(struct ath5k_hw * ah,struct ath5k_desc * desc,struct ath5k_rx_status * rs)601*4882a593Smuzhiyun ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
602*4882a593Smuzhiyun struct ath5k_desc *desc,
603*4882a593Smuzhiyun struct ath5k_rx_status *rs)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun struct ath5k_hw_rx_status *rx_status;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun rx_status = &desc->ud.ds_rx.rx_stat;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun /* No frame received / not ready */
610*4882a593Smuzhiyun if (unlikely(!(rx_status->rx_status_1 &
611*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_DONE)))
612*4882a593Smuzhiyun return -EINPROGRESS;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun memset(rs, 0, sizeof(struct ath5k_rx_status));
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun /*
617*4882a593Smuzhiyun * Frame receive status
618*4882a593Smuzhiyun */
619*4882a593Smuzhiyun rs->rs_datalen = rx_status->rx_status_0 &
620*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
621*4882a593Smuzhiyun rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
622*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
623*4882a593Smuzhiyun rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
624*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
625*4882a593Smuzhiyun rs->rs_more = !!(rx_status->rx_status_0 &
626*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS0_MORE);
627*4882a593Smuzhiyun /* TODO: this timestamp is 13 bit, later on we assume 15 bit!
628*4882a593Smuzhiyun * also the HAL code for 5210 says the timestamp is bits [10..22] of the
629*4882a593Smuzhiyun * TSF, and extends the timestamp here to 15 bit.
630*4882a593Smuzhiyun * we need to check on 5210...
631*4882a593Smuzhiyun */
632*4882a593Smuzhiyun rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
633*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun if (ah->ah_version == AR5K_AR5211)
636*4882a593Smuzhiyun rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
637*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211);
638*4882a593Smuzhiyun else
639*4882a593Smuzhiyun rs->rs_antenna = (rx_status->rx_status_0 &
640*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210)
641*4882a593Smuzhiyun ? 2 : 1;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun /*
644*4882a593Smuzhiyun * Key table status
645*4882a593Smuzhiyun */
646*4882a593Smuzhiyun if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
647*4882a593Smuzhiyun rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
648*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
649*4882a593Smuzhiyun else
650*4882a593Smuzhiyun rs->rs_keyix = AR5K_RXKEYIX_INVALID;
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun /*
653*4882a593Smuzhiyun * Receive/descriptor errors
654*4882a593Smuzhiyun */
655*4882a593Smuzhiyun if (!(rx_status->rx_status_1 &
656*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
657*4882a593Smuzhiyun if (rx_status->rx_status_1 &
658*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
659*4882a593Smuzhiyun rs->rs_status |= AR5K_RXERR_CRC;
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun /* only on 5210 */
662*4882a593Smuzhiyun if ((ah->ah_version == AR5K_AR5210) &&
663*4882a593Smuzhiyun (rx_status->rx_status_1 &
664*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210))
665*4882a593Smuzhiyun rs->rs_status |= AR5K_RXERR_FIFO;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun if (rx_status->rx_status_1 &
668*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
669*4882a593Smuzhiyun rs->rs_status |= AR5K_RXERR_PHY;
670*4882a593Smuzhiyun rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
671*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun if (rx_status->rx_status_1 &
675*4882a593Smuzhiyun AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
676*4882a593Smuzhiyun rs->rs_status |= AR5K_RXERR_DECRYPT;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun return 0;
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun /**
683*4882a593Smuzhiyun * ath5k_hw_proc_5212_rx_status() - Process the rx status descriptor on 5212
684*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
685*4882a593Smuzhiyun * @desc: The &struct ath5k_desc
686*4882a593Smuzhiyun * @rs: The &struct ath5k_rx_status
687*4882a593Smuzhiyun *
688*4882a593Smuzhiyun * Internal function used to process an RX status descriptor
689*4882a593Smuzhiyun * on AR5212 and later MAC.
690*4882a593Smuzhiyun *
691*4882a593Smuzhiyun * Returns 0 on success or -EINPROGRESS in case we haven't received the who;e
692*4882a593Smuzhiyun * frame yet.
693*4882a593Smuzhiyun */
694*4882a593Smuzhiyun static int
ath5k_hw_proc_5212_rx_status(struct ath5k_hw * ah,struct ath5k_desc * desc,struct ath5k_rx_status * rs)695*4882a593Smuzhiyun ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
696*4882a593Smuzhiyun struct ath5k_desc *desc,
697*4882a593Smuzhiyun struct ath5k_rx_status *rs)
698*4882a593Smuzhiyun {
699*4882a593Smuzhiyun struct ath5k_hw_rx_status *rx_status;
700*4882a593Smuzhiyun u32 rxstat0, rxstat1;
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun rx_status = &desc->ud.ds_rx.rx_stat;
703*4882a593Smuzhiyun rxstat1 = READ_ONCE(rx_status->rx_status_1);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /* No frame received / not ready */
706*4882a593Smuzhiyun if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE)))
707*4882a593Smuzhiyun return -EINPROGRESS;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun memset(rs, 0, sizeof(struct ath5k_rx_status));
710*4882a593Smuzhiyun rxstat0 = READ_ONCE(rx_status->rx_status_0);
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun /*
713*4882a593Smuzhiyun * Frame receive status
714*4882a593Smuzhiyun */
715*4882a593Smuzhiyun rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
716*4882a593Smuzhiyun rs->rs_rssi = AR5K_REG_MS(rxstat0,
717*4882a593Smuzhiyun AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
718*4882a593Smuzhiyun rs->rs_rate = AR5K_REG_MS(rxstat0,
719*4882a593Smuzhiyun AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
720*4882a593Smuzhiyun rs->rs_antenna = AR5K_REG_MS(rxstat0,
721*4882a593Smuzhiyun AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
722*4882a593Smuzhiyun rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE);
723*4882a593Smuzhiyun rs->rs_tstamp = AR5K_REG_MS(rxstat1,
724*4882a593Smuzhiyun AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun /*
727*4882a593Smuzhiyun * Key table status
728*4882a593Smuzhiyun */
729*4882a593Smuzhiyun if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
730*4882a593Smuzhiyun rs->rs_keyix = AR5K_REG_MS(rxstat1,
731*4882a593Smuzhiyun AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
732*4882a593Smuzhiyun else
733*4882a593Smuzhiyun rs->rs_keyix = AR5K_RXKEYIX_INVALID;
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun /*
736*4882a593Smuzhiyun * Receive/descriptor errors
737*4882a593Smuzhiyun */
738*4882a593Smuzhiyun if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
739*4882a593Smuzhiyun if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
740*4882a593Smuzhiyun rs->rs_status |= AR5K_RXERR_CRC;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
743*4882a593Smuzhiyun rs->rs_status |= AR5K_RXERR_PHY;
744*4882a593Smuzhiyun rs->rs_phyerr = AR5K_REG_MS(rxstat1,
745*4882a593Smuzhiyun AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE);
746*4882a593Smuzhiyun if (!ah->ah_capabilities.cap_has_phyerr_counters)
747*4882a593Smuzhiyun ath5k_ani_phy_error_report(ah, rs->rs_phyerr);
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
751*4882a593Smuzhiyun rs->rs_status |= AR5K_RXERR_DECRYPT;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
754*4882a593Smuzhiyun rs->rs_status |= AR5K_RXERR_MIC;
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun return 0;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun /********\
761*4882a593Smuzhiyun * Attach *
762*4882a593Smuzhiyun \********/
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun /**
765*4882a593Smuzhiyun * ath5k_hw_init_desc_functions() - Init function pointers inside ah
766*4882a593Smuzhiyun * @ah: The &struct ath5k_hw
767*4882a593Smuzhiyun *
768*4882a593Smuzhiyun * Maps the internal descriptor functions to the function pointers on ah, used
769*4882a593Smuzhiyun * from above. This is used as an abstraction layer to handle the various chips
770*4882a593Smuzhiyun * the same way.
771*4882a593Smuzhiyun */
772*4882a593Smuzhiyun int
ath5k_hw_init_desc_functions(struct ath5k_hw * ah)773*4882a593Smuzhiyun ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
774*4882a593Smuzhiyun {
775*4882a593Smuzhiyun if (ah->ah_version == AR5K_AR5212) {
776*4882a593Smuzhiyun ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
777*4882a593Smuzhiyun ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
778*4882a593Smuzhiyun ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
779*4882a593Smuzhiyun } else if (ah->ah_version <= AR5K_AR5211) {
780*4882a593Smuzhiyun ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
781*4882a593Smuzhiyun ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
782*4882a593Smuzhiyun ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
783*4882a593Smuzhiyun } else
784*4882a593Smuzhiyun return -ENOTSUPP;
785*4882a593Smuzhiyun return 0;
786*4882a593Smuzhiyun }
787