xmit.c revision 72f5f457564e8ebc6c38ee4f98ee59cd03c2f614
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
3088499ab3d8dbbf9c080416952603742666c71262Michael Buesch#include "xmit.h"
31ef1a628d83fc0423c36e773281162be790503168Michael Buesch#include "phy_common.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	}
498318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
50e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
51e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
528318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of an OFDM PLCP header. */
53a3c0b87c4f21911fb7185902dd13f0e3cd7f33f7Lorenzo Navastatic int 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	}
758318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
76e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
77e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
78e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_cck(const u8 bitrate)
79e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
80e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
81e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
82e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x0A;
83e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
84e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x14;
85e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
86e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x37;
87e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
88e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x6E;
89e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
90e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
91e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
92e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
93e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
94e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
95e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
96e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
97e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
98e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xB;
99e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
100e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xF;
101e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
102e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xA;
103e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
104e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xE;
105e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
106e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x9;
107e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
108e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xD;
109e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
110e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x8;
111e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
112e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xC;
113e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
114e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
115e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
116e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
117e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
118e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
119e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			   const u16 octets, const u8 bitrate)
120e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
121e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	__u8 *raw = plcp->raw;
122e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
123e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (b43_is_ofdm_rate(bitrate)) {
1241a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		u32 d;
1251a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch
1261a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d = b43_plcp_get_ratecode_ofdm(bitrate);
127e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(octets & 0xF000);
1281a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d |= (octets << 5);
129b52a033c2c501a8015df3727a4bd73389ccb1641Matthieu CASTET		plcp->data = cpu_to_le32(d);
130e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
131e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		u32 plen;
132e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
133e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		plen = octets * 16 / bitrate;
134e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if ((octets * 16 % bitrate) > 0) {
135e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			plen++;
136e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if ((bitrate == B43_CCK_RATE_11MB)
137e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    && ((octets * 8 % 11) < 4)) {
138e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x84;
139e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else
140e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x04;
141e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else
142e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			raw[1] = 0x04;
143b52a033c2c501a8015df3727a4bd73389ccb1641Matthieu CASTET		plcp->data |= cpu_to_le32(plen << 16);
144e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		raw[0] = b43_plcp_get_ratecode_cck(bitrate);
145e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
146e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
147e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
148e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_calc_fallback_rate(u8 bitrate)
149e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
150e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
151e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
152e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
153e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
154e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
155e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
156e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_2MB;
157e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
158e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
159e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
160e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
161e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
162e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_6MB;
163e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
164e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_9MB;
165e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
166e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_12MB;
167e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
168e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_18MB;
169e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
170e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_24MB;
171e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
172e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_36MB;
173e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
174e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_48MB;
175e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
176e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
177e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
178e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
179e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
180eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch/* Generate a TX data header. */
18109552ccd8277e6382097e93a40f7311a09449367Michael Bueschint b43_generate_txhdr(struct b43_wldev *dev,
18209552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u8 *_txhdr,
183035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		       struct sk_buff *skb_frag,
184e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		       struct ieee80211_tx_info *info,
18509552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u16 cookie)
186e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
187035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski	const unsigned char *fragment_data = skb_frag->data;
188035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski	unsigned int fragment_len = skb_frag->len;
189eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
190e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_phy *phy = &dev->phy;
191e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct ieee80211_hdr *wlhdr =
192e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (const struct ieee80211_hdr *)fragment_data;
193d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg	int use_encryption = !!info->control.hw_key;
194f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	__le16 fctl = wlhdr->frame_control;
1958318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	struct ieee80211_rate *fbrate;
196e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 rate, rate_fb;
197e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int rate_ofdm, rate_fb_ofdm;
198e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	unsigned int plcp_fragment_len;
199e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 mac_ctl = 0;
200e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phy_ctl = 0;
201e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 extra_ft = 0;
2022e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	struct ieee80211_rate *txrate;
203e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	struct ieee80211_tx_rate *rates;
204e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
205e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(txhdr, 0, sizeof(*txhdr));
206e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
207e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
2082e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
209e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_ofdm = b43_is_ofdm_rate(rate);
210870abdf67170daa9f1022e55a35c469239fcc74cFelix Fietkau	fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate;
2118318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	rate_fb = fbrate->hw_value;
212e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
213e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
214e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
215e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate);
216e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
217e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
218e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_frame_ctl = wlhdr->frame_control;
219e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
220e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
221e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Calculate duration for fallback rate */
222e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if ((rate_fb == rate) ||
223e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
224e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id == cpu_to_le16(0))) {
225e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* If the fallback rate equals the normal rate or the
226e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * dur_id field contains an AID, CFP magic or 0,
227e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * use the original dur_id field. */
228e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->dur_fb = wlhdr->duration_id;
229e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
230e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		txhdr->dur_fb = ieee80211_generic_frame_duration(
231e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			dev->wl->hw, info->control.vif, fragment_len, fbrate);
232e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
233e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
234e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp_fragment_len = fragment_len + FCS_LEN;
235e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (use_encryption) {
236e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		u8 key_idx = info->control.hw_key->hw_key_idx;
237e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		struct b43_key *key;
238e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
239e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		size_t iv_len;
240e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
24166d2d089c394c7e31020947d682523f77a93244bMichael Buesch		B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key));
242e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		key = &(dev->key[key_idx]);
2437be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch
24409552ccd8277e6382097e93a40f7311a09449367Michael Buesch		if (unlikely(!key->keyconf)) {
24509552ccd8277e6382097e93a40f7311a09449367Michael Buesch			/* This key is invalid. This might only happen
24609552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * in a short timeframe after machine resume before
24709552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * we were able to reconfigure keys.
24809552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * Drop this packet completely. Do not transmit it
24909552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * unencrypted to avoid leaking information. */
25009552ccd8277e6382097e93a40f7311a09449367Michael Buesch			return -ENOKEY;
2517be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch		}
25209552ccd8277e6382097e93a40f7311a09449367Michael Buesch
25309552ccd8277e6382097e93a40f7311a09449367Michael Buesch		/* Hardware appends ICV. */
25476708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		plcp_fragment_len += info->control.hw_key->icv_len;
25509552ccd8277e6382097e93a40f7311a09449367Michael Buesch
25609552ccd8277e6382097e93a40f7311a09449367Michael Buesch		key_idx = b43_kidx_to_fw(dev, key_idx);
25709552ccd8277e6382097e93a40f7311a09449367Michael Buesch		mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
25809552ccd8277e6382097e93a40f7311a09449367Michael Buesch			   B43_TXH_MAC_KEYIDX;
25909552ccd8277e6382097e93a40f7311a09449367Michael Buesch		mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
26009552ccd8277e6382097e93a40f7311a09449367Michael Buesch			   B43_TXH_MAC_KEYALG;
261f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison		wlhdr_len = ieee80211_hdrlen(fctl);
262035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		if (key->algorithm == B43_SEC_ALGO_TKIP) {
263035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			u16 phase1key[5];
264035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			int i;
265035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			/* we give the phase1key and iv16 here, the key is stored in
266035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			 * shm. With that the hardware can do phase 2 and encryption.
267035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			 */
268035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
269035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski					IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
270cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			/* phase1key is in host endian. Copy to little-endian txhdr->iv. */
271cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			for (i = 0; i < 5; i++) {
272cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch				txhdr->iv[i * 2 + 0] = phase1key[i];
273cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch				txhdr->iv[i * 2 + 1] = phase1key[i] >> 8;
274cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			}
275035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			/* iv16 */
276035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
277035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		} else {
278035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			iv_len = min((size_t) info->control.hw_key->iv_len,
279035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski				     ARRAY_SIZE(txhdr->iv));
280035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
281035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		}
282e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
283eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	if (b43_is_old_txhdr_format(dev)) {
284eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
285eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      plcp_fragment_len, rate);
286eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	} else {
287eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp),
288eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      plcp_fragment_len, rate);
289eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	}
290e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
291e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			      plcp_fragment_len, rate_fb);
292e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
293e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Extra Frame Types */
294e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_fb_ofdm)
295eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		extra_ft |= B43_TXH_EFT_FB_OFDM;
296eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
297eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		extra_ft |= B43_TXH_EFT_FB_CCK;
298e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
299e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Set channel radio code. Note that the micrcode ORs 0x100 to
300e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * this value before comparing it to the value in SHM, if this
301e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * is a 5Ghz packet.
302e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 */
303e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->chan_radio_code = phy->channel;
304e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
305e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* PHY TX Control word */
306e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
307eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ENC_OFDM;
308eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
309eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ENC_CCK;
310e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
311eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
3129db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch
313e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) {
3149db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 0: /* Default */
315eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT01AUTO;
316e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
3179db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 1: /* Antenna 0 */
318eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT0;
319e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
3209db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 2: /* Antenna 1 */
321eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT1;
322eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		break;
323eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	case 3: /* Antenna 2 */
324eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT2;
325eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		break;
326eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	case 4: /* Antenna 3 */
327eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT3;
328e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
329e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
330e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
331e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
332e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
333e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	rates = info->control.rates;
334e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* MAC control */
335e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
336eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_ACK;
337f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg	/* use hardware sequence counter as the non-TID counter */
338f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
339eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_HWSEQ;
340e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
341eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_STMSDU;
342e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A)
343eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_5GHZ;
344e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
345e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	/* Overwrite rates[0].count to make the retry calculation
346e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * in the tx status easier. need the actual retry limit to
347e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * detect whether the fallback rate was used.
348e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 */
349e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
350e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	    (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
351e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
352eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_LONGFRAME;
353e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else {
354e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
355e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	}
356e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
357e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Generate the RTS or CTS-to-self frame */
358e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
359e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
360e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int len;
361e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		struct ieee80211_hdr *hdr;
362e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate, rts_rate_fb;
363e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate_ofdm, rts_rate_fb_ofdm;
364eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		struct b43_plcp_hdr6 *plcp;
3652e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg		struct ieee80211_rate *rts_cts_rate;
366e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
367e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
3682e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg
3692e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg		rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
370e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
371e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb = b43_calc_fallback_rate(rts_rate);
372e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
373e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
374e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
375eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			struct ieee80211_cts *cts;
376eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
377eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			if (b43_is_old_txhdr_format(dev)) {
378eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
379eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->old_format.rts_frame);
380eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			} else {
381eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
382eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->new_format.rts_frame);
383eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
384e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
385e4d6b7951812d98417feb10784e400e253caf633Michael Buesch						fragment_data, fragment_len,
386e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg						info, cts);
387eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDCTS;
388e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_cts);
389e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
390eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			struct ieee80211_rts *rts;
391eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
392eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			if (b43_is_old_txhdr_format(dev)) {
393eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
394eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->old_format.rts_frame);
395eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			} else {
396eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
397eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->new_format.rts_frame);
398eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
399e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_rts_get(dev->wl->hw, info->control.vif,
400eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					  fragment_data, fragment_len,
401e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg					  info, rts);
402eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDRTS;
403e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_rts);
404e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
405e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		len += FCS_LEN;
406eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
407eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		/* Generate the PLCP headers for the RTS/CTS frame */
408eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		if (b43_is_old_txhdr_format(dev))
409eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			plcp = &txhdr->old_format.rts_plcp;
410eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
411eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			plcp = &txhdr->new_format.rts_plcp;
412eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
413eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      len, rts_rate);
414eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		plcp = &txhdr->rts_plcp_fb;
415eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
416e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				      len, rts_rate_fb);
417eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
418eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		if (b43_is_old_txhdr_format(dev)) {
419eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
420eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				(&txhdr->old_format.rts_frame);
421eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
422eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
423eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				(&txhdr->new_format.rts_frame);
424eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
425e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->rts_dur_fb = hdr->duration_id;
426eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
427e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_ofdm) {
428eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_OFDM;
429e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
430e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_ofdm(rts_rate);
431eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
432eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_CCK;
433e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
434e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_cck(rts_rate);
435eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
436e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_fb_ofdm)
437eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
438eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
439eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_CCK;
440e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
441e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
442e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Magic cookie */
443eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	if (b43_is_old_txhdr_format(dev))
444eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		txhdr->old_format.cookie = cpu_to_le16(cookie);
445eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
446eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		txhdr->new_format.cookie = cpu_to_le16(cookie);
447e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
448e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Apply the bitfields */
449e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
450e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
451e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->extra_ft = extra_ft;
452e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
45309552ccd8277e6382097e93a40f7311a09449367Michael Buesch	return 0;
454e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
455e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
456e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev,
457e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       u8 in_rssi, int ofdm,
458e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       int adjust_2053, int adjust_2050)
459e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
460e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
461ef1a628d83fc0423c36e773281162be790503168Michael Buesch	struct b43_phy_g *gphy = phy->g;
462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s32 tmp;
463e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
464e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (phy->radio_ver) {
465e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2050:
466e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (ofdm) {
467e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
468e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (tmp > 127)
469e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 256;
470e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp *= 73;
471e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp /= 64;
472e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (adjust_2050)
473e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
474e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			else
475e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 3;
476e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
47795de2841aad971867851b59c0c5253ecc2e19832Larry Finger			if (dev->dev->bus->sprom.
478e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    boardflags_lo & B43_BFL_RSSI) {
479e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				if (in_rssi > 63)
480e4d6b7951812d98417feb10784e400e253caf633Michael Buesch					in_rssi = 63;
481ef1a628d83fc0423c36e773281162be790503168Michael Buesch				B43_WARN_ON(phy->type != B43_PHYTYPE_G);
482ef1a628d83fc0423c36e773281162be790503168Michael Buesch				tmp = gphy->nrssi_lt[in_rssi];
483e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
484e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -131;
485e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
486e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 57;
487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else {
488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = in_rssi;
489e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
490e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -149;
491e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
492e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 68;
493e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
494e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (phy->type == B43_PHYTYPE_G && adjust_2050)
495e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
496e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
497e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
498e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2060:
499e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (in_rssi > 127)
500e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi - 256;
501e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
502e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
503e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
504e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
505e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp = in_rssi;
506e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp -= 11;
507e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp *= 103;
508e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp /= 64;
509e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (adjust_2053)
510e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 109;
511e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
512e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 83;
513e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
514e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
515e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return (s8) tmp;
516e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
517e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
518e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO
519e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0
520e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi)
521e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
522e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
523e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s8 ret;
524e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
525e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A) {
526e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		//TODO: Incomplete specs.
527e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = 0;
528e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else
529e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1);
530e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
531e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return ret;
532e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
533e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif
534e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
535e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
536e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
537e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_rx_status status;
538e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_plcp_hdr6 *plcp;
539e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_hdr *wlhdr;
540e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
541f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	__le16 fctl;
542e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phystat0, phystat3, chanstat, mactime;
543e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 macstat;
544e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 chanid;
5458318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	u16 phytype;
546e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int padding;
547e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
548e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(&status, 0, sizeof(status));
549e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
550e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Get metadata about the frame from the header. */
551e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	phystat0 = le16_to_cpu(rxhdr->phy_status0);
552e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	phystat3 = le16_to_cpu(rxhdr->phy_status3);
553e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	macstat = le32_to_cpu(rxhdr->mac_status);
554e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	mactime = le16_to_cpu(rxhdr->mac_time);
555e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanstat = le16_to_cpu(rxhdr->channel);
5568318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	phytype = chanstat & B43_RX_CHAN_PHYTYPE;
557e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
558ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
559e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11FCSErrorCount++;
560ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_FAILED_FCS_CRC;
561ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	}
562ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV)))
563ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_FAILED_PLCP_CRC;
564ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (phystat0 & B43_RX_PHYST0_SHORTPRMBL)
565ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_SHORTPRE;
566e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DECERR) {
567e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* Decryption with the given key failed.
568e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * Drop the packet. We also won't be able to decrypt it with
569e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * the key in software. */
570e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
571e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
572e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
573e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Skip PLCP and padding */
574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) {
576e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (1)\n");
577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
578e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
579e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp = (struct b43_plcp_hdr6 *)(skb->data + padding);
580e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding);
581e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* The skb contains the Wireless Header + payload data now */
582e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */  + FCS_LEN))) {
583e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (2)\n");
584e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
585e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
586e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	wlhdr = (struct ieee80211_hdr *)(skb->data);
587f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	fctl = wlhdr->frame_control;
588e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
589e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DEC) {
590e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int keyidx;
591e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
592e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
593e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = ((macstat & B43_RX_MAC_KEYIDX)
594e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			  >> B43_RX_MAC_KEYIDX_SHIFT);
595e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* We must adjust the key index here. We want the "physical"
596e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * key index, but the ucode passed it slightly different.
597e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 */
598e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = b43_kidx_to_raw(dev, keyidx);
59966d2d089c394c7e31020947d682523f77a93244bMichael Buesch		B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
600e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
601e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
602f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison			wlhdr_len = ieee80211_hdrlen(fctl);
603e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (unlikely(skb->len < (wlhdr_len + 3))) {
604e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				b43dbg(dev->wl,
605e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				       "RX: Packet size underrun (3)\n");
606e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				goto drop;
607e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
608e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			status.flag |= RX_FLAG_DECRYPTED;
609e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
610e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
611e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
6127b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	/* Link quality statistics */
613e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.noise = dev->stats.link_noise;
6147b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
6157b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch//		s8 rssi = max(rxhdr->power0, rxhdr->power1);
6167b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//TODO: Find out what the rssi value is (dBm or percentage?)
6177b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//      and also find out what the maximum possible value is.
6187b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//      Fill status.ssi and status.signal fields.
6197b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	} else {
620566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf		status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
6217b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat0 & B43_RX_PHYST0_OFDM),
6227b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat0 & B43_RX_PHYST0_GAINCTL),
6237b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat3 & B43_RX_PHYST3_TRSTATE));
624566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf		status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
6257b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	}
6267b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch
627e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phystat0 & B43_RX_PHYST0_OFDM)
6288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
6298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg						phytype == B43_PHYTYPE_A);
630e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
6318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
632ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (unlikely(status.rate_idx == -1)) {
633ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		/* PLCP seems to be corrupted.
634ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		 * Drop the frame, if we are not interested in corrupted frames. */
635ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		if (!(dev->wl->filter_flags & FIF_PLCPFAIL))
636ce4fbdbf161b2676b3833412367113572d739253Michael Buesch			goto drop;
637ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	}
638e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
639c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
640c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	/*
641d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * All frames on monitor interfaces and beacons always need a full
642d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
643d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * purposes and beacons for IBSS merging.
644d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * This code assumes we get to process the packet within 16 bits
645d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * of timestamp, i.e. about 65 milliseconds after the PHY received
646d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * the first symbol.
647c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	 */
648f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
649c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		u16 low_mactime_now;
650c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
651c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		b43_tsf_read(dev, &status.mactime);
652c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		low_mactime_now = status.mactime;
653c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime = status.mactime & ~0xFFFFULL;
654c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime += mactime;
655c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		if (low_mactime_now <= mactime)
656c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville			status.mactime -= 0x10000;
657c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.flag |= RX_FLAG_TSFT;
658c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	}
659e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
660e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
661e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
662e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_A:
6638318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_5GHZ;
664d987160b710c98997015832422a05e18d9f0f925Michael Buesch		B43_WARN_ON(1);
665d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* FIXME: We don't really know which value the "chanid" contains.
666d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 *        So the following assignment might be wrong. */
6678318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.freq = b43_channel_to_freq_5ghz(chanid);
668e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
669e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_G:
6708318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_2GHZ;
671d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the radio channel cookie value as used
672d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * to tune the radio. */
673e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		status.freq = chanid + 2400;
674d987160b710c98997015832422a05e18d9f0f925Michael Buesch		break;
675d987160b710c98997015832422a05e18d9f0f925Michael Buesch	case B43_PHYTYPE_N:
676826ee70664c658a022d999f7eb4d3cd9448895ddGábor Stefanik	case B43_PHYTYPE_LP:
677d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the SHM channel cookie. Which is the plain
678d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * channel number in b43. */
6798318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		if (chanstat & B43_RX_CHAN_5GHZ) {
6808318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_5GHZ;
6818318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.freq = b43_freq_to_channel_5ghz(chanid);
6828318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		} else {
6838318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_2GHZ;
6848318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.freq = b43_freq_to_channel_2ghz(chanid);
6858318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		}
686e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
687e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
688e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
689d987160b710c98997015832422a05e18d9f0f925Michael Buesch		goto drop;
690e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
691e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
692f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
69372f5f457564e8ebc6c38ee4f98ee59cd03c2f614John W. Linville	ieee80211_rx_ni(dev->wl->hw, skb);
694e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
695990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch#if B43_DEBUG
696990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch	dev->rx_count++;
697990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch#endif
698e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return;
699e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop:
700e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43dbg(dev->wl, "RX: Packet dropped\n");
701e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	dev_kfree_skb_any(skb);
702e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
703e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
704e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev,
705e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			 const struct b43_txstatus *status)
706e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
707e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_debugfs_log_txstat(dev, status);
708e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
709e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->intermediate)
710e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
711e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->for_ampdu)
712e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
713e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (!status->acked)
714e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11ACKFailureCount++;
715e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->rts_count) {
716e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (status->rts_count == 0xF)	//FIXME
717e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSFailureCount++;
718e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
719e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSSuccessCount++;
720e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
721e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
7225100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
7235100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_handle_txstatus(dev, status);
7245100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
7255100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_handle_txstatus(dev, status);
72618c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch
72718c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch	b43_phy_txpower_check(dev, 0);
728e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
729e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
7305100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch/* Fill out the mac80211 TXstatus report based on the b43-specific
7315100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * txstatus report data. This returns a boolean whether the frame was
7325100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * successfully transmitted. */
733e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Bergbool b43_fill_txstatus_report(struct b43_wldev *dev,
734e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			      struct ieee80211_tx_info *report,
7355100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			      const struct b43_txstatus *status)
736e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
7375100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	bool frame_success = 1;
738e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	int retry_limit;
739e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
740e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	/* preserve the confiured retry limit before clearing the status
741e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * The xmit function has overwritten the rc's value with the actual
742e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * retry limit done by the hardware */
743e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	retry_limit = report->status.rates[0].count;
744e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	ieee80211_tx_info_clear_status(report);
7455100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch
7465100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (status->acked) {
7475100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was ACKed. */
748e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		report->flags |= IEEE80211_TX_STAT_ACK;
7495100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	} else {
7505100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was not ACKed... */
751e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
7525100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			/* ...but we expected an ACK. */
7535100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			frame_success = 0;
7545100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		}
7555100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	}
7565100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (status->frame_count == 0) {
7575100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was not transmitted at all. */
758e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[0].count = 0;
759e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
760e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		/*
761e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * If the short retries (RTS, not data frame) have exceeded
762e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * the limit, the hw will not have tried the selected rate,
763e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * but will have used the fallback rate instead.
764e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * Don't let the rate control count attempts for the selected
765e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * rate in this case, otherwise the statistics will be off.
766e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 */
767e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[0].count = 0;
768e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[1].count = status->frame_count;
769e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else {
770e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		if (status->frame_count > retry_limit) {
771e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[0].count = retry_limit;
772e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[1].count = status->frame_count -
773e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg					retry_limit;
774e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
775e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		} else {
776e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[0].count = status->frame_count;
777e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[1].idx = -1;
778e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		}
779e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	}
7805100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch
7815100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	return frame_success;
782e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
783e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
784e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */
785e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev)
786e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
7875100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
7885100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_tx_suspend(dev);
7895100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
7905100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_tx_suspend(dev);
791e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
792e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
793e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */
794e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev)
795e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
7965100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
7975100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_tx_resume(dev);
7985100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
7995100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_tx_resume(dev);
800e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
801