xmit.c revision f37d923422b61884a75a2a64865ed03ca5ccfc6d
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"
335100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch#include "pio.h"
3403b29773b613f10d2f97dbf0983f1c4c58507967Michael Buesch
35e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of a CCK PLCP header. */
378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
38e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
39e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (plcp->raw[0]) {
40e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x0A:
418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 0;
42e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x14:
438318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 1;
44e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x37:
458318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 2;
46e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x6E:
478318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 3;
48e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
49e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
508318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
51e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
52e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of an OFDM PLCP header. */
548318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
55e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
568318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	int base = aphy ? 0 : 4;
578318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
58e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (plcp->raw[0] & 0xF) {
59e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xB:
608318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 0;
61e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xF:
628318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 1;
63e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xA:
648318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 2;
65e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xE:
668318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 3;
67e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x9:
688318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 4;
69e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xD:
708318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 5;
71e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x8:
728318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 6;
73e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xC:
748318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 7;
75e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
76e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
778318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
78e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
79e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
80e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_cck(const u8 bitrate)
81e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
82e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
83e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
84e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x0A;
85e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
86e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x14;
87e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
88e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x37;
89e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
90e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x6E;
91e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
92e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
93e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
94e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
95e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
96e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
97e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
98e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
99e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
100e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xB;
101e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
102e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xF;
103e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
104e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xA;
105e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
106e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xE;
107e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
108e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x9;
109e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
110e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xD;
111e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
112e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x8;
113e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
114e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xC;
115e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
116e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
117e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
118e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
119e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
120e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
121e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			   const u16 octets, const u8 bitrate)
122e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
123e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	__le32 *data = &(plcp->data);
124e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	__u8 *raw = plcp->raw;
125e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
126e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (b43_is_ofdm_rate(bitrate)) {
1271a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		u32 d;
1281a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch
1291a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d = b43_plcp_get_ratecode_ofdm(bitrate);
130e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(octets & 0xF000);
1311a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d |= (octets << 5);
1321a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		*data = cpu_to_le32(d);
133e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
134e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		u32 plen;
135e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
136e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		plen = octets * 16 / bitrate;
137e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if ((octets * 16 % bitrate) > 0) {
138e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			plen++;
139e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if ((bitrate == B43_CCK_RATE_11MB)
140e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    && ((octets * 8 % 11) < 4)) {
141e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x84;
142e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else
143e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x04;
144e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else
145e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			raw[1] = 0x04;
146e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		*data |= cpu_to_le32(plen << 16);
147e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		raw[0] = b43_plcp_get_ratecode_cck(bitrate);
148e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
149e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
150e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
151e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_calc_fallback_rate(u8 bitrate)
152e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
153e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
154e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
155e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
156e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
157e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
158e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
159e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_2MB;
160e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
161e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
162e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
163e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
164e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
165e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_6MB;
166e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
167e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_9MB;
168e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
169e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_12MB;
170e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
171e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_18MB;
172e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
173e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_24MB;
174e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
175e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_36MB;
176e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
177e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_48MB;
178e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
179e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
180e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
181e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
182e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
183eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch/* Generate a TX data header. */
18409552ccd8277e6382097e93a40f7311a09449367Michael Bueschint b43_generate_txhdr(struct b43_wldev *dev,
18509552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u8 *_txhdr,
18609552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       const unsigned char *fragment_data,
18709552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       unsigned int fragment_len,
188e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		       const struct ieee80211_tx_info *info,
18909552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u16 cookie)
190e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
191eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
192e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_phy *phy = &dev->phy;
193e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct ieee80211_hdr *wlhdr =
194e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (const struct ieee80211_hdr *)fragment_data;
195e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT));
196f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	__le16 fctl = wlhdr->frame_control;
1978318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	struct ieee80211_rate *fbrate;
198e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 rate, rate_fb;
199e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int rate_ofdm, rate_fb_ofdm;
200e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	unsigned int plcp_fragment_len;
201e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 mac_ctl = 0;
202e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phy_ctl = 0;
203e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 extra_ft = 0;
2042e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	struct ieee80211_rate *txrate;
205e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
206e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(txhdr, 0, sizeof(*txhdr));
207e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
208e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
2092e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
210e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_ofdm = b43_is_ofdm_rate(rate);
211e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate;
2128318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	rate_fb = fbrate->hw_value;
213e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
214e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
215e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
216e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate);
217e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
218e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
219e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_frame_ctl = wlhdr->frame_control;
220e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
221e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
222e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Calculate duration for fallback rate */
223e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if ((rate_fb == rate) ||
224e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
225e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id == cpu_to_le16(0))) {
226e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* If the fallback rate equals the normal rate or the
227e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * dur_id field contains an AID, CFP magic or 0,
228e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * use the original dur_id field. */
229e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->dur_fb = wlhdr->duration_id;
230e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
231e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		txhdr->dur_fb = ieee80211_generic_frame_duration(
232e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			dev->wl->hw, info->control.vif, fragment_len, fbrate);
233e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
234e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
235e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp_fragment_len = fragment_len + FCS_LEN;
236e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (use_encryption) {
237e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		u8 key_idx = info->control.hw_key->hw_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. */
255e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		plcp_fragment_len += info->control.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;
262f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison		wlhdr_len = ieee80211_hdrlen(fctl);
263e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		iv_len = min((size_t) info->control.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;
294e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
295eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
2969db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch
297e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	switch (b43_ieee80211_antenna_sanitize(dev, info->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 */
318e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
319eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_ACK;
320f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	if (!ieee80211_is_pspoll(fctl))
321eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_HWSEQ;
322e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
323eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_STMSDU;
324e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A)
325eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_5GHZ;
326e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
327eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_LONGFRAME;
328e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
329e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Generate the RTS or CTS-to-self frame */
330e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
331e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	    (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
332e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int len;
333e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		struct ieee80211_hdr *hdr;
334e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate, rts_rate_fb;
335e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate_ofdm, rts_rate_fb_ofdm;
336eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		struct b43_plcp_hdr6 *plcp;
3372e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg		struct ieee80211_rate *rts_cts_rate;
338e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
339e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
3402e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg
3412e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg		rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
342e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
343e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb = b43_calc_fallback_rate(rts_rate);
344e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
345e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
346e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
347eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			struct ieee80211_cts *cts;
348eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
349eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			if (b43_is_old_txhdr_format(dev)) {
350eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
351eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->old_format.rts_frame);
352eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			} else {
353eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
354eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->new_format.rts_frame);
355eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
356e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
357e4d6b7951812d98417feb10784e400e253caf633Michael Buesch						fragment_data, fragment_len,
358e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg						info, cts);
359eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDCTS;
360e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_cts);
361e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
362eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			struct ieee80211_rts *rts;
363eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
364eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			if (b43_is_old_txhdr_format(dev)) {
365eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
366eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->old_format.rts_frame);
367eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			} else {
368eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
369eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->new_format.rts_frame);
370eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
371e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_rts_get(dev->wl->hw, info->control.vif,
372eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					  fragment_data, fragment_len,
373e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg					  info, rts);
374eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDRTS;
375e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_rts);
376e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
377e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		len += FCS_LEN;
378eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
379eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		/* Generate the PLCP headers for the RTS/CTS frame */
380eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		if (b43_is_old_txhdr_format(dev))
381eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			plcp = &txhdr->old_format.rts_plcp;
382eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
383eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			plcp = &txhdr->new_format.rts_plcp;
384eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
385eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      len, rts_rate);
386eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		plcp = &txhdr->rts_plcp_fb;
387eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
388e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				      len, rts_rate_fb);
389eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
390eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		if (b43_is_old_txhdr_format(dev)) {
391eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
392eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				(&txhdr->old_format.rts_frame);
393eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
394eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
395eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				(&txhdr->new_format.rts_frame);
396eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
397e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->rts_dur_fb = hdr->duration_id;
398eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
399e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_ofdm) {
400eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_OFDM;
401e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
402e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_ofdm(rts_rate);
403eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
404eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_CCK;
405e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
406e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_cck(rts_rate);
407eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
408e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_fb_ofdm)
409eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
410eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
411eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_CCK;
412e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
413e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
414e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Magic cookie */
415eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	if (b43_is_old_txhdr_format(dev))
416eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		txhdr->old_format.cookie = cpu_to_le16(cookie);
417eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
418eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		txhdr->new_format.cookie = cpu_to_le16(cookie);
419e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
420e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Apply the bitfields */
421e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
422e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
423e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->extra_ft = extra_ft;
424e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
42509552ccd8277e6382097e93a40f7311a09449367Michael Buesch	return 0;
426e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
427e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
428e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev,
429e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       u8 in_rssi, int ofdm,
430e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       int adjust_2053, int adjust_2050)
431e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
432e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
433e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s32 tmp;
434e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
435e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (phy->radio_ver) {
436e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2050:
437e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (ofdm) {
438e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
439e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (tmp > 127)
440e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 256;
441e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp *= 73;
442e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp /= 64;
443e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (adjust_2050)
444e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
445e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			else
446e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 3;
447e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
44895de2841aad971867851b59c0c5253ecc2e19832Larry Finger			if (dev->dev->bus->sprom.
449e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    boardflags_lo & B43_BFL_RSSI) {
450e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				if (in_rssi > 63)
451e4d6b7951812d98417feb10784e400e253caf633Michael Buesch					in_rssi = 63;
452e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = phy->nrssi_lt[in_rssi];
453e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
454e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -131;
455e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
456e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 57;
457e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else {
458e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = in_rssi;
459e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
460e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -149;
461e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 68;
463e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
464e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (phy->type == B43_PHYTYPE_G && adjust_2050)
465e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
466e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
467e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
468e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2060:
469e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (in_rssi > 127)
470e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi - 256;
471e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
472e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
473e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
474e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
475e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp = in_rssi;
476e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp -= 11;
477e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp *= 103;
478e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp /= 64;
479e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (adjust_2053)
480e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 109;
481e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
482e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 83;
483e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
484e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
485e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return (s8) tmp;
486e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO
489e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0
490e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi)
491e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
492e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
493e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s8 ret;
494e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
495e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A) {
496e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		//TODO: Incomplete specs.
497e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = 0;
498e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else
499e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1);
500e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
501e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return ret;
502e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
503e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif
504e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
505e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
506e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
507e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_rx_status status;
508e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_plcp_hdr6 *plcp;
509e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_hdr *wlhdr;
510e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
511f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	__le16 fctl;
512e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phystat0, phystat3, chanstat, mactime;
513e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 macstat;
514e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 chanid;
5158318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	u16 phytype;
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	macstat = le32_to_cpu(rxhdr->mac_status);
524e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	mactime = le16_to_cpu(rxhdr->mac_time);
525e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanstat = le16_to_cpu(rxhdr->channel);
5268318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	phytype = chanstat & B43_RX_CHAN_PHYTYPE;
527e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
528e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_FCSERR)
529e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11FCSErrorCount++;
530e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DECERR) {
531e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* Decryption with the given key failed.
532e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * Drop the packet. We also won't be able to decrypt it with
533e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * the key in software. */
534e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
535e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
536e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
537e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Skip PLCP and padding */
538e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
539e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) {
540e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (1)\n");
541e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
542e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
543e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp = (struct b43_plcp_hdr6 *)(skb->data + padding);
544e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding);
545e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* The skb contains the Wireless Header + payload data now */
546e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */  + FCS_LEN))) {
547e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (2)\n");
548e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
549e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
550e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	wlhdr = (struct ieee80211_hdr *)(skb->data);
551f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	fctl = wlhdr->frame_control;
552e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
553e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DEC) {
554e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int keyidx;
555e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
556e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
557e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = ((macstat & B43_RX_MAC_KEYIDX)
558e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			  >> B43_RX_MAC_KEYIDX_SHIFT);
559e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* We must adjust the key index here. We want the "physical"
560e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * key index, but the ucode passed it slightly different.
561e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 */
562e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = b43_kidx_to_raw(dev, keyidx);
563e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(keyidx >= dev->max_nr_keys);
564e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
565e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
566f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison			wlhdr_len = ieee80211_hdrlen(fctl);
567e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (unlikely(skb->len < (wlhdr_len + 3))) {
568e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				b43dbg(dev->wl,
569e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				       "RX: Packet size underrun (3)\n");
570e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				goto drop;
571e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
572e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			status.flag |= RX_FLAG_DECRYPTED;
573e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
5767b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	/* Link quality statistics */
577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.noise = dev->stats.link_noise;
5787b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
5797b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch//		s8 rssi = max(rxhdr->power0, rxhdr->power1);
5807b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//TODO: Find out what the rssi value is (dBm or percentage?)
5817b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//      and also find out what the maximum possible value is.
5827b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//      Fill status.ssi and status.signal fields.
5837b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	} else {
584566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf		status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
5857b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat0 & B43_RX_PHYST0_OFDM),
5867b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat0 & B43_RX_PHYST0_GAINCTL),
5877b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat3 & B43_RX_PHYST3_TRSTATE));
588566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf		status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
5897b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	}
5907b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch
591e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phystat0 & B43_RX_PHYST0_OFDM)
5928318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
5938318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg						phytype == B43_PHYTYPE_A);
594e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
5958318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
596e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
597c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
598c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	/*
599d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * All frames on monitor interfaces and beacons always need a full
600d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
601d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * purposes and beacons for IBSS merging.
602d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * This code assumes we get to process the packet within 16 bits
603d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * of timestamp, i.e. about 65 milliseconds after the PHY received
604d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * the first symbol.
605c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	 */
606f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
607c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		u16 low_mactime_now;
608c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
609c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		b43_tsf_read(dev, &status.mactime);
610c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		low_mactime_now = status.mactime;
611c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime = status.mactime & ~0xFFFFULL;
612c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime += mactime;
613c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		if (low_mactime_now <= mactime)
614c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville			status.mactime -= 0x10000;
615c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.flag |= RX_FLAG_TSFT;
616c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	}
617e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
618e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
619e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
620e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_A:
6218318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_5GHZ;
622d987160b710c98997015832422a05e18d9f0f925Michael Buesch		B43_WARN_ON(1);
623d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* FIXME: We don't really know which value the "chanid" contains.
624d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 *        So the following assignment might be wrong. */
6258318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.freq = b43_channel_to_freq_5ghz(chanid);
626e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
627e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_G:
6288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_2GHZ;
629d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the radio channel cookie value as used
630d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * to tune the radio. */
631e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		status.freq = chanid + 2400;
632d987160b710c98997015832422a05e18d9f0f925Michael Buesch		break;
633d987160b710c98997015832422a05e18d9f0f925Michael Buesch	case B43_PHYTYPE_N:
634d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the SHM channel cookie. Which is the plain
635d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * channel number in b43. */
6368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		if (chanstat & B43_RX_CHAN_5GHZ) {
6378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_5GHZ;
6388318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.freq = b43_freq_to_channel_5ghz(chanid);
6398318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		} else {
6408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_2GHZ;
6418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.freq = b43_freq_to_channel_2ghz(chanid);
6428318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		}
643e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
644e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
645e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
646d987160b710c98997015832422a05e18d9f0f925Michael Buesch		goto drop;
647e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
648e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
649e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	dev->stats.last_rx = jiffies;
650e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
651e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
652e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return;
653e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop:
654e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43dbg(dev->wl, "RX: Packet dropped\n");
655e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	dev_kfree_skb_any(skb);
656e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
657e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
658e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev,
659e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			 const struct b43_txstatus *status)
660e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
661e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_debugfs_log_txstat(dev, status);
662e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
663e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->intermediate)
664e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
665e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->for_ampdu)
666e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
667e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (!status->acked)
668e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11ACKFailureCount++;
669e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->rts_count) {
670e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (status->rts_count == 0xF)	//FIXME
671e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSFailureCount++;
672e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
673e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSSuccessCount++;
674e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
675e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
6765100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
6775100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_handle_txstatus(dev, status);
6785100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
6795100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_handle_txstatus(dev, status);
680e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
681e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
6825100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch/* Fill out the mac80211 TXstatus report based on the b43-specific
6835100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * txstatus report data. This returns a boolean whether the frame was
6845100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * successfully transmitted. */
685e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Bergbool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
6865100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			      const struct b43_txstatus *status)
687e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
6885100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	bool frame_success = 1;
6895100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch
6905100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (status->acked) {
6915100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was ACKed. */
692e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		report->flags |= IEEE80211_TX_STAT_ACK;
6935100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	} else {
6945100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was not ACKed... */
695e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
6965100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			/* ...but we expected an ACK. */
6975100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			frame_success = 0;
698e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			report->status.excessive_retries = 1;
6995100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		}
7005100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	}
7015100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (status->frame_count == 0) {
7025100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was not transmitted at all. */
703e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		report->status.retry_count = 0;
7045100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	} else
705e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		report->status.retry_count = status->frame_count - 1;
7065100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch
7075100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	return frame_success;
708e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
709e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
710e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */
711e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev)
712e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
7135100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
7145100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_tx_suspend(dev);
7155100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
7165100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_tx_suspend(dev);
717e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
718e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
719e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */
720e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev)
721e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
7225100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
7235100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_tx_resume(dev);
7245100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
7255100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_tx_resume(dev);
726e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
727