xmit.c revision d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736
1e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/*
2e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
3e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  Broadcom B43 wireless driver
4e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
5e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  Transmission (TX/RX) related functions.
6e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
7e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
81f21ad2a4f7f66855dae600ddd635ff5fb299bbdStefano Brivio  Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
9e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
10e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
11e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
12e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
13e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  This program is free software; you can redistribute it and/or modify
14e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  it under the terms of the GNU General Public License as published by
15e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  the Free Software Foundation; either version 2 of the License, or
16e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  (at your option) any later version.
17e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
18e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  This program is distributed in the hope that it will be useful,
19e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  but WITHOUT ANY WARRANTY; without even the implied warranty of
20e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  GNU General Public License for more details.
22e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
23e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  You should have received a copy of the GNU General Public License
24e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  along with this program; see the file COPYING.  If not, write to
25e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
26e4d6b7951812d98417feb10784e400e253caf633Michael Buesch  Boston, MA 02110-1301, USA.
27e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
28e4d6b7951812d98417feb10784e400e253caf633Michael Buesch*/
29e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
30e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "xmit.h"
31e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "phy.h"
32e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "dma.h"
3303b29773b613f10d2f97dbf0983f1c4c58507967Michael Buesch
34e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
358318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of a CCK PLCP header. */
368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
37e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
38e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (plcp->raw[0]) {
39e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x0A:
408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 0;
41e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x14:
428318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 1;
43e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x37:
448318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 2;
45e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x6E:
468318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 3;
47e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
48e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
498318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
50e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
51e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
528318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of an OFDM PLCP header. */
538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
54e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
558318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	int base = aphy ? 0 : 4;
568318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
57e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (plcp->raw[0] & 0xF) {
58e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xB:
598318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 0;
60e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xF:
618318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 1;
62e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xA:
638318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 2;
64e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xE:
658318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 3;
66e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x9:
678318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 4;
68e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xD:
698318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 5;
70e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x8:
718318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 6;
72e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xC:
738318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 7;
74e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
75e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
768318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
77e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
78e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
79e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_cck(const u8 bitrate)
80e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
81e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
82e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
83e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x0A;
84e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
85e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x14;
86e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
87e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x37;
88e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
89e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x6E;
90e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
91e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
92e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
93e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
94e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
95e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
96e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
97e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
98e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
99e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xB;
100e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
101e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xF;
102e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
103e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xA;
104e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
105e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xE;
106e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
107e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x9;
108e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
109e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xD;
110e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
111e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x8;
112e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
113e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xC;
114e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
115e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
116e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
117e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
118e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
119e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
120e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			   const u16 octets, const u8 bitrate)
121e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
122e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	__le32 *data = &(plcp->data);
123e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	__u8 *raw = plcp->raw;
124e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
125e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (b43_is_ofdm_rate(bitrate)) {
1261a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		u32 d;
1271a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch
1281a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d = b43_plcp_get_ratecode_ofdm(bitrate);
129e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(octets & 0xF000);
1301a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d |= (octets << 5);
1311a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		*data = cpu_to_le32(d);
132e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
133e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		u32 plen;
134e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
135e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		plen = octets * 16 / bitrate;
136e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if ((octets * 16 % bitrate) > 0) {
137e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			plen++;
138e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if ((bitrate == B43_CCK_RATE_11MB)
139e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    && ((octets * 8 % 11) < 4)) {
140e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x84;
141e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else
142e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x04;
143e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else
144e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			raw[1] = 0x04;
145e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		*data |= cpu_to_le32(plen << 16);
146e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		raw[0] = b43_plcp_get_ratecode_cck(bitrate);
147e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
148e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
149e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
150e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_calc_fallback_rate(u8 bitrate)
151e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
152e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
153e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
154e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
155e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
156e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
157e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
158e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_2MB;
159e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
160e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
161e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
162e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
163e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
164e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_6MB;
165e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
166e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_9MB;
167e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
168e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_12MB;
169e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
170e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_18MB;
171e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
172e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_24MB;
173e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
174e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_36MB;
175e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
176e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_48MB;
177e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
178e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
179e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
180e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
181e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
182eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch/* Generate a TX data header. */
18309552ccd8277e6382097e93a40f7311a09449367Michael Bueschint b43_generate_txhdr(struct b43_wldev *dev,
18409552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u8 *_txhdr,
18509552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       const unsigned char *fragment_data,
18609552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       unsigned int fragment_len,
18709552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       const struct ieee80211_tx_control *txctl,
18809552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u16 cookie)
189e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
190eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
191e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_phy *phy = &dev->phy;
192e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct ieee80211_hdr *wlhdr =
193e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (const struct ieee80211_hdr *)fragment_data;
194e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
195e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 fctl = le16_to_cpu(wlhdr->frame_control);
1968318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	struct ieee80211_rate *fbrate;
197e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 rate, rate_fb;
198e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int rate_ofdm, rate_fb_ofdm;
199e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	unsigned int plcp_fragment_len;
200e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 mac_ctl = 0;
201e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phy_ctl = 0;
202e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 extra_ft = 0;
203e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
204e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(txhdr, 0, sizeof(*txhdr));
205e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
2068318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	WARN_ON(!txctl->tx_rate);
2078318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB;
208e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_ofdm = b43_is_ofdm_rate(rate);
2098318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	fbrate = txctl->alt_retry_rate ? : txctl->tx_rate;
2108318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	rate_fb = fbrate->hw_value;
211e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
212e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
213e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
214e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate);
215e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
216e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
217e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_frame_ctl = wlhdr->frame_control;
218e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
219e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
220e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Calculate duration for fallback rate */
221e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if ((rate_fb == rate) ||
222e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
223e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id == cpu_to_le16(0))) {
224e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* If the fallback rate equals the normal rate or the
225e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * dur_id field contains an AID, CFP magic or 0,
226e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * use the original dur_id field. */
227e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->dur_fb = wlhdr->duration_id;
228e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
229e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
23032bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg								 txctl->vif,
231e4d6b7951812d98417feb10784e400e253caf633Michael Buesch								 fragment_len,
2328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg								 fbrate);
233e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
234e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
235e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp_fragment_len = fragment_len + FCS_LEN;
236e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (use_encryption) {
237e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		u8 key_idx = (u16) (txctl->key_idx);
238e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		struct b43_key *key;
239e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
240e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		size_t iv_len;
241e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
242e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(key_idx >= dev->max_nr_keys);
243e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		key = &(dev->key[key_idx]);
2447be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch
24509552ccd8277e6382097e93a40f7311a09449367Michael Buesch		if (unlikely(!key->keyconf)) {
24609552ccd8277e6382097e93a40f7311a09449367Michael Buesch			/* This key is invalid. This might only happen
24709552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * in a short timeframe after machine resume before
24809552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * we were able to reconfigure keys.
24909552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * Drop this packet completely. Do not transmit it
25009552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * unencrypted to avoid leaking information. */
25109552ccd8277e6382097e93a40f7311a09449367Michael Buesch			return -ENOKEY;
2527be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch		}
25309552ccd8277e6382097e93a40f7311a09449367Michael Buesch
25409552ccd8277e6382097e93a40f7311a09449367Michael Buesch		/* Hardware appends ICV. */
25509552ccd8277e6382097e93a40f7311a09449367Michael Buesch		plcp_fragment_len += txctl->icv_len;
25609552ccd8277e6382097e93a40f7311a09449367Michael Buesch
25709552ccd8277e6382097e93a40f7311a09449367Michael Buesch		key_idx = b43_kidx_to_fw(dev, key_idx);
25809552ccd8277e6382097e93a40f7311a09449367Michael Buesch		mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
25909552ccd8277e6382097e93a40f7311a09449367Michael Buesch			   B43_TXH_MAC_KEYIDX;
26009552ccd8277e6382097e93a40f7311a09449367Michael Buesch		mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
26109552ccd8277e6382097e93a40f7311a09449367Michael Buesch			   B43_TXH_MAC_KEYALG;
26209552ccd8277e6382097e93a40f7311a09449367Michael Buesch		wlhdr_len = ieee80211_get_hdrlen(fctl);
26309552ccd8277e6382097e93a40f7311a09449367Michael Buesch		iv_len = min((size_t) txctl->iv_len,
26409552ccd8277e6382097e93a40f7311a09449367Michael Buesch			     ARRAY_SIZE(txhdr->iv));
26509552ccd8277e6382097e93a40f7311a09449367Michael Buesch		memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
266e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
267eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	if (b43_is_old_txhdr_format(dev)) {
268eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
269eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      plcp_fragment_len, rate);
270eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	} else {
271eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp),
272eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      plcp_fragment_len, rate);
273eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	}
274e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
275e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			      plcp_fragment_len, rate_fb);
276e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
277e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Extra Frame Types */
278e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_fb_ofdm)
279eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		extra_ft |= B43_TXH_EFT_FB_OFDM;
280eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
281eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		extra_ft |= B43_TXH_EFT_FB_CCK;
282e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
283e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Set channel radio code. Note that the micrcode ORs 0x100 to
284e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * this value before comparing it to the value in SHM, if this
285e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * is a 5Ghz packet.
286e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 */
287e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->chan_radio_code = phy->channel;
288e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
289e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* PHY TX Control word */
290e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
291eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ENC_OFDM;
292eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
293eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ENC_CCK;
2948318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
295eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
2969db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch
2979db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) {
2989db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 0: /* Default */
299eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT01AUTO;
300e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
3019db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 1: /* Antenna 0 */
302eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT0;
303e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
3049db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 2: /* Antenna 1 */
305eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT1;
306eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		break;
307eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	case 3: /* Antenna 2 */
308eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT2;
309eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		break;
310eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	case 4: /* Antenna 3 */
311eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT3;
312e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
313e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
314e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
315e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
316e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
317e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* MAC control */
318e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK))
319eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_ACK;
320e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
321e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	      ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
322eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_HWSEQ;
323e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
324eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_STMSDU;
325e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A)
326eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_5GHZ;
32774cfdba7ce7b601559a4bcdc9054baf1bdc6948dMichael Buesch	if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)
328eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_LONGFRAME;
329e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
330e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Generate the RTS or CTS-to-self frame */
331e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
332e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
333e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int len;
334e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		struct ieee80211_hdr *hdr;
335e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate, rts_rate_fb;
336e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate_ofdm, rts_rate_fb_ofdm;
337eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		struct b43_plcp_hdr6 *plcp;
338e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
3398318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		WARN_ON(!txctl->rts_cts_rate);
3408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
341e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
342e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb = b43_calc_fallback_rate(rts_rate);
343e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
344e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
345e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
346eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			struct ieee80211_cts *cts;
347eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
348eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			if (b43_is_old_txhdr_format(dev)) {
349eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
350eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->old_format.rts_frame);
351eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			} else {
352eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
353eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->new_format.rts_frame);
354eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
35532bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg			ieee80211_ctstoself_get(dev->wl->hw, txctl->vif,
356e4d6b7951812d98417feb10784e400e253caf633Michael Buesch						fragment_data, fragment_len,
357eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch						txctl, cts);
358eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDCTS;
359e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_cts);
360e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
361eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			struct ieee80211_rts *rts;
362eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
363eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			if (b43_is_old_txhdr_format(dev)) {
364eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
365eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->old_format.rts_frame);
366eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			} else {
367eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
368eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->new_format.rts_frame);
369eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
37032bfd35d4b63bd63de4bb0d791ef049c3c868726Johannes Berg			ieee80211_rts_get(dev->wl->hw, txctl->vif,
371eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					  fragment_data, fragment_len,
372eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					  txctl, rts);
373eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDRTS;
374e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_rts);
375e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
376e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		len += FCS_LEN;
377eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
378eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		/* Generate the PLCP headers for the RTS/CTS frame */
379eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		if (b43_is_old_txhdr_format(dev))
380eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			plcp = &txhdr->old_format.rts_plcp;
381eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
382eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			plcp = &txhdr->new_format.rts_plcp;
383eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
384eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      len, rts_rate);
385eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		plcp = &txhdr->rts_plcp_fb;
386eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
387e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				      len, rts_rate_fb);
388eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
389eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		if (b43_is_old_txhdr_format(dev)) {
390eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
391eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				(&txhdr->old_format.rts_frame);
392eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
393eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
394eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				(&txhdr->new_format.rts_frame);
395eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
396e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->rts_dur_fb = hdr->duration_id;
397eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
398e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_ofdm) {
399eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_OFDM;
400e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
401e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_ofdm(rts_rate);
402eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
403eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_CCK;
404e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
405e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_cck(rts_rate);
406eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
407e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_fb_ofdm)
408eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
409eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
410eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_CCK;
411e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
412e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
413e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Magic cookie */
414eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	if (b43_is_old_txhdr_format(dev))
415eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		txhdr->old_format.cookie = cpu_to_le16(cookie);
416eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
417eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		txhdr->new_format.cookie = cpu_to_le16(cookie);
418e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
419e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Apply the bitfields */
420e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
421e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
422e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->extra_ft = extra_ft;
423e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
42409552ccd8277e6382097e93a40f7311a09449367Michael Buesch	return 0;
425e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
426e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
427e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev,
428e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       u8 in_rssi, int ofdm,
429e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       int adjust_2053, int adjust_2050)
430e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
431e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
432e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s32 tmp;
433e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
434e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (phy->radio_ver) {
435e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2050:
436e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (ofdm) {
437e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
438e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (tmp > 127)
439e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 256;
440e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp *= 73;
441e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp /= 64;
442e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (adjust_2050)
443e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
444e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			else
445e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 3;
446e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
44795de2841aad971867851b59c0c5253ecc2e19832Larry Finger			if (dev->dev->bus->sprom.
448e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    boardflags_lo & B43_BFL_RSSI) {
449e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				if (in_rssi > 63)
450e4d6b7951812d98417feb10784e400e253caf633Michael Buesch					in_rssi = 63;
451e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = phy->nrssi_lt[in_rssi];
452e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
453e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -131;
454e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
455e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 57;
456e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else {
457e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = in_rssi;
458e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
459e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -149;
460e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
461e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 68;
462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
463e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (phy->type == B43_PHYTYPE_G && adjust_2050)
464e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
465e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
466e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
467e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2060:
468e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (in_rssi > 127)
469e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi - 256;
470e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
471e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
472e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
473e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
474e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp = in_rssi;
475e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp -= 11;
476e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp *= 103;
477e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp /= 64;
478e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (adjust_2053)
479e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 109;
480e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
481e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 83;
482e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
483e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
484e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return (s8) tmp;
485e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
486e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO
488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0
489e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi)
490e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
491e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
492e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s8 ret;
493e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
494e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A) {
495e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		//TODO: Incomplete specs.
496e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = 0;
497e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else
498e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1);
499e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
500e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return ret;
501e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
502e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif
503e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
504e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
505e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
506e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_rx_status status;
507e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_plcp_hdr6 *plcp;
508e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_hdr *wlhdr;
509e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
510e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 fctl;
511e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phystat0, phystat3, chanstat, mactime;
512e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 macstat;
513e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 chanid;
5148318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	u16 phytype;
515e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 jssi;
516e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int padding;
517e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
518e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(&status, 0, sizeof(status));
519e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
520e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Get metadata about the frame from the header. */
521e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	phystat0 = le16_to_cpu(rxhdr->phy_status0);
522e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	phystat3 = le16_to_cpu(rxhdr->phy_status3);
523e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	jssi = rxhdr->jssi;
524e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	macstat = le32_to_cpu(rxhdr->mac_status);
525e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	mactime = le16_to_cpu(rxhdr->mac_time);
526e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanstat = le16_to_cpu(rxhdr->channel);
5278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	phytype = chanstat & B43_RX_CHAN_PHYTYPE;
528e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
529e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_FCSERR)
530e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11FCSErrorCount++;
531e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DECERR) {
532e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* Decryption with the given key failed.
533e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * Drop the packet. We also won't be able to decrypt it with
534e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * the key in software. */
535e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
536e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
537e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
538e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Skip PLCP and padding */
539e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
540e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) {
541e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (1)\n");
542e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
543e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
544e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp = (struct b43_plcp_hdr6 *)(skb->data + padding);
545e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding);
546e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* The skb contains the Wireless Header + payload data now */
547e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */  + FCS_LEN))) {
548e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (2)\n");
549e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
550e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
551e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	wlhdr = (struct ieee80211_hdr *)(skb->data);
552e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	fctl = le16_to_cpu(wlhdr->frame_control);
553e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
554e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DEC) {
555e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int keyidx;
556e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
557e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
558e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = ((macstat & B43_RX_MAC_KEYIDX)
559e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			  >> B43_RX_MAC_KEYIDX_SHIFT);
560e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* We must adjust the key index here. We want the "physical"
561e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * key index, but the ucode passed it slightly different.
562e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 */
563e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = b43_kidx_to_raw(dev, keyidx);
564e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(keyidx >= dev->max_nr_keys);
565e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
566e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
567e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			wlhdr_len = ieee80211_get_hdrlen(fctl);
568e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (unlikely(skb->len < (wlhdr_len + 3))) {
569e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				b43dbg(dev->wl,
570e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				       "RX: Packet size underrun (3)\n");
571e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				goto drop;
572e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
573e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			status.flag |= RX_FLAG_DECRYPTED;
574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
576e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.ssi = b43_rssi_postprocess(dev, jssi,
578e4d6b7951812d98417feb10784e400e253caf633Michael Buesch					  (phystat0 & B43_RX_PHYST0_OFDM),
579e4d6b7951812d98417feb10784e400e253caf633Michael Buesch					  (phystat0 & B43_RX_PHYST0_GAINCTL),
580e4d6b7951812d98417feb10784e400e253caf633Michael Buesch					  (phystat3 & B43_RX_PHYST3_TRSTATE));
581e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.noise = dev->stats.link_noise;
582e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* the next line looks wrong, but is what mac80211 wants */
583e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.signal = (jssi * 100) / B43_RX_MAX_SSI;
584e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phystat0 & B43_RX_PHYST0_OFDM)
5858318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
5868318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg						phytype == B43_PHYTYPE_A);
587e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
5888318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
589e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
590c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
591c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	/*
592d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * All frames on monitor interfaces and beacons always need a full
593d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
594d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * purposes and beacons for IBSS merging.
595d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * This code assumes we get to process the packet within 16 bits
596d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * of timestamp, i.e. about 65 milliseconds after the PHY received
597d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * the first symbol.
598c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	 */
599d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
600d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	    == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
601d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	    dev->wl->radiotap_enabled) {
602c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		u16 low_mactime_now;
603c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
604c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		b43_tsf_read(dev, &status.mactime);
605c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		low_mactime_now = status.mactime;
606c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime = status.mactime & ~0xFFFFULL;
607c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime += mactime;
608c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		if (low_mactime_now <= mactime)
609c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville			status.mactime -= 0x10000;
610c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.flag |= RX_FLAG_TSFT;
611c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	}
612e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
613e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
614e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
615e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_A:
6168318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_5GHZ;
617d987160b710c98997015832422a05e18d9f0f925Michael Buesch		B43_WARN_ON(1);
618d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* FIXME: We don't really know which value the "chanid" contains.
619d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 *        So the following assignment might be wrong. */
6208318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.freq = b43_channel_to_freq_5ghz(chanid);
621e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
622e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_G:
6238318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_2GHZ;
624d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the radio channel cookie value as used
625d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * to tune the radio. */
626e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		status.freq = chanid + 2400;
627d987160b710c98997015832422a05e18d9f0f925Michael Buesch		break;
628d987160b710c98997015832422a05e18d9f0f925Michael Buesch	case B43_PHYTYPE_N:
629d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the SHM channel cookie. Which is the plain
630d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * channel number in b43. */
6318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		if (chanstat & B43_RX_CHAN_5GHZ) {
6328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_5GHZ;
6338318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.freq = b43_freq_to_channel_5ghz(chanid);
6348318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		} else {
6358318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_2GHZ;
6368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.freq = b43_freq_to_channel_2ghz(chanid);
6378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		}
638e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
639e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
640e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
641d987160b710c98997015832422a05e18d9f0f925Michael Buesch		goto drop;
642e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
643e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
644e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	dev->stats.last_rx = jiffies;
645e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
646e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
647e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return;
648e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop:
649e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43dbg(dev->wl, "RX: Packet dropped\n");
650e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	dev_kfree_skb_any(skb);
651e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
652e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
653e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev,
654e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			 const struct b43_txstatus *status)
655e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
656e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_debugfs_log_txstat(dev, status);
657e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
658e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->intermediate)
659e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
660e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->for_ampdu)
661e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
662e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (!status->acked)
663e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11ACKFailureCount++;
664e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->rts_count) {
665e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (status->rts_count == 0xF)	//FIXME
666e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSFailureCount++;
667e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
668e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSSuccessCount++;
669e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
670e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
67103b29773b613f10d2f97dbf0983f1c4c58507967Michael Buesch	b43_dma_handle_txstatus(dev, status);
672e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
673e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
674e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Handle TX status report as received through DMA/PIO queues */
675e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_hwtxstatus(struct b43_wldev *dev,
676e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			   const struct b43_hwtxstatus *hw)
677e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
678e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_txstatus status;
679e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 tmp;
680e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
681e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.cookie = le16_to_cpu(hw->cookie);
682e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.seq = le16_to_cpu(hw->seq);
683e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.phy_stat = hw->phy_stat;
684e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	tmp = hw->count;
685e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.frame_count = (tmp >> 4);
686e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.rts_count = (tmp & 0x0F);
687e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	tmp = hw->flags;
688e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.supp_reason = ((tmp & 0x1C) >> 2);
689e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.pm_indicated = !!(tmp & 0x80);
690e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.intermediate = !!(tmp & 0x40);
691e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.for_ampdu = !!(tmp & 0x20);
692e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.acked = !!(tmp & 0x02);
693e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
694e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_handle_txstatus(dev, &status);
695e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
696e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
697e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */
698e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev)
699e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
70003b29773b613f10d2f97dbf0983f1c4c58507967Michael Buesch	b43_dma_tx_suspend(dev);
701e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
702e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
703e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */
704e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev)
705e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
70603b29773b613f10d2f97dbf0983f1c4c58507967Michael Buesch	b43_dma_tx_resume(dev);
707e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
708e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
709e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0
710e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic void upload_qos_parms(struct b43_wldev *dev,
711e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			     const u16 * parms, u16 offset)
712e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
713e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int i;
714e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
715e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	for (i = 0; i < B43_NR_QOSPARMS; i++) {
716e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43_shm_write16(dev, B43_SHM_SHARED,
717e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				offset + (i * 2), parms[i]);
718e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
719e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
720e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif
721e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
722e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Initialize the QoS parameters */
723e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_qos_init(struct b43_wldev *dev)
724e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
725e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* FIXME: This function must probably be called from the mac80211
726e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * config callback. */
727e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return;
728e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
729e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
730e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	//FIXME kill magic
731e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4);
732e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
733e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/*TODO: We might need some stack support here to get the values. */
734e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
735