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>
9eb032b9837a958e21ca000358a5bde5e17192ddbMichael Buesch  Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
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
353311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłeckistatic const struct b43_tx_legacy_rate_phy_ctl_entry b43_tx_legacy_rate_phy_ctl[] = {
363311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_CCK_RATE_1MB,	0x0,			0x0 },
373311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_CCK_RATE_2MB,	0x0,			0x1 },
383311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_CCK_RATE_5MB,	0x0,			0x2 },
393311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_CCK_RATE_11MB,	0x0,			0x3 },
403311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_OFDM_RATE_6MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_BPSK },
413311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_OFDM_RATE_9MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_BPSK },
423311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_OFDM_RATE_12MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_QPSK },
433311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_OFDM_RATE_18MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QPSK },
443311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_OFDM_RATE_24MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_QAM16 },
453311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_OFDM_RATE_36MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QAM16 },
463311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_OFDM_RATE_48MB,	B43_TXH_PHY1_CRATE_2_3,	B43_TXH_PHY1_MODUL_QAM64 },
473311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	{ B43_OFDM_RATE_54MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QAM64 },
483311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki};
493311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
503311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłeckistatic const struct b43_tx_legacy_rate_phy_ctl_entry *
513311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłeckib43_tx_legacy_rate_phy_ctl_ent(u8 bitrate)
523311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki{
533311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
543311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	unsigned int i;
553311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
563311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	for (i = 0; i < ARRAY_SIZE(b43_tx_legacy_rate_phy_ctl); i++) {
573311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		e = &(b43_tx_legacy_rate_phy_ctl[i]);
583311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		if (e->bitrate == bitrate)
593311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			return e;
603311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	}
613311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
623311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	B43_WARN_ON(1);
633311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	return NULL;
643311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki}
65e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
668318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of a CCK PLCP header. */
678318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
68e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
69e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (plcp->raw[0]) {
70e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x0A:
718318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 0;
72e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x14:
738318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 1;
74e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x37:
758318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 2;
76e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x6E:
778318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 3;
78e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
798318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
80e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
81e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
828318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of an OFDM PLCP header. */
83c0624881187cd06fbcbdc177c507ab589b1b6f1eRafał Miłeckistatic int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5)
84e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
85c0624881187cd06fbcbdc177c507ab589b1b6f1eRafał Miłecki	/* For 2 GHz band first OFDM rate is at index 4, see main.c */
86c0624881187cd06fbcbdc177c507ab589b1b6f1eRafał Miłecki	int base = ghz5 ? 0 : 4;
878318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
88e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (plcp->raw[0] & 0xF) {
89e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xB:
908318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 0;
91e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xF:
928318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 1;
93e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xA:
948318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 2;
95e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xE:
968318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 3;
97e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x9:
988318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 4;
99e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xD:
1008318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 5;
101e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x8:
1028318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 6;
103e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xC:
1048318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 7;
105e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
1068318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
107e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
108e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
109e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_cck(const u8 bitrate)
110e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
111e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
112e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
113e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x0A;
114e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
115e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x14;
116e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
117e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x37;
118e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
119e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x6E;
120e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
121e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
122e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
123e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
124e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
125e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
126e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
127e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
128e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
129e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xB;
130e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
131e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xF;
132e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
133e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xA;
134e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
135e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xE;
136e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
137e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x9;
138e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
139e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xD;
140e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
141e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x8;
142e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
143e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xC;
144e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
145e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
146e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
147e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
148e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
149e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
150e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			   const u16 octets, const u8 bitrate)
151e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
152e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	__u8 *raw = plcp->raw;
153e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
154e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (b43_is_ofdm_rate(bitrate)) {
1551a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		u32 d;
1561a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch
1571a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d = b43_plcp_get_ratecode_ofdm(bitrate);
158e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(octets & 0xF000);
1591a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d |= (octets << 5);
160b52a033c2c501a8015df3727a4bd73389ccb1641Matthieu CASTET		plcp->data = cpu_to_le32(d);
161e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
162e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		u32 plen;
163e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
164e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		plen = octets * 16 / bitrate;
165e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if ((octets * 16 % bitrate) > 0) {
166e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			plen++;
167e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if ((bitrate == B43_CCK_RATE_11MB)
168e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    && ((octets * 8 % 11) < 4)) {
169e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x84;
170e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else
171e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x04;
172e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else
173e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			raw[1] = 0x04;
174b52a033c2c501a8015df3727a4bd73389ccb1641Matthieu CASTET		plcp->data |= cpu_to_le32(plen << 16);
175e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		raw[0] = b43_plcp_get_ratecode_cck(bitrate);
176e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
177e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
178e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
179694718d8ad2f0b11d7376f8aa32b1befff6e5966Rafał Miłecki/* TODO: verify if needed for SSLPN or LCN  */
1803311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłeckistatic u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
1813311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki{
1823311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	const struct b43_phy *phy = &dev->phy;
1833311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
1843311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	u16 control = 0;
1853311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	u16 bw;
1863311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
1873311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	if (phy->type == B43_PHYTYPE_LP)
1883311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		bw = B43_TXH_PHY1_BW_20;
1893311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	else /* FIXME */
1903311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		bw = B43_TXH_PHY1_BW_20;
1913311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
1923311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	if (0) { /* FIXME: MIMO */
1933311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	} else if (b43_is_cck_rate(bitrate) && phy->type != B43_PHYTYPE_LP) {
1943311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		control = bw;
1953311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	} else {
1963311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		control = bw;
1973311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		e = b43_tx_legacy_rate_phy_ctl_ent(bitrate);
1983311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		if (e) {
1993311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			control |= e->coding_rate;
2003311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			control |= e->modulation;
2013311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		}
2023311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		control |= B43_TXH_PHY1_MODE_SISO;
2033311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	}
2043311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
2053311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	return control;
2063311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki}
2073311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
208e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_calc_fallback_rate(u8 bitrate)
209e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
210e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
211e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
212e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
213e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
214e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
215e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
216e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_2MB;
217e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
218e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
219e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
220e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
221e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
222e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_6MB;
223e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
224e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_9MB;
225e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
226e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_12MB;
227e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
228e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_18MB;
229e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
230e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_24MB;
231e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
232e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_36MB;
233e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
234e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_48MB;
235e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
236e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
237e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
238e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
239e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
240eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch/* Generate a TX data header. */
24109552ccd8277e6382097e93a40f7311a09449367Michael Bueschint b43_generate_txhdr(struct b43_wldev *dev,
24209552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u8 *_txhdr,
243035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		       struct sk_buff *skb_frag,
244e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		       struct ieee80211_tx_info *info,
24509552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u16 cookie)
246e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
247035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski	const unsigned char *fragment_data = skb_frag->data;
248035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski	unsigned int fragment_len = skb_frag->len;
249eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
250e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_phy *phy = &dev->phy;
251e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct ieee80211_hdr *wlhdr =
252e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (const struct ieee80211_hdr *)fragment_data;
253d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg	int use_encryption = !!info->control.hw_key;
254f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	__le16 fctl = wlhdr->frame_control;
2558318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	struct ieee80211_rate *fbrate;
256e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 rate, rate_fb;
257e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int rate_ofdm, rate_fb_ofdm;
258e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	unsigned int plcp_fragment_len;
259e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 mac_ctl = 0;
260e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phy_ctl = 0;
261694718d8ad2f0b11d7376f8aa32b1befff6e5966Rafał Miłecki	bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP ||
262694718d8ad2f0b11d7376f8aa32b1befff6e5966Rafał Miłecki			      phy->type == B43_PHYTYPE_N ||
263694718d8ad2f0b11d7376f8aa32b1befff6e5966Rafał Miłecki			      phy->type == B43_PHYTYPE_HT);
264e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 extra_ft = 0;
2652e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	struct ieee80211_rate *txrate;
266e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	struct ieee80211_tx_rate *rates;
267e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
268e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(txhdr, 0, sizeof(*txhdr));
269e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
270e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
2712e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
272e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_ofdm = b43_is_ofdm_rate(rate);
273870abdf67170daa9f1022e55a35c469239fcc74cFelix Fietkau	fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate;
2748318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	rate_fb = fbrate->hw_value;
275e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
276e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
277e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
278e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate);
279e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
280e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
281e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_frame_ctl = wlhdr->frame_control;
282d458cdf712e0c671e8e819abb16ecd6e44f9daecJoe Perches	memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN);
283e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
284e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Calculate duration for fallback rate */
285e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if ((rate_fb == rate) ||
286e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
287e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id == cpu_to_le16(0))) {
288e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* If the fallback rate equals the normal rate or the
289e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * dur_id field contains an AID, CFP magic or 0,
290e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * use the original dur_id field. */
291e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->dur_fb = wlhdr->duration_id;
292e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
293e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		txhdr->dur_fb = ieee80211_generic_frame_duration(
2944ee73f338a528f44fd90496adfbfd9c119401850Michal Kazior			dev->wl->hw, info->control.vif, info->band,
2954ee73f338a528f44fd90496adfbfd9c119401850Michal Kazior			fragment_len, fbrate);
296e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
297e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
298e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp_fragment_len = fragment_len + FCS_LEN;
299e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (use_encryption) {
300e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		u8 key_idx = info->control.hw_key->hw_key_idx;
301e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		struct b43_key *key;
302e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
303e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		size_t iv_len;
304e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
30566d2d089c394c7e31020947d682523f77a93244bMichael Buesch		B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key));
306e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		key = &(dev->key[key_idx]);
3077be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch
30809552ccd8277e6382097e93a40f7311a09449367Michael Buesch		if (unlikely(!key->keyconf)) {
30909552ccd8277e6382097e93a40f7311a09449367Michael Buesch			/* This key is invalid. This might only happen
31009552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * in a short timeframe after machine resume before
31109552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * we were able to reconfigure keys.
31209552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * Drop this packet completely. Do not transmit it
31309552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * unencrypted to avoid leaking information. */
31409552ccd8277e6382097e93a40f7311a09449367Michael Buesch			return -ENOKEY;
3157be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch		}
31609552ccd8277e6382097e93a40f7311a09449367Michael Buesch
31709552ccd8277e6382097e93a40f7311a09449367Michael Buesch		/* Hardware appends ICV. */
31876708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		plcp_fragment_len += info->control.hw_key->icv_len;
31909552ccd8277e6382097e93a40f7311a09449367Michael Buesch
32009552ccd8277e6382097e93a40f7311a09449367Michael Buesch		key_idx = b43_kidx_to_fw(dev, key_idx);
32109552ccd8277e6382097e93a40f7311a09449367Michael Buesch		mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
32209552ccd8277e6382097e93a40f7311a09449367Michael Buesch			   B43_TXH_MAC_KEYIDX;
32309552ccd8277e6382097e93a40f7311a09449367Michael Buesch		mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
32409552ccd8277e6382097e93a40f7311a09449367Michael Buesch			   B43_TXH_MAC_KEYALG;
325f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison		wlhdr_len = ieee80211_hdrlen(fctl);
326035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		if (key->algorithm == B43_SEC_ALGO_TKIP) {
327035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			u16 phase1key[5];
328035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			int i;
329035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			/* we give the phase1key and iv16 here, the key is stored in
330035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			 * shm. With that the hardware can do phase 2 and encryption.
331035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			 */
332523b02ea23b175dd3e46e3daf1bc9354376640a3Johannes Berg			ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);
333cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			/* phase1key is in host endian. Copy to little-endian txhdr->iv. */
334cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			for (i = 0; i < 5; i++) {
335cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch				txhdr->iv[i * 2 + 0] = phase1key[i];
336cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch				txhdr->iv[i * 2 + 1] = phase1key[i] >> 8;
337cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			}
338035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			/* iv16 */
339035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
340035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		} else {
341c8e4955653a470ece7bf580c84fc88eb58cc9850Silvan Jegen			iv_len = min_t(size_t, info->control.hw_key->iv_len,
342035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski				     ARRAY_SIZE(txhdr->iv));
343035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
344035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		}
345e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
346efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki	switch (dev->fw.hdr_format) {
3475d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki	case B43_FW_HDR_598:
3485d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp),
3495d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki				      plcp_fragment_len, rate);
3505d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki		break;
351efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki	case B43_FW_HDR_351:
3522391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp),
353eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      plcp_fragment_len, rate);
354efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		break;
355efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki	case B43_FW_HDR_410:
3562391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp),
357eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      plcp_fragment_len, rate);
358efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		break;
359eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	}
360e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
361e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			      plcp_fragment_len, rate_fb);
362e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
363e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Extra Frame Types */
364e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_fb_ofdm)
365eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		extra_ft |= B43_TXH_EFT_FB_OFDM;
366eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
367eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		extra_ft |= B43_TXH_EFT_FB_CCK;
368e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
369e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Set channel radio code. Note that the micrcode ORs 0x100 to
370e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * this value before comparing it to the value in SHM, if this
371e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * is a 5Ghz packet.
372e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 */
373e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->chan_radio_code = phy->channel;
374e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
375e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* PHY TX Control word */
376e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
377eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ENC_OFDM;
378eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
379eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ENC_CCK;
380e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
381eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
3829db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch
383d748b4642a53cd1ead303f9e2b008295391466b7Johannes Berg	switch (b43_ieee80211_antenna_sanitize(dev, 0)) {
3849db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 0: /* Default */
385eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT01AUTO;
386e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
3879db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 1: /* Antenna 0 */
388eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT0;
389e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
3909db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 2: /* Antenna 1 */
391eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT1;
392eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		break;
393eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	case 3: /* Antenna 2 */
394eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT2;
395eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		break;
396eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	case 4: /* Antenna 3 */
397eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT3;
398e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
399e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
400e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
401e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
402e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
403e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	rates = info->control.rates;
404e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* MAC control */
405e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
406eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_ACK;
407f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg	/* use hardware sequence counter as the non-TID counter */
408f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
409eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_HWSEQ;
410e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
411eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_STMSDU;
41224acfc632b7ba55bbc2a9305e8df31c8e41178b6Rafał Miłecki	if (!phy->gmode)
413eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_5GHZ;
414e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
415e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	/* Overwrite rates[0].count to make the retry calculation
416e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * in the tx status easier. need the actual retry limit to
417e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * detect whether the fallback rate was used.
418e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 */
419e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
420e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	    (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
421e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
422eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_LONGFRAME;
423e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else {
424e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
425e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	}
426e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
427e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Generate the RTS or CTS-to-self frame */
428e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
429e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
430e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int len;
431efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		struct ieee80211_hdr *uninitialized_var(hdr);
432e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate, rts_rate_fb;
433e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate_ofdm, rts_rate_fb_ofdm;
434efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		struct b43_plcp_hdr6 *uninitialized_var(plcp);
4352e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg		struct ieee80211_rate *rts_cts_rate;
436e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
437e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
4382e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg
4392e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg		rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
440e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
441e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb = b43_calc_fallback_rate(rts_rate);
442e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
443e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
444e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
445efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			struct ieee80211_cts *uninitialized_var(cts);
446eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
447efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			switch (dev->fw.hdr_format) {
4485d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki			case B43_FW_HDR_598:
4495d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki				cts = (struct ieee80211_cts *)
4505d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki					(txhdr->format_598.rts_frame);
4515d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki				break;
452efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			case B43_FW_HDR_351:
453eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
4542391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki					(txhdr->format_351.rts_frame);
455efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki				break;
456efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			case B43_FW_HDR_410:
457eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
4582391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki					(txhdr->format_410.rts_frame);
459efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki				break;
460eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
461e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch						fragment_data, fragment_len,
463e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg						info, cts);
464eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDCTS;
465e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_cts);
466e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
467efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			struct ieee80211_rts *uninitialized_var(rts);
468eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
469efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			switch (dev->fw.hdr_format) {
4705d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki			case B43_FW_HDR_598:
4715d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki				rts = (struct ieee80211_rts *)
4725d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki					(txhdr->format_598.rts_frame);
4735d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki				break;
474efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			case B43_FW_HDR_351:
475eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
4762391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki					(txhdr->format_351.rts_frame);
477efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki				break;
478efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			case B43_FW_HDR_410:
479eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
4802391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki					(txhdr->format_410.rts_frame);
481efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki				break;
482eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
483e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_rts_get(dev->wl->hw, info->control.vif,
484eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					  fragment_data, fragment_len,
485e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg					  info, rts);
486eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDRTS;
487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_rts);
488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
489e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		len += FCS_LEN;
490eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
491eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		/* Generate the PLCP headers for the RTS/CTS frame */
492efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		switch (dev->fw.hdr_format) {
4935d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki		case B43_FW_HDR_598:
4945d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki			plcp = &txhdr->format_598.rts_plcp;
4955d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki			break;
496efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		case B43_FW_HDR_351:
4972391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki			plcp = &txhdr->format_351.rts_plcp;
498efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			break;
499efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		case B43_FW_HDR_410:
5002391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki			plcp = &txhdr->format_410.rts_plcp;
501efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			break;
502efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		}
503eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
504eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      len, rts_rate);
505eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		plcp = &txhdr->rts_plcp_fb;
506eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
507e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				      len, rts_rate_fb);
508eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
509efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		switch (dev->fw.hdr_format) {
5105d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki		case B43_FW_HDR_598:
5115d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki			hdr = (struct ieee80211_hdr *)
5125d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki				(&txhdr->format_598.rts_frame);
5135d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki			break;
514efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		case B43_FW_HDR_351:
515eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
5162391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki				(&txhdr->format_351.rts_frame);
517efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			break;
518efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		case B43_FW_HDR_410:
519eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
5202391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki				(&txhdr->format_410.rts_frame);
521efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki			break;
522eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
523e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->rts_dur_fb = hdr->duration_id;
524eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
525e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_ofdm) {
526eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_OFDM;
527e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
528e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_ofdm(rts_rate);
529eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
530eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_CCK;
531e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
532e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_cck(rts_rate);
533eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
534e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_fb_ofdm)
535eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
536eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
537eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_CCK;
5383311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
5393311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
540694718d8ad2f0b11d7376f8aa32b1befff6e5966Rafał Miłecki		    fill_phy_ctl1) {
5413311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			txhdr->phy_ctl1_rts = cpu_to_le16(
5423311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki				b43_generate_tx_phy_ctl1(dev, rts_rate));
5433311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			txhdr->phy_ctl1_rts_fb = cpu_to_le16(
5443311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki				b43_generate_tx_phy_ctl1(dev, rts_rate_fb));
5453311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		}
546e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
547e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
548e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Magic cookie */
549efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki	switch (dev->fw.hdr_format) {
5505d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki	case B43_FW_HDR_598:
5515d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki		txhdr->format_598.cookie = cpu_to_le16(cookie);
5525d852905561a979dfb4d8a68f7313dcb8f055becRafał Miłecki		break;
553efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki	case B43_FW_HDR_351:
5542391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki		txhdr->format_351.cookie = cpu_to_le16(cookie);
555efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		break;
556efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki	case B43_FW_HDR_410:
5572391b7e8d40e4b3be0756396c628d2323f2d0b8dRafał Miłecki		txhdr->format_410.cookie = cpu_to_le16(cookie);
558efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki		break;
559efe0249b0fd1e9a32a7e6a5dc9c751d4d97b0adfRafał Miłecki	}
560e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
561694718d8ad2f0b11d7376f8aa32b1befff6e5966Rafał Miłecki	if (fill_phy_ctl1) {
5623311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		txhdr->phy_ctl1 =
5633311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
5643311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		txhdr->phy_ctl1_fb =
5653311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate_fb));
5663311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	}
5673311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
568e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Apply the bitfields */
569e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
570e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
571e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->extra_ft = extra_ft;
572e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
57309552ccd8277e6382097e93a40f7311a09449367Michael Buesch	return 0;
574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
576e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev,
577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       u8 in_rssi, int ofdm,
578e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       int adjust_2053, int adjust_2050)
579e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
580e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
581ef1a628d83fc0423c36e773281162be790503168Michael Buesch	struct b43_phy_g *gphy = phy->g;
582e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s32 tmp;
583e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
584e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (phy->radio_ver) {
585e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2050:
586e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (ofdm) {
587e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
588e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (tmp > 127)
589e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 256;
590e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp *= 73;
591e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp /= 64;
592e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (adjust_2050)
593e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
594e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			else
595e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 3;
596e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
5970581483afe1a6f90f828b36111b05a70c162137dRafał Miłecki			if (dev->dev->bus_sprom->
598e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    boardflags_lo & B43_BFL_RSSI) {
599e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				if (in_rssi > 63)
600e4d6b7951812d98417feb10784e400e253caf633Michael Buesch					in_rssi = 63;
601ef1a628d83fc0423c36e773281162be790503168Michael Buesch				B43_WARN_ON(phy->type != B43_PHYTYPE_G);
602ef1a628d83fc0423c36e773281162be790503168Michael Buesch				tmp = gphy->nrssi_lt[in_rssi];
603e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
604e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -131;
605e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
606e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 57;
607e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else {
608e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = in_rssi;
609e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
610e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -149;
611e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
612e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 68;
613e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
614e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (phy->type == B43_PHYTYPE_G && adjust_2050)
615e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
616e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
617e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
618e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2060:
619e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (in_rssi > 127)
620e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi - 256;
621e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
622e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
623e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
624e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
625e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp = in_rssi;
626e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp -= 11;
627e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp *= 103;
628e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp /= 64;
629e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (adjust_2053)
630e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 109;
631e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
632e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 83;
633e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
634e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
635e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return (s8) tmp;
636e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
637e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
638e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO
639e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0
640e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi)
641e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
642e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
643e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s8 ret;
644e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
645e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A) {
646e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		//TODO: Incomplete specs.
647e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = 0;
648e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else
649e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1);
650e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
651e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return ret;
652e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
653e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif
654e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
655e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
656e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
657e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_rx_status status;
658e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_plcp_hdr6 *plcp;
659e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_hdr *wlhdr;
660e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
661f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	__le16 fctl;
66217030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki	u16 phystat0, phystat3;
66317030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki	u16 uninitialized_var(chanstat), uninitialized_var(mactime);
66417030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki	u32 uninitialized_var(macstat);
665e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 chanid;
6668318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	u16 phytype;
6671924b4e294df4e97ad22557700e554af409569bcJohannes Berg	int padding, rate_idx;
668e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
669e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(&status, 0, sizeof(status));
670e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
671e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Get metadata about the frame from the header. */
672e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	phystat0 = le16_to_cpu(rxhdr->phy_status0);
673e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	phystat3 = le16_to_cpu(rxhdr->phy_status3);
67417030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki	switch (dev->fw.hdr_format) {
67517030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki	case B43_FW_HDR_598:
67617030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki		macstat = le32_to_cpu(rxhdr->format_598.mac_status);
67717030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki		mactime = le16_to_cpu(rxhdr->format_598.mac_time);
67817030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki		chanstat = le16_to_cpu(rxhdr->format_598.channel);
67917030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki		break;
68017030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki	case B43_FW_HDR_410:
68117030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki	case B43_FW_HDR_351:
68217030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki		macstat = le32_to_cpu(rxhdr->format_351.mac_status);
68317030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki		mactime = le16_to_cpu(rxhdr->format_351.mac_time);
68417030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki		chanstat = le16_to_cpu(rxhdr->format_351.channel);
68517030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki		break;
68617030f48e31adde5b043741c91ba143f5f7db0fdRafał Miłecki	}
6878318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	phytype = chanstat & B43_RX_CHAN_PHYTYPE;
688e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
689ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
690e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11FCSErrorCount++;
691ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_FAILED_FCS_CRC;
692ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	}
693ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV)))
694ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_FAILED_PLCP_CRC;
695ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (phystat0 & B43_RX_PHYST0_SHORTPRMBL)
696ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_SHORTPRE;
697e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DECERR) {
698e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* Decryption with the given key failed.
699e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * Drop the packet. We also won't be able to decrypt it with
700e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * the key in software. */
701e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
702e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
703e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
704e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Skip PLCP and padding */
705e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
706e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) {
707e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (1)\n");
708e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
709e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
710e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp = (struct b43_plcp_hdr6 *)(skb->data + padding);
711e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding);
712e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* The skb contains the Wireless Header + payload data now */
713e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */  + FCS_LEN))) {
714e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (2)\n");
715e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
716e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
717e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	wlhdr = (struct ieee80211_hdr *)(skb->data);
718f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	fctl = wlhdr->frame_control;
719e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
720e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DEC) {
721e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int keyidx;
722e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
723e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
724e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = ((macstat & B43_RX_MAC_KEYIDX)
725e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			  >> B43_RX_MAC_KEYIDX_SHIFT);
726e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* We must adjust the key index here. We want the "physical"
727e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * key index, but the ucode passed it slightly different.
728e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 */
729e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = b43_kidx_to_raw(dev, keyidx);
73066d2d089c394c7e31020947d682523f77a93244bMichael Buesch		B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
731e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
732e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
733f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison			wlhdr_len = ieee80211_hdrlen(fctl);
734e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (unlikely(skb->len < (wlhdr_len + 3))) {
735e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				b43dbg(dev->wl,
736e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				       "RX: Packet size underrun (3)\n");
737e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				goto drop;
738e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
739e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			status.flag |= RX_FLAG_DECRYPTED;
740e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
741e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
742e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
7437b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	/* Link quality statistics */
744207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
74573d51f38c736ae286372e90056a7f31519f555acRafał Miłecki	case B43_PHYTYPE_HT:
74673d51f38c736ae286372e90056a7f31519f555acRafał Miłecki		/* TODO: is max the right choice? */
74773d51f38c736ae286372e90056a7f31519f555acRafał Miłecki		status.signal = max_t(__s8,
74873d51f38c736ae286372e90056a7f31519f555acRafał Miłecki			max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1),
74973d51f38c736ae286372e90056a7f31519f555acRafał Miłecki			rxhdr->phy_ht_power2);
75073d51f38c736ae286372e90056a7f31519f555acRafał Miłecki		break;
751207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki	case B43_PHYTYPE_N:
75273d51f38c736ae286372e90056a7f31519f555acRafał Miłecki		/* Broadcom has code for min and avg, but always uses max */
753207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki		if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
754207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki			status.signal = max(rxhdr->power1, rxhdr->power2);
755207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki		else
756207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki			status.signal = max(rxhdr->power0, rxhdr->power1);
757207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki		break;
758207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki	case B43_PHYTYPE_A:
759207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki	case B43_PHYTYPE_B:
760207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki	case B43_PHYTYPE_G:
761207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki	case B43_PHYTYPE_LP:
762566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf		status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
7637b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat0 & B43_RX_PHYST0_OFDM),
7647b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat0 & B43_RX_PHYST0_GAINCTL),
7657b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat3 & B43_RX_PHYST3_TRSTATE));
766207ae4a3733686df2aabd2dd6feefbde4e69cdd5Rafał Miłecki		break;
7677b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	}
7687b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch
769e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phystat0 & B43_RX_PHYST0_OFDM)
7701924b4e294df4e97ad22557700e554af409569bcJohannes Berg		rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
771c0624881187cd06fbcbdc177c507ab589b1b6f1eRafał Miłecki					!!(chanstat & B43_RX_CHAN_5GHZ));
772e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
7731924b4e294df4e97ad22557700e554af409569bcJohannes Berg		rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
7741924b4e294df4e97ad22557700e554af409569bcJohannes Berg	if (unlikely(rate_idx == -1)) {
775ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		/* PLCP seems to be corrupted.
776ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		 * Drop the frame, if we are not interested in corrupted frames. */
777ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		if (!(dev->wl->filter_flags & FIF_PLCPFAIL))
778ce4fbdbf161b2676b3833412367113572d739253Michael Buesch			goto drop;
779ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	}
7801924b4e294df4e97ad22557700e554af409569bcJohannes Berg	status.rate_idx = rate_idx;
781e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
782c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
783c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	/*
784d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * All frames on monitor interfaces and beacons always need a full
785d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
786d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * purposes and beacons for IBSS merging.
787d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * This code assumes we get to process the packet within 16 bits
788d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * of timestamp, i.e. about 65 milliseconds after the PHY received
789d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * the first symbol.
790c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	 */
791f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
792c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		u16 low_mactime_now;
793c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
794c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		b43_tsf_read(dev, &status.mactime);
795c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		low_mactime_now = status.mactime;
796c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime = status.mactime & ~0xFFFFULL;
797c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime += mactime;
798c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		if (low_mactime_now <= mactime)
799c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville			status.mactime -= 0x10000;
800f4bda337bbb6e245e2a07f344990adeb6a70ff35Thomas Pedersen		status.flag |= RX_FLAG_MACTIME_START;
801c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	}
802e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
803e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
804e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
805e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_A:
8068318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_5GHZ;
807d987160b710c98997015832422a05e18d9f0f925Michael Buesch		B43_WARN_ON(1);
808d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* FIXME: We don't really know which value the "chanid" contains.
809d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 *        So the following assignment might be wrong. */
810bb6bd25c08738ace7102a550a15481e70bc31ee8ZHAO Gang		status.freq =
811bb6bd25c08738ace7102a550a15481e70bc31ee8ZHAO Gang			ieee80211_channel_to_frequency(chanid, status.band);
812e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
813e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_G:
8148318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_2GHZ;
8152fc68eb122c7ea6cd5be1fe7d6650c0beb2f4f40Rafał Miłecki		/* Somewhere between 478.104 and 508.1084 firmware for G-PHY
8162fc68eb122c7ea6cd5be1fe7d6650c0beb2f4f40Rafał Miłecki		 * has been modified to be compatible with N-PHY and others.
8172fc68eb122c7ea6cd5be1fe7d6650c0beb2f4f40Rafał Miłecki		 */
8182fc68eb122c7ea6cd5be1fe7d6650c0beb2f4f40Rafał Miłecki		if (dev->fw.rev >= 508)
8192fc68eb122c7ea6cd5be1fe7d6650c0beb2f4f40Rafał Miłecki			status.freq = ieee80211_channel_to_frequency(chanid, status.band);
8202fc68eb122c7ea6cd5be1fe7d6650c0beb2f4f40Rafał Miłecki		else
8212fc68eb122c7ea6cd5be1fe7d6650c0beb2f4f40Rafał Miłecki			status.freq = chanid + 2400;
822d987160b710c98997015832422a05e18d9f0f925Michael Buesch		break;
823d987160b710c98997015832422a05e18d9f0f925Michael Buesch	case B43_PHYTYPE_N:
824826ee70664c658a022d999f7eb4d3cd9448895ddGábor Stefanik	case B43_PHYTYPE_LP:
8256a461c23e7051d090751a2030e5febf6356c8d57Rafał Miłecki	case B43_PHYTYPE_HT:
826d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the SHM channel cookie. Which is the plain
827d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * channel number in b43. */
828bb6bd25c08738ace7102a550a15481e70bc31ee8ZHAO Gang		if (chanstat & B43_RX_CHAN_5GHZ)
8298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_5GHZ;
830bb6bd25c08738ace7102a550a15481e70bc31ee8ZHAO Gang		else
8318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_2GHZ;
832bb6bd25c08738ace7102a550a15481e70bc31ee8ZHAO Gang		status.freq =
833bb6bd25c08738ace7102a550a15481e70bc31ee8ZHAO Gang			ieee80211_channel_to_frequency(chanid, status.band);
834e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
835e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
836e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
837d987160b710c98997015832422a05e18d9f0f925Michael Buesch		goto drop;
838e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
839e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
840f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
84172f5f457564e8ebc6c38ee4f98ee59cd03c2f614John W. Linville	ieee80211_rx_ni(dev->wl->hw, skb);
842e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
843990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch#if B43_DEBUG
844990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch	dev->rx_count++;
845990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch#endif
846e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return;
847e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop:
848e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	dev_kfree_skb_any(skb);
849e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
850e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
851e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev,
852e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			 const struct b43_txstatus *status)
853e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
854e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_debugfs_log_txstat(dev, status);
855e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
856e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->intermediate)
857e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
858e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->for_ampdu)
859e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
860e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (!status->acked)
861e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11ACKFailureCount++;
862e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->rts_count) {
863e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (status->rts_count == 0xF)	//FIXME
864e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSFailureCount++;
865e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
866e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSSuccessCount++;
867e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
868e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
8695100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
8705100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_handle_txstatus(dev, status);
8715100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
8725100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_handle_txstatus(dev, status);
87318c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch
87418c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch	b43_phy_txpower_check(dev, 0);
875e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
876e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
8775100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch/* Fill out the mac80211 TXstatus report based on the b43-specific
8785100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * txstatus report data. This returns a boolean whether the frame was
8795100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * successfully transmitted. */
880e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Bergbool b43_fill_txstatus_report(struct b43_wldev *dev,
881e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			      struct ieee80211_tx_info *report,
8825100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			      const struct b43_txstatus *status)
883e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
8843db1cd5c05f35fb43eb134df6f321de4e63141f2Rusty Russell	bool frame_success = true;
885e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	int retry_limit;
886e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
887e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	/* preserve the confiured retry limit before clearing the status
888e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * The xmit function has overwritten the rc's value with the actual
889e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * retry limit done by the hardware */
890e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	retry_limit = report->status.rates[0].count;
891e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	ieee80211_tx_info_clear_status(report);
8925100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch
8935100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (status->acked) {
8945100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was ACKed. */
895e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		report->flags |= IEEE80211_TX_STAT_ACK;
8965100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	} else {
8975100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was not ACKed... */
898e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
8995100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			/* ...but we expected an ACK. */
9003db1cd5c05f35fb43eb134df6f321de4e63141f2Rusty Russell			frame_success = false;
9015100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		}
9025100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	}
9035100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (status->frame_count == 0) {
9045100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was not transmitted at all. */
905e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[0].count = 0;
906e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
907e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		/*
908e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * If the short retries (RTS, not data frame) have exceeded
909e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * the limit, the hw will not have tried the selected rate,
910e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * but will have used the fallback rate instead.
911e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * Don't let the rate control count attempts for the selected
912e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * rate in this case, otherwise the statistics will be off.
913e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 */
914e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[0].count = 0;
915e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[1].count = status->frame_count;
916e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else {
917e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		if (status->frame_count > retry_limit) {
918e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[0].count = retry_limit;
919e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[1].count = status->frame_count -
920e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg					retry_limit;
921e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
922e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		} else {
923e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[0].count = status->frame_count;
924e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[1].idx = -1;
925e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		}
926e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	}
9275100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch
9285100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	return frame_success;
929e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
930e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
931e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */
932e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev)
933e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
9345100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
9355100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_tx_suspend(dev);
9365100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
9375100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_tx_suspend(dev);
938e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
939e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
940e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */
941e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev)
942e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
9435100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
9445100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_tx_resume(dev);
9455100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
9465100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_tx_resume(dev);
947e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
948