xmit.c revision 76708dee382a69b2f9d0e50f413f99fefb2dc509
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> 975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de> 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, 191e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg const 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; 20475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 20575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger wlhdr = (const struct ieee80211_hdr *)fragment_data; 20675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 20775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger memset(txhdr, 0, sizeof(*txhdr)); 20875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 209e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg tx_rate = ieee80211_get_tx_rate(dev->wl->hw, info); 2102e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg 2112e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg rate = tx_rate->hw_value; 21275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger rate_ofdm = b43legacy_is_ofdm_rate(rate); 213e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : tx_rate; 2148318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); 21575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 21675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger txhdr->mac_frame_ctl = wlhdr->frame_control; 21775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); 21875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 21975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Calculate duration for fallback rate */ 2208318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if ((rate_fb->hw_value == rate) || 22175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (wlhdr->duration_id & cpu_to_le16(0x8000)) || 22275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (wlhdr->duration_id == cpu_to_le16(0))) { 22375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* If the fallback rate equals the normal rate or the 22475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger * dur_id field contains an AID, CFP magic or 0, 22575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger * use the original dur_id field. */ 22675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger txhdr->dur_fb = wlhdr->duration_id; 22775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } else { 22875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, 229e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info->control.vif, 23075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger fragment_len, 2318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg rate_fb); 23275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 23375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 23475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger plcp_fragment_len = fragment_len + FCS_LEN; 23575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (use_encryption) { 236e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg u8 key_idx = info->control.hw_key->hw_key_idx; 23775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger struct b43legacy_key *key; 23875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int wlhdr_len; 23975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger size_t iv_len; 24075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 24175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger B43legacy_WARN_ON(key_idx >= dev->max_nr_keys); 24275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger key = &(dev->key[key_idx]); 24375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 24475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (key->enabled) { 24575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Hardware appends ICV. */ 24676708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau plcp_fragment_len += info->control.hw_key->icv_len; 24775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 24875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger key_idx = b43legacy_kidx_to_fw(dev, key_idx); 24975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) & 25075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger B43legacy_TX4_MAC_KEYIDX; 25175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= (key->algorithm << 25275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger B43legacy_TX4_MAC_KEYALG_SHIFT) & 25375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger B43legacy_TX4_MAC_KEYALG; 254ba5b6efe5d945f7a4c5b656051cc16698afdda24Harvey Harrison wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control); 25576708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau iv_len = min((size_t)info->control.hw_key->iv_len, 25675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger ARRAY_SIZE(txhdr->iv)); 25775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); 2589eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio } else { 2599eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio /* This key is invalid. This might only happen 2609eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio * in a short timeframe after machine resume before 2619eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio * we were able to reconfigure keys. 2629eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio * Drop this packet completely. Do not transmit it 2639eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio * unencrypted to avoid leaking information. */ 2649eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio return -ENOKEY; 26575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 26675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 26775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) 26875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (&txhdr->plcp), plcp_fragment_len, 26975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger rate); 27075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) 27175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (&txhdr->plcp_fb), plcp_fragment_len, 2728318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg rate_fb->hw_value); 27375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 27475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* PHY TX Control word */ 27575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (rate_ofdm) 27675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger phy_ctl |= B43legacy_TX4_PHY_OFDM; 27775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (dev->short_preamble) 27875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; 279e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg switch (info->antenna_sel_tx) { 28075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger case 0: 28175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger phy_ctl |= B43legacy_TX4_PHY_ANTLAST; 28275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger break; 28375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger case 1: 28475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger phy_ctl |= B43legacy_TX4_PHY_ANT0; 28575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger break; 28675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger case 2: 28775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger phy_ctl |= B43legacy_TX4_PHY_ANT1; 28875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger break; 28975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger default: 29075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger B43legacy_BUG_ON(1); 29175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 29275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 29375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* MAC control */ 294e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) 29575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= B43legacy_TX4_MAC_ACK; 296f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) 29775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= B43legacy_TX4_MAC_HWSEQ; 298e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) 29975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= B43legacy_TX4_MAC_STMSDU; 30075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (rate_fb_ofdm) 30175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM; 302e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) 3030a6e1bee5770a6d4c4569a4720614402ab5f9d7aStefano Brivio mac_ctl |= B43legacy_TX4_MAC_LONGFRAME; 30475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 30575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Generate the RTS or CTS-to-self frame */ 306e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || 307e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { 30875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger unsigned int len; 30975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger struct ieee80211_hdr *hdr; 31075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int rts_rate; 31175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int rts_rate_fb; 31275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int rts_rate_ofdm; 31375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int rts_rate_fb_ofdm; 31475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 315e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value; 31675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate); 31775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate); 31875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb); 31975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (rts_rate_fb_ofdm) 32075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM; 32175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 322e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { 32375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger ieee80211_ctstoself_get(dev->wl->hw, 324e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info->control.vif, 32575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger fragment_data, 326e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg fragment_len, info, 32775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (struct ieee80211_cts *) 32875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (txhdr->rts_frame)); 32975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= B43legacy_TX4_MAC_SENDCTS; 33075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger len = sizeof(struct ieee80211_cts); 33175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } else { 33275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger ieee80211_rts_get(dev->wl->hw, 333e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info->control.vif, 334e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg fragment_data, fragment_len, info, 33575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (struct ieee80211_rts *) 33675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (txhdr->rts_frame)); 33775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mac_ctl |= B43legacy_TX4_MAC_SENDRTS; 33875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger len = sizeof(struct ieee80211_rts); 33975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 34075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger len += FCS_LEN; 34175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) 34275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (&txhdr->rts_plcp), 34375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger len, rts_rate); 34475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) 34575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (&txhdr->rts_plcp_fb), 34675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger len, rts_rate_fb); 34775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame); 34875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger txhdr->rts_dur_fb = hdr->duration_id; 34975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 35075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 35175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Magic cookie */ 35275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger txhdr->cookie = cpu_to_le16(cookie); 35375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 35475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Apply the bitfields */ 35575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger txhdr->mac_ctl = cpu_to_le32(mac_ctl); 35675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger txhdr->phy_ctl = cpu_to_le16(phy_ctl); 3579eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio 3589eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio return 0; 35975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 36075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 3619eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivioint b43legacy_generate_txhdr(struct b43legacy_wldev *dev, 36275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u8 *txhdr, 36375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger const unsigned char *fragment_data, 36475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger unsigned int fragment_len, 365e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg const struct ieee80211_tx_info *info, 36675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u16 cookie) 36775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{ 3689eca9a8e81928685b4de00ecef83a7c13c340fc9Stefano Brivio return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, 36975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger fragment_data, fragment_len, 370e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info, cookie); 37175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 37275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 37375388acd0cd827dc1498043daa7d1c760902cd67Larry Fingerstatic s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev, 37475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u8 in_rssi, int ofdm, 37575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int adjust_2053, int adjust_2050) 37675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{ 37775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger struct b43legacy_phy *phy = &dev->phy; 37875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger s32 tmp; 37975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 38075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger switch (phy->radio_ver) { 38175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger case 0x2050: 38275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (ofdm) { 38375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = in_rssi; 38475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (tmp > 127) 38575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp -= 256; 38675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp *= 73; 38775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp /= 64; 38875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (adjust_2050) 38975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp += 25; 39075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger else 39175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp -= 3; 39275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } else { 3937797aa384870e3bb5bfd3b6a0eae61e7c7a4c993Larry Finger if (dev->dev->bus->sprom.boardflags_lo 39475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger & B43legacy_BFL_RSSI) { 39575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (in_rssi > 63) 39675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger in_rssi = 63; 39775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = phy->nrssi_lt[in_rssi]; 39875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = 31 - tmp; 39975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp *= -131; 40075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp /= 128; 40175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp -= 57; 40275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } else { 40375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = in_rssi; 40475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = 31 - tmp; 40575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp *= -149; 40675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp /= 128; 40775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp -= 68; 40875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 40975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (phy->type == B43legacy_PHYTYPE_G && 41075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger adjust_2050) 41175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp += 25; 41275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 41375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger break; 41475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger case 0x2060: 41575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (in_rssi > 127) 41675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = in_rssi - 256; 41775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger else 41875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = in_rssi; 41975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger break; 42075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger default: 42175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = in_rssi; 42275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp -= 11; 42375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp *= 103; 42475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp /= 64; 42575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (adjust_2053) 42675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp -= 109; 42775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger else 42875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp -= 83; 42975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 43075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 43175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger return (s8)tmp; 43275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 43375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 43475388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_rx(struct b43legacy_wldev *dev, 43575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger struct sk_buff *skb, 43675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger const void *_rxhdr) 43775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{ 43875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger struct ieee80211_rx_status status; 43975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger struct b43legacy_plcp_hdr6 *plcp; 44075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger struct ieee80211_hdr *wlhdr; 44175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr; 442b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison __le16 fctl; 44375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u16 phystat0; 44475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u16 phystat3; 44575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u16 chanstat; 44675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u16 mactime; 44775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u32 macstat; 44875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u16 chanid; 44975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u8 jssi; 45075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int padding; 45175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 45275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger memset(&status, 0, sizeof(status)); 45375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 45475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Get metadata about the frame from the header. */ 45575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger phystat0 = le16_to_cpu(rxhdr->phy_status0); 45675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger phystat3 = le16_to_cpu(rxhdr->phy_status3); 45775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger jssi = rxhdr->jssi; 45875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger macstat = le16_to_cpu(rxhdr->mac_status); 45975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger mactime = le16_to_cpu(rxhdr->mac_time); 46075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger chanstat = le16_to_cpu(rxhdr->channel); 46175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 46275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (macstat & B43legacy_RX_MAC_FCSERR) 46375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger dev->wl->ieee_stats.dot11FCSErrorCount++; 46475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 46575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Skip PLCP and padding */ 46675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger padding = (macstat & B43legacy_RX_MAC_PADDING) ? 2 : 0; 46775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (unlikely(skb->len < (sizeof(struct b43legacy_plcp_hdr6) + 46875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger padding))) { 46975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacydbg(dev->wl, "RX: Packet size underrun (1)\n"); 47075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger goto drop; 47175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 47275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger plcp = (struct b43legacy_plcp_hdr6 *)(skb->data + padding); 47375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger skb_pull(skb, sizeof(struct b43legacy_plcp_hdr6) + padding); 47475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* The skb contains the Wireless Header + payload data now */ 47575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (unlikely(skb->len < (2+2+6/*minimum hdr*/ + FCS_LEN))) { 47675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacydbg(dev->wl, "RX: Packet size underrun (2)\n"); 47775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger goto drop; 47875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 47975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger wlhdr = (struct ieee80211_hdr *)(skb->data); 480b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison fctl = wlhdr->frame_control; 48175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 48275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if ((macstat & B43legacy_RX_MAC_DEC) && 48375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger !(macstat & B43legacy_RX_MAC_DECERR)) { 48475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger unsigned int keyidx; 48575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int wlhdr_len; 48675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int iv_len; 48775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger int icv_len; 48875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 48975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger keyidx = ((macstat & B43legacy_RX_MAC_KEYIDX) 49075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger >> B43legacy_RX_MAC_KEYIDX_SHIFT); 49175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* We must adjust the key index here. We want the "physical" 49275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger * key index, but the ucode passed it slightly different. 49375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger */ 49475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger keyidx = b43legacy_kidx_to_raw(dev, keyidx); 49575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger B43legacy_WARN_ON(keyidx >= dev->max_nr_keys); 49675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 49775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) { 49875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Remove PROTECTED flag to mark it as decrypted. */ 499b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison B43legacy_WARN_ON(!ieee80211_has_protected(fctl)); 500b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison fctl &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED); 501b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison wlhdr->frame_control = fctl; 50275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 503b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison wlhdr_len = ieee80211_hdrlen(fctl); 50475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (unlikely(skb->len < (wlhdr_len + 3))) { 50575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacydbg(dev->wl, "RX: Packet size" 50675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger " underrun3\n"); 50775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger goto drop; 50875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 50975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (skb->data[wlhdr_len + 3] & (1 << 5)) { 51075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* The Ext-IV Bit is set in the "KeyID" 51175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger * octet of the IV. 51275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger */ 51375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger iv_len = 8; 51475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger icv_len = 8; 51575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } else { 51675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger iv_len = 4; 51775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger icv_len = 4; 51875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 51975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (unlikely(skb->len < (wlhdr_len + iv_len + 52075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger icv_len))) { 52175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacydbg(dev->wl, "RX: Packet size" 52275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger " underrun4\n"); 52375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger goto drop; 52475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 52575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Remove the IV */ 52675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger memmove(skb->data + iv_len, skb->data, wlhdr_len); 52775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger skb_pull(skb, iv_len); 52875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* Remove the ICV */ 52975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger skb_trim(skb, skb->len - icv_len); 53075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 53175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.flag |= RX_FLAG_DECRYPTED; 53275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 53375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 53475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 535566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf status.signal = b43legacy_rssi_postprocess(dev, jssi, 53675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (phystat0 & B43legacy_RX_PHYST0_OFDM), 53775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (phystat0 & B43legacy_RX_PHYST0_GAINCTL), 53875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger (phystat3 & B43legacy_RX_PHYST3_TRSTATE)); 53975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.noise = dev->stats.link_noise; 540566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf status.qual = (jssi * 100) / B43legacy_RX_MAX_SSI; 5418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg /* change to support A PHY */ 54275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (phystat0 & B43legacy_RX_PHYST0_OFDM) 5438318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false); 54475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger else 5458318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp); 54675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT); 547c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville 548c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville /* 549d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * All frames on monitor interfaces and beacons always need a full 550d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * 64-bit timestamp. Monitor interfaces need it for diagnostic 551d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * purposes and beacons for IBSS merging. 552d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * This code assumes we get to process the packet within 16 bits 553d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * of timestamp, i.e. about 65 milliseconds after the PHY received 554d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * the first symbol. 555c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville */ 556b99a017c01bb19b58fd0826e36a1bdacf581c545Harvey Harrison if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { 557c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville u16 low_mactime_now; 558c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville 559c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville b43legacy_tsf_read(dev, &status.mactime); 560c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville low_mactime_now = status.mactime; 561c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime = status.mactime & ~0xFFFFULL; 562c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime += mactime; 563c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville if (low_mactime_now <= mactime) 564c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime -= 0x10000; 565c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.flag |= RX_FLAG_TSFT; 566c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville } 56775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 56875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger chanid = (chanstat & B43legacy_RX_CHAN_ID) >> 56975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger B43legacy_RX_CHAN_ID_SHIFT; 57075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) { 57175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger case B43legacy_PHYTYPE_B: 57275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger case B43legacy_PHYTYPE_G: 5738318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_2GHZ; 57475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.freq = chanid + 2400; 57575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger break; 57675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger default: 57775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n", 57875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger chanstat); 57975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 58075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 58175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger dev->stats.last_rx = jiffies; 58275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger ieee80211_rx_irqsafe(dev->wl->hw, skb, &status); 58375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 58475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger return; 58575388acd0cd827dc1498043daa7d1c760902cd67Larry Fingerdrop: 58675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacydbg(dev->wl, "RX: Packet dropped\n"); 58775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger dev_kfree_skb_any(skb); 58875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 58975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 59075388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_handle_txstatus(struct b43legacy_wldev *dev, 59175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger const struct b43legacy_txstatus *status) 59275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{ 59375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_debugfs_log_txstat(dev, status); 59475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 59575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (status->intermediate) 59675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger return; 59775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (status->for_ampdu) 59875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger return; 59975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (!status->acked) 60075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger dev->wl->ieee_stats.dot11ACKFailureCount++; 60175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (status->rts_count) { 60275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (status->rts_count == 0xF) /* FIXME */ 60375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger dev->wl->ieee_stats.dot11RTSFailureCount++; 60475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger else 60575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger dev->wl->ieee_stats.dot11RTSSuccessCount++; 60675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger } 60775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 60875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (b43legacy_using_pio(dev)) 60975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_pio_handle_txstatus(dev, status); 61075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger else 61175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_dma_handle_txstatus(dev, status); 61275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 61375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 61475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Handle TX status report as received through DMA/PIO queues */ 61575388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev, 61675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger const struct b43legacy_hwtxstatus *hw) 61775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{ 61875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger struct b43legacy_txstatus status; 61975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger u8 tmp; 62075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 62175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.cookie = le16_to_cpu(hw->cookie); 62275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.seq = le16_to_cpu(hw->seq); 62375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.phy_stat = hw->phy_stat; 62475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger tmp = hw->count; 62575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.frame_count = (tmp >> 4); 62675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.rts_count = (tmp & 0x0F); 627c6a2afdacccd56cc0be8e9a7977f0ed1509069f6Larry Finger tmp = hw->flags << 1; 62875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.supp_reason = ((tmp & 0x1C) >> 2); 62975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.pm_indicated = !!(tmp & 0x80); 63075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.intermediate = !!(tmp & 0x40); 63175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.for_ampdu = !!(tmp & 0x20); 63275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger status.acked = !!(tmp & 0x02); 63375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 63475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_handle_txstatus(dev, &status); 63575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 63675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 63775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Stop any TX operation on the device (suspend the hardware queues) */ 63875388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_tx_suspend(struct b43legacy_wldev *dev) 63975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{ 64075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (b43legacy_using_pio(dev)) 64175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_pio_freeze_txqueues(dev); 64275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger else 64375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_dma_tx_suspend(dev); 64475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 64575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 64675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Resume any TX operation on the device (resume the hardware queues) */ 64775388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_tx_resume(struct b43legacy_wldev *dev) 64875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{ 64975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger if (b43legacy_using_pio(dev)) 65075388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_pio_thaw_txqueues(dev); 65175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger else 65275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_dma_tx_resume(dev); 65375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 65475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 65575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger/* Initialize the QoS parameters */ 65675388acd0cd827dc1498043daa7d1c760902cd67Larry Fingervoid b43legacy_qos_init(struct b43legacy_wldev *dev) 65775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger{ 65875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* FIXME: This function must probably be called from the mac80211 65975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger * config callback. */ 66075388acd0cd827dc1498043daa7d1c760902cd67Larry Fingerreturn; 66175388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 66275388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_hf_write(dev, b43legacy_hf_read(dev) | B43legacy_HF_EDCF); 66375388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /* FIXME kill magic */ 66475388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_write16(dev, 0x688, 66575388acd0cd827dc1498043daa7d1c760902cd67Larry Finger b43legacy_read16(dev, 0x688) | 0x4); 66675388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 66775388acd0cd827dc1498043daa7d1c760902cd67Larry Finger 66875388acd0cd827dc1498043daa7d1c760902cd67Larry Finger /*TODO: We might need some stack support here to get the values. */ 66975388acd0cd827dc1498043daa7d1c760902cd67Larry Finger} 670