xmit.c revision eb032b9837a958e21ca000358a5bde5e17192ddb
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. */
83a3c0b87c4f21911fb7185902dd13f0e3cd7f33f7Lorenzo Navastatic int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
84e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
858318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	int base = aphy ? 0 : 4;
868318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
87e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (plcp->raw[0] & 0xF) {
88e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xB:
898318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 0;
90e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xF:
918318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 1;
92e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xA:
938318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 2;
94e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xE:
958318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 3;
96e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x9:
978318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 4;
98e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xD:
998318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 5;
100e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x8:
1018318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 6;
102e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0xC:
1038318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 7;
104e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
1058318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
106e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
107e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
108e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_cck(const u8 bitrate)
109e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
110e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
111e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
112e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x0A;
113e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
114e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x14;
115e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
116e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x37;
117e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
118e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x6E;
119e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
120e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
121e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
122e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
123e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
124e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
125e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
126e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
127e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
128e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xB;
129e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
130e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xF;
131e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
132e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xA;
133e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
134e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xE;
135e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
136e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x9;
137e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
138e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xD;
139e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
140e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0x8;
141e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
142e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return 0xC;
143e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
144e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
145e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
146e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
147e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
148e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
149e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			   const u16 octets, const u8 bitrate)
150e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
151e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	__u8 *raw = plcp->raw;
152e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
153e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (b43_is_ofdm_rate(bitrate)) {
1541a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		u32 d;
1551a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch
1561a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d = b43_plcp_get_ratecode_ofdm(bitrate);
157e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(octets & 0xF000);
1581a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch		d |= (octets << 5);
159b52a033c2c501a8015df3727a4bd73389ccb1641Matthieu CASTET		plcp->data = cpu_to_le32(d);
160e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
161e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		u32 plen;
162e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
163e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		plen = octets * 16 / bitrate;
164e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if ((octets * 16 % bitrate) > 0) {
165e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			plen++;
166e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if ((bitrate == B43_CCK_RATE_11MB)
167e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    && ((octets * 8 % 11) < 4)) {
168e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x84;
169e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else
170e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				raw[1] = 0x04;
171e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else
172e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			raw[1] = 0x04;
173b52a033c2c501a8015df3727a4bd73389ccb1641Matthieu CASTET		plcp->data |= cpu_to_le32(plen << 16);
174e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		raw[0] = b43_plcp_get_ratecode_cck(bitrate);
175e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
176e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
177e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
1783311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłeckistatic u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
1793311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki{
1803311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	const struct b43_phy *phy = &dev->phy;
1813311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
1823311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	u16 control = 0;
1833311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	u16 bw;
1843311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
1853311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	if (phy->type == B43_PHYTYPE_LP)
1863311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		bw = B43_TXH_PHY1_BW_20;
1873311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	else /* FIXME */
1883311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		bw = B43_TXH_PHY1_BW_20;
1893311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
1903311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	if (0) { /* FIXME: MIMO */
1913311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	} else if (b43_is_cck_rate(bitrate) && phy->type != B43_PHYTYPE_LP) {
1923311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		control = bw;
1933311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	} else {
1943311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		control = bw;
1953311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		e = b43_tx_legacy_rate_phy_ctl_ent(bitrate);
1963311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		if (e) {
1973311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			control |= e->coding_rate;
1983311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			control |= e->modulation;
1993311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		}
2003311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		control |= B43_TXH_PHY1_MODE_SISO;
2013311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	}
2023311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
2033311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	return control;
2043311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki}
2053311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
206e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_calc_fallback_rate(u8 bitrate)
207e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
208e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (bitrate) {
209e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_1MB:
210e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
211e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_2MB:
212e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_1MB;
213e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_5MB:
214e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_2MB;
215e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_CCK_RATE_11MB:
216e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
217e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_6MB:
218e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_CCK_RATE_5MB;
219e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_9MB:
220e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_6MB;
221e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_12MB:
222e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_9MB;
223e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_18MB:
224e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_12MB;
225e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_24MB:
226e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_18MB;
227e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_36MB:
228e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_24MB;
229e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_48MB:
230e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_36MB;
231e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_OFDM_RATE_54MB:
232e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return B43_OFDM_RATE_48MB;
233e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
234e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	B43_WARN_ON(1);
235e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return 0;
236e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
237e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
238eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch/* Generate a TX data header. */
23909552ccd8277e6382097e93a40f7311a09449367Michael Bueschint b43_generate_txhdr(struct b43_wldev *dev,
24009552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u8 *_txhdr,
241035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		       struct sk_buff *skb_frag,
242e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		       struct ieee80211_tx_info *info,
24309552ccd8277e6382097e93a40f7311a09449367Michael Buesch		       u16 cookie)
244e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
245035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski	const unsigned char *fragment_data = skb_frag->data;
246035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski	unsigned int fragment_len = skb_frag->len;
247eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
248e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_phy *phy = &dev->phy;
249e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct ieee80211_hdr *wlhdr =
250e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (const struct ieee80211_hdr *)fragment_data;
251d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg	int use_encryption = !!info->control.hw_key;
252f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	__le16 fctl = wlhdr->frame_control;
2538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	struct ieee80211_rate *fbrate;
254e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 rate, rate_fb;
255e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int rate_ofdm, rate_fb_ofdm;
256e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	unsigned int plcp_fragment_len;
257e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 mac_ctl = 0;
258e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phy_ctl = 0;
259e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u8 extra_ft = 0;
2602e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	struct ieee80211_rate *txrate;
261e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	struct ieee80211_tx_rate *rates;
262e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
263e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(txhdr, 0, sizeof(*txhdr));
264e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
265e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
2662e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
267e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_ofdm = b43_is_ofdm_rate(rate);
268870abdf67170daa9f1022e55a35c469239fcc74cFelix Fietkau	fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate;
2698318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	rate_fb = fbrate->hw_value;
270e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
271e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
272e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
273e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate);
274e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
275e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
276e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_frame_ctl = wlhdr->frame_control;
277e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
278e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
279e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Calculate duration for fallback rate */
280e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if ((rate_fb == rate) ||
281e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
282e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	    (wlhdr->duration_id == cpu_to_le16(0))) {
283e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* If the fallback rate equals the normal rate or the
284e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * dur_id field contains an AID, CFP magic or 0,
285e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * use the original dur_id field. */
286e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->dur_fb = wlhdr->duration_id;
287e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else {
288e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		txhdr->dur_fb = ieee80211_generic_frame_duration(
289e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			dev->wl->hw, info->control.vif, fragment_len, fbrate);
290e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
291e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
292e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp_fragment_len = fragment_len + FCS_LEN;
293e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (use_encryption) {
294e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		u8 key_idx = info->control.hw_key->hw_key_idx;
295e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		struct b43_key *key;
296e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
297e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		size_t iv_len;
298e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
29966d2d089c394c7e31020947d682523f77a93244bMichael Buesch		B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key));
300e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		key = &(dev->key[key_idx]);
3017be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch
30209552ccd8277e6382097e93a40f7311a09449367Michael Buesch		if (unlikely(!key->keyconf)) {
30309552ccd8277e6382097e93a40f7311a09449367Michael Buesch			/* This key is invalid. This might only happen
30409552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * in a short timeframe after machine resume before
30509552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * we were able to reconfigure keys.
30609552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * Drop this packet completely. Do not transmit it
30709552ccd8277e6382097e93a40f7311a09449367Michael Buesch			 * unencrypted to avoid leaking information. */
30809552ccd8277e6382097e93a40f7311a09449367Michael Buesch			return -ENOKEY;
3097be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch		}
31009552ccd8277e6382097e93a40f7311a09449367Michael Buesch
31109552ccd8277e6382097e93a40f7311a09449367Michael Buesch		/* Hardware appends ICV. */
31276708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau		plcp_fragment_len += info->control.hw_key->icv_len;
31309552ccd8277e6382097e93a40f7311a09449367Michael Buesch
31409552ccd8277e6382097e93a40f7311a09449367Michael Buesch		key_idx = b43_kidx_to_fw(dev, key_idx);
31509552ccd8277e6382097e93a40f7311a09449367Michael Buesch		mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
31609552ccd8277e6382097e93a40f7311a09449367Michael Buesch			   B43_TXH_MAC_KEYIDX;
31709552ccd8277e6382097e93a40f7311a09449367Michael Buesch		mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
31809552ccd8277e6382097e93a40f7311a09449367Michael Buesch			   B43_TXH_MAC_KEYALG;
319f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison		wlhdr_len = ieee80211_hdrlen(fctl);
320035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		if (key->algorithm == B43_SEC_ALGO_TKIP) {
321035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			u16 phase1key[5];
322035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			int i;
323035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			/* we give the phase1key and iv16 here, the key is stored in
324035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			 * shm. With that the hardware can do phase 2 and encryption.
325035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			 */
326035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
327035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski					IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
328cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			/* phase1key is in host endian. Copy to little-endian txhdr->iv. */
329cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			for (i = 0; i < 5; i++) {
330cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch				txhdr->iv[i * 2 + 0] = phase1key[i];
331cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch				txhdr->iv[i * 2 + 1] = phase1key[i] >> 8;
332cde1b55b43b71cabb1a94278a809bca21b9df791Michael Buesch			}
333035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			/* iv16 */
334035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
335035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		} else {
336035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			iv_len = min((size_t) info->control.hw_key->iv_len,
337035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski				     ARRAY_SIZE(txhdr->iv));
338035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski			memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
339035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9gregor kowski		}
340e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
341eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	if (b43_is_old_txhdr_format(dev)) {
342eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
343eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      plcp_fragment_len, rate);
344eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	} else {
345eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp),
346eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      plcp_fragment_len, rate);
347eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	}
348e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
349e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			      plcp_fragment_len, rate_fb);
350e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
351e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Extra Frame Types */
352e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_fb_ofdm)
353eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		extra_ft |= B43_TXH_EFT_FB_OFDM;
354eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
355eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		extra_ft |= B43_TXH_EFT_FB_CCK;
356e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
357e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Set channel radio code. Note that the micrcode ORs 0x100 to
358e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * this value before comparing it to the value in SHM, if this
359e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 * is a 5Ghz packet.
360e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	 */
361e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->chan_radio_code = phy->channel;
362e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
363e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* PHY TX Control word */
364e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (rate_ofdm)
365eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ENC_OFDM;
366eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
367eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ENC_CCK;
368e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
369eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
3709db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch
371e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) {
3729db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 0: /* Default */
373eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT01AUTO;
374e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
3759db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 1: /* Antenna 0 */
376eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT0;
377e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
3789db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch	case 2: /* Antenna 1 */
379eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT1;
380eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		break;
381eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	case 3: /* Antenna 2 */
382eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT2;
383eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		break;
384eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	case 4: /* Antenna 3 */
385eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		phy_ctl |= B43_TXH_PHY_ANT3;
386e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
387e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
388e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
389e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
390e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
391e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	rates = info->control.rates;
392e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* MAC control */
393e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
394eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_ACK;
395f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg	/* use hardware sequence counter as the non-TID counter */
396f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
397eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_HWSEQ;
398e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
399eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_STMSDU;
400e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A)
401eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_5GHZ;
402e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
403e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	/* Overwrite rates[0].count to make the retry calculation
404e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * in the tx status easier. need the actual retry limit to
405e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * detect whether the fallback rate was used.
406e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 */
407e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
408e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	    (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
409e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
410eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		mac_ctl |= B43_TXH_MAC_LONGFRAME;
411e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else {
412e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
413e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	}
414e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
415e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Generate the RTS or CTS-to-self frame */
416e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
417e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
418e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int len;
419e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		struct ieee80211_hdr *hdr;
420e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate, rts_rate_fb;
421e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int rts_rate_ofdm, rts_rate_fb_ofdm;
422eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		struct b43_plcp_hdr6 *plcp;
4232e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg		struct ieee80211_rate *rts_cts_rate;
424e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
425e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
4262e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg
4272e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg		rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
428e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
429e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb = b43_calc_fallback_rate(rts_rate);
430e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
431e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
432e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
433eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			struct ieee80211_cts *cts;
434eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
435eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			if (b43_is_old_txhdr_format(dev)) {
436eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
437eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->old_format.rts_frame);
438eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			} else {
439eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				cts = (struct ieee80211_cts *)
440eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->new_format.rts_frame);
441eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
442e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
443e4d6b7951812d98417feb10784e400e253caf633Michael Buesch						fragment_data, fragment_len,
444e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg						info, cts);
445eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDCTS;
446e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_cts);
447e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
448eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			struct ieee80211_rts *rts;
449eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
450eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			if (b43_is_old_txhdr_format(dev)) {
451eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
452eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->old_format.rts_frame);
453eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			} else {
454eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				rts = (struct ieee80211_rts *)
455eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					(txhdr->new_format.rts_frame);
456eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			}
457e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			ieee80211_rts_get(dev->wl->hw, info->control.vif,
458eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch					  fragment_data, fragment_len,
459e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg					  info, rts);
460eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			mac_ctl |= B43_TXH_MAC_SENDRTS;
461e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			len = sizeof(struct ieee80211_rts);
462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
463e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		len += FCS_LEN;
464eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
465eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		/* Generate the PLCP headers for the RTS/CTS frame */
466eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		if (b43_is_old_txhdr_format(dev))
467eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			plcp = &txhdr->old_format.rts_plcp;
468eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
469eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			plcp = &txhdr->new_format.rts_plcp;
470eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
471eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				      len, rts_rate);
472eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		plcp = &txhdr->rts_plcp_fb;
473eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
474e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				      len, rts_rate_fb);
475eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
476eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		if (b43_is_old_txhdr_format(dev)) {
477eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
478eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				(&txhdr->old_format.rts_frame);
479eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
480eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			hdr = (struct ieee80211_hdr *)
481eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch				(&txhdr->new_format.rts_frame);
482eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
483e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		txhdr->rts_dur_fb = hdr->duration_id;
484eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch
485e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_ofdm) {
486eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_OFDM;
487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_ofdm(rts_rate);
489eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		} else {
490eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTS_CCK;
491e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			txhdr->phy_rate_rts =
492e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    b43_plcp_get_ratecode_cck(rts_rate);
493eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		}
494e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (rts_rate_fb_ofdm)
495eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
496eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		else
497eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch			extra_ft |= B43_TXH_EFT_RTSFB_CCK;
4983311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
4993311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
5003311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		    phy->type == B43_PHYTYPE_N) {
5013311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			txhdr->phy_ctl1_rts = cpu_to_le16(
5023311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki				b43_generate_tx_phy_ctl1(dev, rts_rate));
5033311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			txhdr->phy_ctl1_rts_fb = cpu_to_le16(
5043311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki				b43_generate_tx_phy_ctl1(dev, rts_rate_fb));
5053311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		}
506e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
507e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
508e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Magic cookie */
509eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	if (b43_is_old_txhdr_format(dev))
510eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		txhdr->old_format.cookie = cpu_to_le16(cookie);
511eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch	else
512eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch		txhdr->new_format.cookie = cpu_to_le16(cookie);
513e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
5143311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	if (phy->type == B43_PHYTYPE_N) {
5153311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		txhdr->phy_ctl1 =
5163311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
5173311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki		txhdr->phy_ctl1_fb =
5183311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate_fb));
5193311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki	}
5203311abbbbff1719bbbc8208761e4a75f095f383cRafał Miłecki
521e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Apply the bitfields */
522e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
523e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
524e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	txhdr->extra_ft = extra_ft;
525e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
52609552ccd8277e6382097e93a40f7311a09449367Michael Buesch	return 0;
527e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
528e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
529e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev,
530e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       u8 in_rssi, int ofdm,
531e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			       int adjust_2053, int adjust_2050)
532e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
533e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
534ef1a628d83fc0423c36e773281162be790503168Michael Buesch	struct b43_phy_g *gphy = phy->g;
535e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s32 tmp;
536e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
537e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (phy->radio_ver) {
538e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2050:
539e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (ofdm) {
540e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
541e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (tmp > 127)
542e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 256;
543e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp *= 73;
544e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp /= 64;
545e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (adjust_2050)
546e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
547e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			else
548e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 3;
549e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		} else {
550dedb1eb977d75f301b17190cc4b6e7d17dbf17dbRafał Miłecki			if (dev->sdev->bus->sprom.
551e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			    boardflags_lo & B43_BFL_RSSI) {
552e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				if (in_rssi > 63)
553e4d6b7951812d98417feb10784e400e253caf633Michael Buesch					in_rssi = 63;
554ef1a628d83fc0423c36e773281162be790503168Michael Buesch				B43_WARN_ON(phy->type != B43_PHYTYPE_G);
555ef1a628d83fc0423c36e773281162be790503168Michael Buesch				tmp = gphy->nrssi_lt[in_rssi];
556e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
557e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -131;
558e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
559e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 57;
560e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			} else {
561e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = in_rssi;
562e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp = 31 - tmp;
563e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp *= -149;
564e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp /= 128;
565e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp -= 68;
566e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
567e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (phy->type == B43_PHYTYPE_G && adjust_2050)
568e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				tmp += 25;
569e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
570e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
571e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case 0x2060:
572e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (in_rssi > 127)
573e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi - 256;
574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp = in_rssi;
576e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
578e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp = in_rssi;
579e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp -= 11;
580e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp *= 103;
581e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		tmp /= 64;
582e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (adjust_2053)
583e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 109;
584e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
585e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			tmp -= 83;
586e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
587e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
588e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return (s8) tmp;
589e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
590e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
591e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO
592e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0
593e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi)
594e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
595e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_phy *phy = &dev->phy;
596e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	s8 ret;
597e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
598e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phy->type == B43_PHYTYPE_A) {
599e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		//TODO: Incomplete specs.
600e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = 0;
601e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	} else
602e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1);
603e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
604e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return ret;
605e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
606e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif
607e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
608e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
609e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
610e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_rx_status status;
611e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct b43_plcp_hdr6 *plcp;
612e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	struct ieee80211_hdr *wlhdr;
613e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
614f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	__le16 fctl;
615e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 phystat0, phystat3, chanstat, mactime;
616e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u32 macstat;
617e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	u16 chanid;
6188318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	u16 phytype;
619e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	int padding;
620e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
621e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	memset(&status, 0, sizeof(status));
622e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
623e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Get metadata about the frame from the header. */
624e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	phystat0 = le16_to_cpu(rxhdr->phy_status0);
625e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	phystat3 = le16_to_cpu(rxhdr->phy_status3);
626e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	macstat = le32_to_cpu(rxhdr->mac_status);
627e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	mactime = le16_to_cpu(rxhdr->mac_time);
628e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanstat = le16_to_cpu(rxhdr->channel);
6298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	phytype = chanstat & B43_RX_CHAN_PHYTYPE;
630e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
631ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
632e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11FCSErrorCount++;
633ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_FAILED_FCS_CRC;
634ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	}
635ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV)))
636ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_FAILED_PLCP_CRC;
637ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (phystat0 & B43_RX_PHYST0_SHORTPRMBL)
638ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		status.flag |= RX_FLAG_SHORTPRE;
639e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DECERR) {
640e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* Decryption with the given key failed.
641e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * Drop the packet. We also won't be able to decrypt it with
642e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * the key in software. */
643e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
644e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
645e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
646e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* Skip PLCP and padding */
647e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
648e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) {
649e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (1)\n");
650e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
651e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
652e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	plcp = (struct b43_plcp_hdr6 *)(skb->data + padding);
653e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding);
654e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	/* The skb contains the Wireless Header + payload data now */
655e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */  + FCS_LEN))) {
656e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		b43dbg(dev->wl, "RX: Packet size underrun (2)\n");
657e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		goto drop;
658e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
659e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	wlhdr = (struct ieee80211_hdr *)(skb->data);
660f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	fctl = wlhdr->frame_control;
661e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
662e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (macstat & B43_RX_MAC_DEC) {
663e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		unsigned int keyidx;
664e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		int wlhdr_len;
665e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
666e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = ((macstat & B43_RX_MAC_KEYIDX)
667e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			  >> B43_RX_MAC_KEYIDX_SHIFT);
668e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		/* We must adjust the key index here. We want the "physical"
669e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 * key index, but the ucode passed it slightly different.
670e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		 */
671e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		keyidx = b43_kidx_to_raw(dev, keyidx);
67266d2d089c394c7e31020947d682523f77a93244bMichael Buesch		B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
673e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
674e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
675f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison			wlhdr_len = ieee80211_hdrlen(fctl);
676e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			if (unlikely(skb->len < (wlhdr_len + 3))) {
677e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				b43dbg(dev->wl,
678e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				       "RX: Packet size underrun (3)\n");
679e4d6b7951812d98417feb10784e400e253caf633Michael Buesch				goto drop;
680e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			}
681e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			status.flag |= RX_FLAG_DECRYPTED;
682e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		}
683e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
684e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
6857b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	/* Link quality statistics */
6867b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
6877b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch//		s8 rssi = max(rxhdr->power0, rxhdr->power1);
6887b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//TODO: Find out what the rssi value is (dBm or percentage?)
6897b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//      and also find out what the maximum possible value is.
6907b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch		//      Fill status.ssi and status.signal fields.
6917b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	} else {
692566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf		status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
6937b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat0 & B43_RX_PHYST0_OFDM),
6947b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat0 & B43_RX_PHYST0_GAINCTL),
6957b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch						  (phystat3 & B43_RX_PHYST3_TRSTATE));
6967b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch	}
6977b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch
698e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (phystat0 & B43_RX_PHYST0_OFDM)
6998318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
7008318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg						phytype == B43_PHYTYPE_A);
701e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	else
7028318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
703ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	if (unlikely(status.rate_idx == -1)) {
704ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		/* PLCP seems to be corrupted.
705ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		 * Drop the frame, if we are not interested in corrupted frames. */
706ce4fbdbf161b2676b3833412367113572d739253Michael Buesch		if (!(dev->wl->filter_flags & FIF_PLCPFAIL))
707ce4fbdbf161b2676b3833412367113572d739253Michael Buesch			goto drop;
708ce4fbdbf161b2676b3833412367113572d739253Michael Buesch	}
709e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
710c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
711c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	/*
712d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * All frames on monitor interfaces and beacons always need a full
713d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
714d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * purposes and beacons for IBSS merging.
715d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * This code assumes we get to process the packet within 16 bits
716d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * of timestamp, i.e. about 65 milliseconds after the PHY received
717d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * the first symbol.
718c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	 */
719f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison	if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
720c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		u16 low_mactime_now;
721c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
722c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		b43_tsf_read(dev, &status.mactime);
723c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		low_mactime_now = status.mactime;
724c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime = status.mactime & ~0xFFFFULL;
725c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime += mactime;
726c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		if (low_mactime_now <= mactime)
727c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville			status.mactime -= 0x10000;
7286ebacbb79d2d05978ba50a24d8cbe2a76ff2014cJohannes Berg		status.flag |= RX_FLAG_MACTIME_MPDU;
729c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	}
730e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
731e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
732e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
733e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_A:
7348318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_5GHZ;
735d987160b710c98997015832422a05e18d9f0f925Michael Buesch		B43_WARN_ON(1);
736d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* FIXME: We don't really know which value the "chanid" contains.
737d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 *        So the following assignment might be wrong. */
7388318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.freq = b43_channel_to_freq_5ghz(chanid);
739e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
740e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	case B43_PHYTYPE_G:
7418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_2GHZ;
742d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the radio channel cookie value as used
743d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * to tune the radio. */
744e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		status.freq = chanid + 2400;
745d987160b710c98997015832422a05e18d9f0f925Michael Buesch		break;
746d987160b710c98997015832422a05e18d9f0f925Michael Buesch	case B43_PHYTYPE_N:
747826ee70664c658a022d999f7eb4d3cd9448895ddGábor Stefanik	case B43_PHYTYPE_LP:
748d987160b710c98997015832422a05e18d9f0f925Michael Buesch		/* chanid is the SHM channel cookie. Which is the plain
749d987160b710c98997015832422a05e18d9f0f925Michael Buesch		 * channel number in b43. */
7508318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		if (chanstat & B43_RX_CHAN_5GHZ) {
7518318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_5GHZ;
7528318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.freq = b43_freq_to_channel_5ghz(chanid);
7538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		} else {
7548318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.band = IEEE80211_BAND_2GHZ;
7558318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg			status.freq = b43_freq_to_channel_2ghz(chanid);
7568318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		}
757e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		break;
758e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	default:
759e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		B43_WARN_ON(1);
760d987160b710c98997015832422a05e18d9f0f925Michael Buesch		goto drop;
761e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
762e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
763f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
76472f5f457564e8ebc6c38ee4f98ee59cd03c2f614John W. Linville	ieee80211_rx_ni(dev->wl->hw, skb);
765e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
766990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch#if B43_DEBUG
767990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch	dev->rx_count++;
768990b86f4f9c54f83085d4136498ac44719b17654Michael Buesch#endif
769e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	return;
770e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop:
771e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43dbg(dev->wl, "RX: Packet dropped\n");
772e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	dev_kfree_skb_any(skb);
773e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
774e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
775e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev,
776e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			 const struct b43_txstatus *status)
777e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
778e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	b43_debugfs_log_txstat(dev, status);
779e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
780e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->intermediate)
781e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
782e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->for_ampdu)
783e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		return;
784e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (!status->acked)
785e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		dev->wl->ieee_stats.dot11ACKFailureCount++;
786e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	if (status->rts_count) {
787e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		if (status->rts_count == 0xF)	//FIXME
788e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSFailureCount++;
789e4d6b7951812d98417feb10784e400e253caf633Michael Buesch		else
790e4d6b7951812d98417feb10784e400e253caf633Michael Buesch			dev->wl->ieee_stats.dot11RTSSuccessCount++;
791e4d6b7951812d98417feb10784e400e253caf633Michael Buesch	}
792e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
7935100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
7945100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_handle_txstatus(dev, status);
7955100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
7965100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_handle_txstatus(dev, status);
79718c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch
79818c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch	b43_phy_txpower_check(dev, 0);
799e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
800e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
8015100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch/* Fill out the mac80211 TXstatus report based on the b43-specific
8025100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * txstatus report data. This returns a boolean whether the frame was
8035100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * successfully transmitted. */
804e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Bergbool b43_fill_txstatus_report(struct b43_wldev *dev,
805e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			      struct ieee80211_tx_info *report,
8065100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			      const struct b43_txstatus *status)
807e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
8085100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	bool frame_success = 1;
809e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	int retry_limit;
810e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
811e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	/* preserve the confiured retry limit before clearing the status
812e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * The xmit function has overwritten the rc's value with the actual
813e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * retry limit done by the hardware */
814e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	retry_limit = report->status.rates[0].count;
815e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	ieee80211_tx_info_clear_status(report);
8165100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch
8175100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (status->acked) {
8185100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was ACKed. */
819e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		report->flags |= IEEE80211_TX_STAT_ACK;
8205100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	} else {
8215100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was not ACKed... */
822e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
8235100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			/* ...but we expected an ACK. */
8245100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch			frame_success = 0;
8255100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		}
8265100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	}
8275100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (status->frame_count == 0) {
8285100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		/* The frame was not transmitted at all. */
829e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[0].count = 0;
830e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
831e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		/*
832e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * If the short retries (RTS, not data frame) have exceeded
833e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * the limit, the hw will not have tried the selected rate,
834e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * but will have used the fallback rate instead.
835e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * Don't let the rate control count attempts for the selected
836e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 * rate in this case, otherwise the statistics will be off.
837e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		 */
838e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[0].count = 0;
839e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		report->status.rates[1].count = status->frame_count;
840e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else {
841e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		if (status->frame_count > retry_limit) {
842e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[0].count = retry_limit;
843e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[1].count = status->frame_count -
844e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg					retry_limit;
845e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
846e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		} else {
847e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[0].count = status->frame_count;
848e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			report->status.rates[1].idx = -1;
849e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		}
850e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	}
8515100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch
8525100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	return frame_success;
853e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
854e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
855e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */
856e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev)
857e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
8585100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
8595100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_tx_suspend(dev);
8605100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
8615100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_tx_suspend(dev);
862e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
863e4d6b7951812d98417feb10784e400e253caf633Michael Buesch
864e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */
865e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev)
866e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{
8675100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	if (b43_using_pio_transfers(dev))
8685100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_pio_tx_resume(dev);
8695100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch	else
8705100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch		b43_dma_tx_resume(dev);
871e4d6b7951812d98417feb10784e400e253caf633Michael Buesch}
872