175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/*
275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  Broadcom B43legacy wireless driver
475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  Transmission (TX/RX) related functions.
675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  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>
1075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
1175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
1275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  Copyright (C) 2007 Larry Finger <Larry.Finger@lwfinger.net>
1375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
1475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  This program is free software; you can redistribute it and/or modify
1575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  it under the terms of the GNU General Public License as published by
1675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  the Free Software Foundation; either version 2 of the License, or
1775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  (at your option) any later version.
1875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
1975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  This program is distributed in the hope that it will be useful,
2075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  but WITHOUT ANY WARRANTY; without even the implied warranty of
2175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  GNU General Public License for more details.
2375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
2475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  You should have received a copy of the GNU General Public License
2575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  along with this program; see the file COPYING.  If not, write to
2675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
2775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger  Boston, MA 02110-1301, USA.
2875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
2975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger*/
3075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
3175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger#include <net/dst.h>
3275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
3375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger#include "xmit.h"
3475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger#include "phy.h"
3575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger#include "dma.h"
3675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger#include "pio.h"
3775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
3875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
3975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Extract the bitrate out of a CCK PLCP header. */
408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
4175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
4275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	switch (plcp->raw[0]) {
4375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0x0A:
448318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 0;
4575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0x14:
468318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 1;
4775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0x37:
488318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 2;
4975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0x6E:
508318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return 3;
5175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
5275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	B43legacy_BUG_ON(1);
538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
5475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
5575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
5675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Extract the bitrate out of an OFDM PLCP header. */
578318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
588318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg					      bool aphy)
5975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
608318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	int base = aphy ? 0 : 4;
618318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg
6275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	switch (plcp->raw[0] & 0xF) {
6375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0xB:
648318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 0;
6575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0xF:
668318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 1;
6775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0xA:
688318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 2;
6975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0xE:
708318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 3;
7175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0x9:
728318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 4;
7375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0xD:
748318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 5;
7575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0x8:
768318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 6;
7775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0xC:
788318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		return base + 7;
7975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
8075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	B43legacy_BUG_ON(1);
818318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	return -1;
8275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
8375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
8475388acd0cd827dc1498043daa7d1c760902cd67Larry Fingeru8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
8575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
8675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	switch (bitrate) {
8775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_CCK_RATE_1MB:
8875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0x0A;
8975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_CCK_RATE_2MB:
9075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0x14;
9175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_CCK_RATE_5MB:
9275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0x37;
9375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_CCK_RATE_11MB:
9475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0x6E;
9575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
9675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	B43legacy_BUG_ON(1);
9775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	return 0;
9875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
9975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
10075388acd0cd827dc1498043daa7d1c760902cd67Larry Fingeru8 b43legacy_plcp_get_ratecode_ofdm(const u8 bitrate)
10175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
10275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	switch (bitrate) {
10375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_6MB:
10475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0xB;
10575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_9MB:
10675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0xF;
10775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_12MB:
10875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0xA;
10975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_18MB:
11075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0xE;
11175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_24MB:
11275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0x9;
11375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_36MB:
11475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0xD;
11575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_48MB:
11675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0x8;
11775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_54MB:
11875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return 0xC;
11975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
12075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	B43legacy_BUG_ON(1);
12175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	return 0;
12275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
12375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
12475388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_generate_plcp_hdr(struct b43legacy_plcp_hdr4 *plcp,
12575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				 const u16 octets, const u8 bitrate)
12675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
12775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	__le32 *data = &(plcp->data);
12875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	__u8 *raw = plcp->raw;
12975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
13075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (b43legacy_is_ofdm_rate(bitrate)) {
13175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		u16 d;
13275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
13375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		d = b43legacy_plcp_get_ratecode_ofdm(bitrate);
13475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		B43legacy_WARN_ON(octets & 0xF000);
13575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		d |= (octets << 5);
13675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		*data = cpu_to_le32(d);
13775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	} else {
13875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		u32 plen;
13975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
14075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		plen = octets * 16 / bitrate;
14175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		if ((octets * 16 % bitrate) > 0) {
14275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			plen++;
14375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			if ((bitrate == B43legacy_CCK_RATE_11MB)
14475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			    && ((octets * 8 % 11) < 4))
14575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				raw[1] = 0x84;
14675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			else
14775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				raw[1] = 0x04;
14875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		} else
14975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			raw[1] = 0x04;
15075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		*data |= cpu_to_le32(plen << 16);
15175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		raw[0] = b43legacy_plcp_get_ratecode_cck(bitrate);
15275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
15375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
15475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
15575388acd0cd827dc1498043daa7d1c760902cd67Larry Fingerstatic u8 b43legacy_calc_fallback_rate(u8 bitrate)
15675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
15775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	switch (bitrate) {
15875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_CCK_RATE_1MB:
15975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_CCK_RATE_1MB;
16075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_CCK_RATE_2MB:
16175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_CCK_RATE_1MB;
16275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_CCK_RATE_5MB:
16375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_CCK_RATE_2MB;
16475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_CCK_RATE_11MB:
16575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_CCK_RATE_5MB;
16675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_6MB:
16775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_CCK_RATE_5MB;
16875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_9MB:
16975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_OFDM_RATE_6MB;
17075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_12MB:
17175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_OFDM_RATE_9MB;
17275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_18MB:
17375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_OFDM_RATE_12MB;
17475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_24MB:
17575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_OFDM_RATE_18MB;
17675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_36MB:
17775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_OFDM_RATE_24MB;
17875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_48MB:
17975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_OFDM_RATE_36MB;
18075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_OFDM_RATE_54MB:
18175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return B43legacy_OFDM_RATE_48MB;
18275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
18375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	B43legacy_BUG_ON(1);
18475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	return 0;
18575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
18675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
1879eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Briviostatic int generate_txhdr_fw3(struct b43legacy_wldev *dev,
18875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			       struct b43legacy_txhdr_fw3 *txhdr,
18975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			       const unsigned char *fragment_data,
19075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			       unsigned int fragment_len,
191e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			       struct ieee80211_tx_info *info,
19275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			       u16 cookie)
19375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
19475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	const struct ieee80211_hdr *wlhdr;
195d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg	int use_encryption = !!info->control.hw_key;
19675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u8 rate;
1978318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	struct ieee80211_rate *rate_fb;
19875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	int rate_ofdm;
19975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	int rate_fb_ofdm;
20075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	unsigned int plcp_fragment_len;
20175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u32 mac_ctl = 0;
20275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u16 phy_ctl = 0;
2032e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	struct ieee80211_rate *tx_rate;
204e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	struct ieee80211_tx_rate *rates;
20575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
20675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	wlhdr = (const struct ieee80211_hdr *)fragment_data;
20775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
20875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	memset(txhdr, 0, sizeof(*txhdr));
20975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
210e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	tx_rate = ieee80211_get_tx_rate(dev->wl->hw, info);
2112e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg
2122e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg	rate = tx_rate->hw_value;
21375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	rate_ofdm = b43legacy_is_ofdm_rate(rate);
214870abdf67170daa9f1022e55a35c469239fcc74cFelix Fietkau	rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate;
2158318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
21675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
21775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	txhdr->mac_frame_ctl = wlhdr->frame_control;
21875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
21975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
22075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* Calculate duration for fallback rate */
2218318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	if ((rate_fb->hw_value == rate) ||
22275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
22375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	    (wlhdr->duration_id == cpu_to_le16(0))) {
22475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		/* If the fallback rate equals the normal rate or the
22575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		 * dur_id field contains an AID, CFP magic or 0,
22675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		 * use the original dur_id field. */
22775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		txhdr->dur_fb = wlhdr->duration_id;
22875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	} else {
22975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
230e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg							 info->control.vif,
23175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger							 fragment_len,
2328318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg							 rate_fb);
23375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
23475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
23575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	plcp_fragment_len = fragment_len + FCS_LEN;
23675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (use_encryption) {
237e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		u8 key_idx = info->control.hw_key->hw_key_idx;
23875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		struct b43legacy_key *key;
23975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		int wlhdr_len;
24075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		size_t iv_len;
24175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
24275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		B43legacy_WARN_ON(key_idx >= dev->max_nr_keys);
24375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		key = &(dev->key[key_idx]);
24475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
24575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		if (key->enabled) {
24675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			/* Hardware appends ICV. */
24776708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau			plcp_fragment_len += info->control.hw_key->icv_len;
24875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
24975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			key_idx = b43legacy_kidx_to_fw(dev, key_idx);
25075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) &
25175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				   B43legacy_TX4_MAC_KEYIDX;
25275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			mac_ctl |= (key->algorithm <<
25375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				   B43legacy_TX4_MAC_KEYALG_SHIFT) &
25475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				   B43legacy_TX4_MAC_KEYALG;
255ba5b6efe5d945f7a4c5b656051cc16698afdda24Harvey Harrison			wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control);
25676708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau			iv_len = min((size_t)info->control.hw_key->iv_len,
25775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				     ARRAY_SIZE(txhdr->iv));
25875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
2599eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio		} else {
2609eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio			/* This key is invalid. This might only happen
2619eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio			 * in a short timeframe after machine resume before
2629eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio			 * we were able to reconfigure keys.
2639eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio			 * Drop this packet completely. Do not transmit it
2649eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio			 * unencrypted to avoid leaking information. */
2659eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio			return -ENOKEY;
26675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		}
26775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
26875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
26975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				    (&txhdr->plcp), plcp_fragment_len,
27075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				    rate);
27175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
27275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				    (&txhdr->plcp_fb), plcp_fragment_len,
2738318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg				    rate_fb->hw_value);
27475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
27575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* PHY TX Control word */
27675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (rate_ofdm)
2772d1f96dd90a20c25243cc3b13e9f21d72f00aba0Larry Finger		phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM;
278e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
27975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
280e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	switch (info->antenna_sel_tx) {
28175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0:
28275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		phy_ctl |= B43legacy_TX4_PHY_ANTLAST;
28375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		break;
28475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 1:
28575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		phy_ctl |= B43legacy_TX4_PHY_ANT0;
28675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		break;
28775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 2:
28875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		phy_ctl |= B43legacy_TX4_PHY_ANT1;
28975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		break;
29075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	default:
29175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		B43legacy_BUG_ON(1);
29275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
29375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
29475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* MAC control */
295e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	rates = info->control.rates;
296e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
29775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		mac_ctl |= B43legacy_TX4_MAC_ACK;
298f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
29975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		mac_ctl |= B43legacy_TX4_MAC_HWSEQ;
300e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
30175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		mac_ctl |= B43legacy_TX4_MAC_STMSDU;
30275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (rate_fb_ofdm)
30375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
304e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg
305e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	/* Overwrite rates[0].count to make the retry calculation
306e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * in the tx status easier. need the actual retry limit to
307e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 * detect whether the fallback rate was used.
308e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	 */
309e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
310e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	    (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
311e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
3120a6e1bee5770a6d4c4569a4720614402ab5f9d7aStefano Brivio		mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
313e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	} else {
314e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
315e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	}
31675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
31775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* Generate the RTS or CTS-to-self frame */
318e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
319e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
32075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		unsigned int len;
32175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		struct ieee80211_hdr *hdr;
32275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		int rts_rate;
32375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		int rts_rate_fb;
32475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		int rts_rate_fb_ofdm;
32575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
326e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg		rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value;
32775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
32875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
32975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		if (rts_rate_fb_ofdm)
33075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM;
33175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
332e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
33375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			ieee80211_ctstoself_get(dev->wl->hw,
334e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg						info->control.vif,
33575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger						fragment_data,
336e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg						fragment_len, info,
33775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger						(struct ieee80211_cts *)
33875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger						(txhdr->rts_frame));
33975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			mac_ctl |= B43legacy_TX4_MAC_SENDCTS;
34075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			len = sizeof(struct ieee80211_cts);
34175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		} else {
34275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			ieee80211_rts_get(dev->wl->hw,
343e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg					  info->control.vif,
344e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg					  fragment_data, fragment_len, info,
34575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					  (struct ieee80211_rts *)
34675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					  (txhdr->rts_frame));
34775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			mac_ctl |= B43legacy_TX4_MAC_SENDRTS;
34875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			len = sizeof(struct ieee80211_rts);
34975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		}
35075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		len += FCS_LEN;
35175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
35275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					    (&txhdr->rts_plcp),
35375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					    len, rts_rate);
35475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
35575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					    (&txhdr->rts_plcp_fb),
35675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					    len, rts_rate_fb);
35775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
35875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		txhdr->rts_dur_fb = hdr->duration_id;
35975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
36075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
36175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* Magic cookie */
36275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	txhdr->cookie = cpu_to_le16(cookie);
36375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
36475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* Apply the bitfields */
36575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
36675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
3679eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio
3689eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio	return 0;
36975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
37075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
3719eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivioint b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
37275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			      u8 *txhdr,
37375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			      const unsigned char *fragment_data,
37475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			      unsigned int fragment_len,
375e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg			      struct ieee80211_tx_info *info,
37675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			      u16 cookie)
37775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
3789eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio	return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
37975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			   fragment_data, fragment_len,
380e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg			   info, cookie);
38175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
38275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
38375388acd0cd827dc1498043daa7d1c760902cd67Larry Fingerstatic s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev,
38475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				     u8 in_rssi, int ofdm,
38575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				     int adjust_2053, int adjust_2050)
38675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
38775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	struct b43legacy_phy *phy = &dev->phy;
38875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	s32 tmp;
38975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
39075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	switch (phy->radio_ver) {
39175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0x2050:
39275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		if (ofdm) {
39375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			tmp = in_rssi;
39475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			if (tmp > 127)
39575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp -= 256;
39675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			tmp *= 73;
39775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			tmp /= 64;
39875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			if (adjust_2050)
39975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp += 25;
40075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			else
40175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp -= 3;
40275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		} else {
4037797aa384870e3bb5bfd3b6a0eae61e7c7a4c993Larry Finger			if (dev->dev->bus->sprom.boardflags_lo
40475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			    & B43legacy_BFL_RSSI) {
40575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				if (in_rssi > 63)
40675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					in_rssi = 63;
40775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp = phy->nrssi_lt[in_rssi];
40875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp = 31 - tmp;
40975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp *= -131;
41075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp /= 128;
41175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp -= 57;
41275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			} else {
41375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp = in_rssi;
41475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp = 31 - tmp;
41575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp *= -149;
41675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp /= 128;
41775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp -= 68;
41875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			}
41975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			if (phy->type == B43legacy_PHYTYPE_G &&
42075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			    adjust_2050)
42175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				tmp += 25;
42275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		}
42375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		break;
42475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case 0x2060:
42575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		if (in_rssi > 127)
42675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			tmp = in_rssi - 256;
42775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		else
42875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			tmp = in_rssi;
42975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		break;
43075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	default:
43175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		tmp = in_rssi;
43275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		tmp -= 11;
43375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		tmp *= 103;
43475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		tmp /= 64;
43575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		if (adjust_2053)
43675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			tmp -= 109;
43775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		else
43875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			tmp -= 83;
43975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
44075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
44175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	return (s8)tmp;
44275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
44375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
44475388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_rx(struct b43legacy_wldev *dev,
44575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		  struct sk_buff *skb,
44675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		  const void *_rxhdr)
44775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
44875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	struct ieee80211_rx_status status;
44975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	struct b43legacy_plcp_hdr6 *plcp;
45075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	struct ieee80211_hdr *wlhdr;
45175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr;
452b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison	__le16 fctl;
45375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u16 phystat0;
45475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u16 phystat3;
45575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u16 chanstat;
45675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u16 mactime;
45775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u32 macstat;
45875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u16 chanid;
45975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u8 jssi;
46075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	int padding;
46175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
46275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	memset(&status, 0, sizeof(status));
46375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
46475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* Get metadata about the frame from the header. */
46575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	phystat0 = le16_to_cpu(rxhdr->phy_status0);
46675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	phystat3 = le16_to_cpu(rxhdr->phy_status3);
46775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	jssi = rxhdr->jssi;
46875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	macstat = le16_to_cpu(rxhdr->mac_status);
46975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	mactime = le16_to_cpu(rxhdr->mac_time);
47075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	chanstat = le16_to_cpu(rxhdr->channel);
47175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
47275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (macstat & B43legacy_RX_MAC_FCSERR)
47375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		dev->wl->ieee_stats.dot11FCSErrorCount++;
47475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
47575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* Skip PLCP and padding */
47675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	padding = (macstat & B43legacy_RX_MAC_PADDING) ? 2 : 0;
47775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (unlikely(skb->len < (sizeof(struct b43legacy_plcp_hdr6) +
47875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	    padding))) {
47975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacydbg(dev->wl, "RX: Packet size underrun (1)\n");
48075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		goto drop;
48175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
48275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	plcp = (struct b43legacy_plcp_hdr6 *)(skb->data + padding);
48375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	skb_pull(skb, sizeof(struct b43legacy_plcp_hdr6) + padding);
48475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* The skb contains the Wireless Header + payload data now */
48575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (unlikely(skb->len < (2+2+6/*minimum hdr*/ + FCS_LEN))) {
48675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacydbg(dev->wl, "RX: Packet size underrun (2)\n");
48775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		goto drop;
48875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
48975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	wlhdr = (struct ieee80211_hdr *)(skb->data);
490b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison	fctl = wlhdr->frame_control;
49175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
49275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if ((macstat & B43legacy_RX_MAC_DEC) &&
49375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	    !(macstat & B43legacy_RX_MAC_DECERR)) {
49475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		unsigned int keyidx;
49575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		int wlhdr_len;
49675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		int iv_len;
49775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		int icv_len;
49875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
49975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		keyidx = ((macstat & B43legacy_RX_MAC_KEYIDX)
50075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			  >> B43legacy_RX_MAC_KEYIDX_SHIFT);
50175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		/* We must adjust the key index here. We want the "physical"
50275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		 * key index, but the ucode passed it slightly different.
50375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		 */
50475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		keyidx = b43legacy_kidx_to_raw(dev, keyidx);
50575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		B43legacy_WARN_ON(keyidx >= dev->max_nr_keys);
50675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
50775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) {
50875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			/* Remove PROTECTED flag to mark it as decrypted. */
509b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison			B43legacy_WARN_ON(!ieee80211_has_protected(fctl));
510b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison			fctl &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
511b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison			wlhdr->frame_control = fctl;
51275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
513b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison			wlhdr_len = ieee80211_hdrlen(fctl);
51475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			if (unlikely(skb->len < (wlhdr_len + 3))) {
51575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				b43legacydbg(dev->wl, "RX: Packet size"
51675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					     " underrun3\n");
51775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				goto drop;
51875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			}
51975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			if (skb->data[wlhdr_len + 3] & (1 << 5)) {
52075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				/* The Ext-IV Bit is set in the "KeyID"
52175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				 * octet of the IV.
52275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				 */
52375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				iv_len = 8;
52475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				icv_len = 8;
52575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			} else {
52675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				iv_len = 4;
52775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				icv_len = 4;
52875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			}
52975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			if (unlikely(skb->len < (wlhdr_len + iv_len +
53075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			    icv_len))) {
53175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				b43legacydbg(dev->wl, "RX: Packet size"
53275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger					     " underrun4\n");
53375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				goto drop;
53475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			}
53575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			/* Remove the IV */
53675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			memmove(skb->data + iv_len, skb->data, wlhdr_len);
53775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			skb_pull(skb, iv_len);
53875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			/* Remove the ICV */
53975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			skb_trim(skb, skb->len - icv_len);
54075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
54175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			status.flag |= RX_FLAG_DECRYPTED;
54275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		}
54375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
54475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
545566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf	status.signal = b43legacy_rssi_postprocess(dev, jssi,
54675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				      (phystat0 & B43legacy_RX_PHYST0_OFDM),
54775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				      (phystat0 & B43legacy_RX_PHYST0_GAINCTL),
54875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				      (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
5498318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg	/* change to support A PHY */
55075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (phystat0 & B43legacy_RX_PHYST0_OFDM)
5518318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
55275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	else
5538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
55475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
555c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
556c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	/*
557d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * All frames on monitor interfaces and beacons always need a full
558d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
559d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * purposes and beacons for IBSS merging.
560d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * This code assumes we get to process the packet within 16 bits
561d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * of timestamp, i.e. about 65 milliseconds after the PHY received
562d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg	 * the first symbol.
563c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	 */
564b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison	if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
565c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		u16 low_mactime_now;
566c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville
567c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		b43legacy_tsf_read(dev, &status.mactime);
568c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		low_mactime_now = status.mactime;
569c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime = status.mactime & ~0xFFFFULL;
570c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		status.mactime += mactime;
571c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville		if (low_mactime_now <= mactime)
572c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville			status.mactime -= 0x10000;
5736ebacbb79d2d05978ba50a24d8cbe2a76ff2014cJohannes Berg		status.flag |= RX_FLAG_MACTIME_MPDU;
574c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville	}
57575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
57675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
57775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		  B43legacy_RX_CHAN_ID_SHIFT;
57875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
57975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_PHYTYPE_B:
58075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	case B43legacy_PHYTYPE_G:
5818318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg		status.band = IEEE80211_BAND_2GHZ;
58275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		status.freq = chanid + 2400;
58375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		break;
58475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	default:
58575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
58675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		       chanstat);
58775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
58875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
589f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
590f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg	ieee80211_rx_irqsafe(dev->wl->hw, skb);
59175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
59275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	return;
59375388acd0cd827dc1498043daa7d1c760902cd67Larry Fingerdrop:
59475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	b43legacydbg(dev->wl, "RX: Packet dropped\n");
59575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	dev_kfree_skb_any(skb);
59675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
59775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
59875388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_handle_txstatus(struct b43legacy_wldev *dev,
59975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			     const struct b43legacy_txstatus *status)
60075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
60175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	b43legacy_debugfs_log_txstat(dev, status);
60275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
60375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (status->intermediate)
60475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return;
60575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (status->for_ampdu)
60675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		return;
60775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (!status->acked)
60875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		dev->wl->ieee_stats.dot11ACKFailureCount++;
60975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (status->rts_count) {
61075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		if (status->rts_count == 0xF) /* FIXME */
61175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			dev->wl->ieee_stats.dot11RTSFailureCount++;
61275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		else
61375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			dev->wl->ieee_stats.dot11RTSSuccessCount++;
61475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	}
61575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
61675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (b43legacy_using_pio(dev))
61775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacy_pio_handle_txstatus(dev, status);
61875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	else
61975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacy_dma_handle_txstatus(dev, status);
62075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
62175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
62275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Handle TX status report as received through DMA/PIO queues */
62375388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev,
62475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger				 const struct b43legacy_hwtxstatus *hw)
62575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
62675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	struct b43legacy_txstatus status;
62775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	u8 tmp;
62875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
62975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.cookie = le16_to_cpu(hw->cookie);
63075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.seq = le16_to_cpu(hw->seq);
63175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.phy_stat = hw->phy_stat;
63275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	tmp = hw->count;
63375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.frame_count = (tmp >> 4);
63475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.rts_count = (tmp & 0x0F);
635c6a2afdacccd56cc0be8e9a7977f0ed1509069f6Larry Finger	tmp = hw->flags << 1;
63675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.supp_reason = ((tmp & 0x1C) >> 2);
63775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.pm_indicated = !!(tmp & 0x80);
63875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.intermediate = !!(tmp & 0x40);
63975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.for_ampdu = !!(tmp & 0x20);
64075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	status.acked = !!(tmp & 0x02);
64175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
64275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	b43legacy_handle_txstatus(dev, &status);
64375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
64475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
64575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Stop any TX operation on the device (suspend the hardware queues) */
64675388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_tx_suspend(struct b43legacy_wldev *dev)
64775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
64875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (b43legacy_using_pio(dev))
64975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacy_pio_freeze_txqueues(dev);
65075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	else
65175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacy_dma_tx_suspend(dev);
65275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
65375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
65475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Resume any TX operation on the device (resume the hardware queues) */
65575388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_tx_resume(struct b43legacy_wldev *dev)
65675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
65775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	if (b43legacy_using_pio(dev))
65875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacy_pio_thaw_txqueues(dev);
65975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	else
66075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger		b43legacy_dma_tx_resume(dev);
66175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
66275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
66375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Initialize the QoS parameters */
66475388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_qos_init(struct b43legacy_wldev *dev)
66575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{
66675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* FIXME: This function must probably be called from the mac80211
66775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	 * config callback. */
66875388acd0cd827dc1498043daa7d1c760902cd67Larry Fingerreturn;
66975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
67075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	b43legacy_hf_write(dev, b43legacy_hf_read(dev) | B43legacy_HF_EDCF);
67175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/* FIXME kill magic */
67275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	b43legacy_write16(dev, 0x688,
67375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger			  b43legacy_read16(dev, 0x688) | 0x4);
67475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
67575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger
67675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger	/*TODO: We might need some stack support here to get the values. */
67775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger}
678