xmit.c revision 870abdf67170daa9f1022e55a35c469239fcc74c
1e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* 2e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 3e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Broadcom B43 wireless driver 4e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 5e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Transmission (TX/RX) related functions. 6e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 7e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005 Martin Langer <martin-langer@gmx.de> 81f21ad2a4f7f66855dae600ddd635ff5fb299bbdStefano Brivio Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it> 9e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de> 10e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org> 11e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> 12e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 13e4d6b7951812d98417feb10784e400e253caf633Michael Buesch This program is free software; you can redistribute it and/or modify 14e4d6b7951812d98417feb10784e400e253caf633Michael Buesch it under the terms of the GNU General Public License as published by 15e4d6b7951812d98417feb10784e400e253caf633Michael Buesch the Free Software Foundation; either version 2 of the License, or 16e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (at your option) any later version. 17e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 18e4d6b7951812d98417feb10784e400e253caf633Michael Buesch This program is distributed in the hope that it will be useful, 19e4d6b7951812d98417feb10784e400e253caf633Michael Buesch but WITHOUT ANY WARRANTY; without even the implied warranty of 20e4d6b7951812d98417feb10784e400e253caf633Michael Buesch MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21e4d6b7951812d98417feb10784e400e253caf633Michael Buesch GNU General Public License for more details. 22e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 23e4d6b7951812d98417feb10784e400e253caf633Michael Buesch You should have received a copy of the GNU General Public License 24e4d6b7951812d98417feb10784e400e253caf633Michael Buesch along with this program; see the file COPYING. If not, write to 25e4d6b7951812d98417feb10784e400e253caf633Michael Buesch the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 26e4d6b7951812d98417feb10784e400e253caf633Michael Buesch Boston, MA 02110-1301, USA. 27e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 28e4d6b7951812d98417feb10784e400e253caf633Michael Buesch*/ 29e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 30e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "xmit.h" 31ef1a628d83fc0423c36e773281162be790503168Michael Buesch#include "phy_common.h" 32e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#include "dma.h" 335100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch#include "pio.h" 3403b29773b613f10d2f97dbf0983f1c4c58507967Michael Buesch 35e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 368318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of a CCK PLCP header. */ 378318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) 38e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 39e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (plcp->raw[0]) { 40e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x0A: 418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return 0; 42e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x14: 438318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return 1; 44e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x37: 458318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return 2; 46e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x6E: 478318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return 3; 48e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 49e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 508318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return -1; 51e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 52e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 538318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of an OFDM PLCP header. */ 548318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Bergstatic u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) 55e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 568318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg int base = aphy ? 0 : 4; 578318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 58e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (plcp->raw[0] & 0xF) { 59e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xB: 608318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 0; 61e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xF: 628318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 1; 63e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xA: 648318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 2; 65e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xE: 668318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 3; 67e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x9: 688318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 4; 69e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xD: 708318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 5; 71e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x8: 728318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 6; 73e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xC: 748318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 7; 75e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 76e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 778318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return -1; 78e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 79e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 80e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_cck(const u8 bitrate) 81e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 82e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 83e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_1MB: 84e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x0A; 85e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_2MB: 86e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x14; 87e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_5MB: 88e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x37; 89e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_11MB: 90e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x6E; 91e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 92e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 93e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 94e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 95e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 96e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_ofdm(const u8 bitrate) 97e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 98e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 99e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_6MB: 100e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xB; 101e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_9MB: 102e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xF; 103e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_12MB: 104e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xA; 105e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_18MB: 106e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xE; 107e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_24MB: 108e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x9; 109e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_36MB: 110e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xD; 111e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_48MB: 112e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x8; 113e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_54MB: 114e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xC; 115e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 116e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 117e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 118e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 119e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 120e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, 121e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const u16 octets, const u8 bitrate) 122e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 123e4d6b7951812d98417feb10784e400e253caf633Michael Buesch __le32 *data = &(plcp->data); 124e4d6b7951812d98417feb10784e400e253caf633Michael Buesch __u8 *raw = plcp->raw; 125e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 126e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_is_ofdm_rate(bitrate)) { 1271a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch u32 d; 1281a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch 1291a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch d = b43_plcp_get_ratecode_ofdm(bitrate); 130e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(octets & 0xF000); 1311a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch d |= (octets << 5); 1321a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch *data = cpu_to_le32(d); 133e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 134e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 plen; 135e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 136e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plen = octets * 16 / bitrate; 137e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((octets * 16 % bitrate) > 0) { 138e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plen++; 139e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((bitrate == B43_CCK_RATE_11MB) 140e4d6b7951812d98417feb10784e400e253caf633Michael Buesch && ((octets * 8 % 11) < 4)) { 141e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x84; 142e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 143e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x04; 144e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 145e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x04; 146e4d6b7951812d98417feb10784e400e253caf633Michael Buesch *data |= cpu_to_le32(plen << 16); 147e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[0] = b43_plcp_get_ratecode_cck(bitrate); 148e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 149e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 150e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 151e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_calc_fallback_rate(u8 bitrate) 152e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 153e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 154e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_1MB: 155e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_1MB; 156e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_2MB: 157e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_1MB; 158e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_5MB: 159e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_2MB; 160e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_11MB: 161e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_5MB; 162e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_6MB: 163e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_5MB; 164e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_9MB: 165e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_6MB; 166e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_12MB: 167e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_9MB; 168e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_18MB: 169e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_12MB; 170e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_24MB: 171e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_18MB; 172e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_36MB: 173e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_24MB; 174e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_48MB: 175e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_36MB; 176e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_54MB: 177e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_48MB; 178e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 179e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 180e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 181e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 182e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 183eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch/* Generate a TX data header. */ 18409552ccd8277e6382097e93a40f7311a09449367Michael Bueschint b43_generate_txhdr(struct b43_wldev *dev, 18509552ccd8277e6382097e93a40f7311a09449367Michael Buesch u8 *_txhdr, 18609552ccd8277e6382097e93a40f7311a09449367Michael Buesch const unsigned char *fragment_data, 18709552ccd8277e6382097e93a40f7311a09449367Michael Buesch unsigned int fragment_len, 188e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg const struct ieee80211_tx_info *info, 18909552ccd8277e6382097e93a40f7311a09449367Michael Buesch u16 cookie) 190e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 191eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; 192e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_phy *phy = &dev->phy; 193e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct ieee80211_hdr *wlhdr = 194e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (const struct ieee80211_hdr *)fragment_data; 195d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg int use_encryption = !!info->control.hw_key; 196f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison __le16 fctl = wlhdr->frame_control; 1978318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_rate *fbrate; 198e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 rate, rate_fb; 199e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rate_ofdm, rate_fb_ofdm; 200e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int plcp_fragment_len; 201e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 mac_ctl = 0; 202e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 phy_ctl = 0; 203e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 extra_ft = 0; 2042e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg struct ieee80211_rate *txrate; 205e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 206e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memset(txhdr, 0, sizeof(*txhdr)); 207e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 208e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg txrate = ieee80211_get_tx_rate(dev->wl->hw, info); 2092e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; 210e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rate_ofdm = b43_is_ofdm_rate(rate); 211870abdf67170daa9f1022e55a35c469239fcc74cFelix Fietkau fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate; 2128318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg rate_fb = fbrate->hw_value; 213e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); 214e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 215e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_ofdm) 216e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate); 217e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 218e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate); 219e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->mac_frame_ctl = wlhdr->frame_control; 220e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); 221e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 222e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Calculate duration for fallback rate */ 223e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((rate_fb == rate) || 224e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (wlhdr->duration_id & cpu_to_le16(0x8000)) || 225e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (wlhdr->duration_id == cpu_to_le16(0))) { 226e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* If the fallback rate equals the normal rate or the 227e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * dur_id field contains an AID, CFP magic or 0, 228e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * use the original dur_id field. */ 229e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->dur_fb = wlhdr->duration_id; 230e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 231e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg txhdr->dur_fb = ieee80211_generic_frame_duration( 232e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg dev->wl->hw, info->control.vif, fragment_len, fbrate); 233e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 234e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 235e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp_fragment_len = fragment_len + FCS_LEN; 236e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (use_encryption) { 237e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg u8 key_idx = info->control.hw_key->hw_key_idx; 238e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_key *key; 239e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int wlhdr_len; 240e4d6b7951812d98417feb10784e400e253caf633Michael Buesch size_t iv_len; 241e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 242e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(key_idx >= dev->max_nr_keys); 243e4d6b7951812d98417feb10784e400e253caf633Michael Buesch key = &(dev->key[key_idx]); 2447be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch 24509552ccd8277e6382097e93a40f7311a09449367Michael Buesch if (unlikely(!key->keyconf)) { 24609552ccd8277e6382097e93a40f7311a09449367Michael Buesch /* This key is invalid. This might only happen 24709552ccd8277e6382097e93a40f7311a09449367Michael Buesch * in a short timeframe after machine resume before 24809552ccd8277e6382097e93a40f7311a09449367Michael Buesch * we were able to reconfigure keys. 24909552ccd8277e6382097e93a40f7311a09449367Michael Buesch * Drop this packet completely. Do not transmit it 25009552ccd8277e6382097e93a40f7311a09449367Michael Buesch * unencrypted to avoid leaking information. */ 25109552ccd8277e6382097e93a40f7311a09449367Michael Buesch return -ENOKEY; 2527be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch } 25309552ccd8277e6382097e93a40f7311a09449367Michael Buesch 25409552ccd8277e6382097e93a40f7311a09449367Michael Buesch /* Hardware appends ICV. */ 25576708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau plcp_fragment_len += info->control.hw_key->icv_len; 25609552ccd8277e6382097e93a40f7311a09449367Michael Buesch 25709552ccd8277e6382097e93a40f7311a09449367Michael Buesch key_idx = b43_kidx_to_fw(dev, key_idx); 25809552ccd8277e6382097e93a40f7311a09449367Michael Buesch mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & 25909552ccd8277e6382097e93a40f7311a09449367Michael Buesch B43_TXH_MAC_KEYIDX; 26009552ccd8277e6382097e93a40f7311a09449367Michael Buesch mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & 26109552ccd8277e6382097e93a40f7311a09449367Michael Buesch B43_TXH_MAC_KEYALG; 262f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison wlhdr_len = ieee80211_hdrlen(fctl); 26376708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau iv_len = min((size_t) info->control.hw_key->iv_len, 26409552ccd8277e6382097e93a40f7311a09449367Michael Buesch ARRAY_SIZE(txhdr->iv)); 26509552ccd8277e6382097e93a40f7311a09449367Michael Buesch memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); 266e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 267eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) { 268eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), 269eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp_fragment_len, rate); 270eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 271eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), 272eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp_fragment_len, rate); 273eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 274e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), 275e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp_fragment_len, rate_fb); 276e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 277e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Extra Frame Types */ 278e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_fb_ofdm) 279eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_FB_OFDM; 280eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 281eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_FB_CCK; 282e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 283e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Set channel radio code. Note that the micrcode ORs 0x100 to 284e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * this value before comparing it to the value in SHM, if this 285e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * is a 5Ghz packet. 286e4d6b7951812d98417feb10784e400e253caf633Michael Buesch */ 287e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->chan_radio_code = phy->channel; 288e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 289e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* PHY TX Control word */ 290e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_ofdm) 291eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ENC_OFDM; 292eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 293eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ENC_CCK; 294e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) 295eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_SHORTPRMBL; 2969db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch 297e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { 2989db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch case 0: /* Default */ 299eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT01AUTO; 300e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 3019db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch case 1: /* Antenna 0 */ 302eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT0; 303e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 3049db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch case 2: /* Antenna 1 */ 305eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT1; 306eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch break; 307eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch case 3: /* Antenna 2 */ 308eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT2; 309eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch break; 310eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch case 4: /* Antenna 3 */ 311eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT3; 312e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 313e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 314e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 315e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 316e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 317e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* MAC control */ 318e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) 319eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_ACK; 320f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg /* use hardware sequence counter as the non-TID counter */ 321f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) 322eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_HWSEQ; 323e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) 324eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_STMSDU; 325e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_A) 326eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_5GHZ; 327e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) 328eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_LONGFRAME; 329e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 330e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Generate the RTS or CTS-to-self frame */ 331e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || 332e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { 333e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int len; 334e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_hdr *hdr; 335e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rts_rate, rts_rate_fb; 336e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rts_rate_ofdm, rts_rate_fb_ofdm; 337eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch struct b43_plcp_hdr6 *plcp; 3382e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg struct ieee80211_rate *rts_cts_rate; 339e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 340e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); 3412e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg 3422e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB; 343e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); 344e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_fb = b43_calc_fallback_rate(rts_rate); 345e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); 346e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 347e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { 348eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch struct ieee80211_cts *cts; 349eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 350eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) { 351eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch cts = (struct ieee80211_cts *) 352eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (txhdr->old_format.rts_frame); 353eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 354eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch cts = (struct ieee80211_cts *) 355eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (txhdr->new_format.rts_frame); 356eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 357e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, 358e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_data, fragment_len, 359e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info, cts); 360eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_SENDCTS; 361e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len = sizeof(struct ieee80211_cts); 362e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 363eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch struct ieee80211_rts *rts; 364eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 365eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) { 366eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch rts = (struct ieee80211_rts *) 367eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (txhdr->old_format.rts_frame); 368eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 369eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch rts = (struct ieee80211_rts *) 370eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (txhdr->new_format.rts_frame); 371eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 372e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_rts_get(dev->wl->hw, info->control.vif, 373eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch fragment_data, fragment_len, 374e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info, rts); 375eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_SENDRTS; 376e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len = sizeof(struct ieee80211_rts); 377e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 378e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len += FCS_LEN; 379eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 380eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch /* Generate the PLCP headers for the RTS/CTS frame */ 381eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) 382eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp = &txhdr->old_format.rts_plcp; 383eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 384eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp = &txhdr->new_format.rts_plcp; 385eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, 386eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch len, rts_rate); 387eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp = &txhdr->rts_plcp_fb; 388eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, 389e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len, rts_rate_fb); 390eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 391eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) { 392eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch hdr = (struct ieee80211_hdr *) 393eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (&txhdr->old_format.rts_frame); 394eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 395eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch hdr = (struct ieee80211_hdr *) 396eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (&txhdr->new_format.rts_frame); 397eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 398e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->rts_dur_fb = hdr->duration_id; 399eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 400e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rts_rate_ofdm) { 401eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_RTS_OFDM; 402e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate_rts = 403e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_plcp_get_ratecode_ofdm(rts_rate); 404eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 405eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_RTS_CCK; 406e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate_rts = 407e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_plcp_get_ratecode_cck(rts_rate); 408eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 409e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rts_rate_fb_ofdm) 410eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_RTSFB_OFDM; 411eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 412eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_RTSFB_CCK; 413e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 414e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 415e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Magic cookie */ 416eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) 417eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch txhdr->old_format.cookie = cpu_to_le16(cookie); 418eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 419eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch txhdr->new_format.cookie = cpu_to_le16(cookie); 420e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 421e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Apply the bitfields */ 422e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->mac_ctl = cpu_to_le32(mac_ctl); 423e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_ctl = cpu_to_le16(phy_ctl); 424e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->extra_ft = extra_ft; 425e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 42609552ccd8277e6382097e93a40f7311a09449367Michael Buesch return 0; 427e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 428e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 429e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev, 430e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 in_rssi, int ofdm, 431e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int adjust_2053, int adjust_2050) 432e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 433e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_phy *phy = &dev->phy; 434ef1a628d83fc0423c36e773281162be790503168Michael Buesch struct b43_phy_g *gphy = phy->g; 435e4d6b7951812d98417feb10784e400e253caf633Michael Buesch s32 tmp; 436e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 437e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (phy->radio_ver) { 438e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x2050: 439e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (ofdm) { 440e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 441e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (tmp > 127) 442e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 256; 443e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= 73; 444e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 64; 445e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (adjust_2050) 446e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp += 25; 447e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 448e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 3; 449e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 45095de2841aad971867851b59c0c5253ecc2e19832Larry Finger if (dev->dev->bus->sprom. 451e4d6b7951812d98417feb10784e400e253caf633Michael Buesch boardflags_lo & B43_BFL_RSSI) { 452e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (in_rssi > 63) 453e4d6b7951812d98417feb10784e400e253caf633Michael Buesch in_rssi = 63; 454ef1a628d83fc0423c36e773281162be790503168Michael Buesch B43_WARN_ON(phy->type != B43_PHYTYPE_G); 455ef1a628d83fc0423c36e773281162be790503168Michael Buesch tmp = gphy->nrssi_lt[in_rssi]; 456e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = 31 - tmp; 457e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= -131; 458e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 128; 459e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 57; 460e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 461e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = 31 - tmp; 463e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= -149; 464e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 128; 465e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 68; 466e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 467e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_G && adjust_2050) 468e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp += 25; 469e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 470e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 471e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x2060: 472e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (in_rssi > 127) 473e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi - 256; 474e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 475e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 476e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 477e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 478e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 479e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 11; 480e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= 103; 481e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 64; 482e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (adjust_2053) 483e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 109; 484e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 485e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 83; 486e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return (s8) tmp; 489e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 490e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 491e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO 492e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0 493e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi) 494e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 495e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_phy *phy = &dev->phy; 496e4d6b7951812d98417feb10784e400e253caf633Michael Buesch s8 ret; 497e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 498e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_A) { 499e4d6b7951812d98417feb10784e400e253caf633Michael Buesch //TODO: Incomplete specs. 500e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ret = 0; 501e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 502e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1); 503e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 504e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return ret; 505e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 506e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif 507e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 508e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) 509e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 510e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_rx_status status; 511e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_plcp_hdr6 *plcp; 512e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_hdr *wlhdr; 513e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; 514f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison __le16 fctl; 515e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 phystat0, phystat3, chanstat, mactime; 516e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 macstat; 517e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 chanid; 5188318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg u16 phytype; 519e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int padding; 520e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 521e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memset(&status, 0, sizeof(status)); 522e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 523e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Get metadata about the frame from the header. */ 524e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phystat0 = le16_to_cpu(rxhdr->phy_status0); 525e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phystat3 = le16_to_cpu(rxhdr->phy_status3); 526e4d6b7951812d98417feb10784e400e253caf633Michael Buesch macstat = le32_to_cpu(rxhdr->mac_status); 527e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mactime = le16_to_cpu(rxhdr->mac_time); 528e4d6b7951812d98417feb10784e400e253caf633Michael Buesch chanstat = le16_to_cpu(rxhdr->channel); 5298318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg phytype = chanstat & B43_RX_CHAN_PHYTYPE; 530e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 531e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_FCSERR) 532e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11FCSErrorCount++; 533e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_DECERR) { 534e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Decryption with the given key failed. 535e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * Drop the packet. We also won't be able to decrypt it with 536e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * the key in software. */ 537e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 538e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 539e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 540e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Skip PLCP and padding */ 541e4d6b7951812d98417feb10784e400e253caf633Michael Buesch padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0; 542e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) { 543e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet size underrun (1)\n"); 544e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 545e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 546e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp = (struct b43_plcp_hdr6 *)(skb->data + padding); 547e4d6b7951812d98417feb10784e400e253caf633Michael Buesch skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding); 548e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* The skb contains the Wireless Header + payload data now */ 549e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */ + FCS_LEN))) { 550e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet size underrun (2)\n"); 551e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 552e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 553e4d6b7951812d98417feb10784e400e253caf633Michael Buesch wlhdr = (struct ieee80211_hdr *)(skb->data); 554f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison fctl = wlhdr->frame_control; 555e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 556e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_DEC) { 557e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int keyidx; 558e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int wlhdr_len; 559e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 560e4d6b7951812d98417feb10784e400e253caf633Michael Buesch keyidx = ((macstat & B43_RX_MAC_KEYIDX) 561e4d6b7951812d98417feb10784e400e253caf633Michael Buesch >> B43_RX_MAC_KEYIDX_SHIFT); 562e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* We must adjust the key index here. We want the "physical" 563e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * key index, but the ucode passed it slightly different. 564e4d6b7951812d98417feb10784e400e253caf633Michael Buesch */ 565e4d6b7951812d98417feb10784e400e253caf633Michael Buesch keyidx = b43_kidx_to_raw(dev, keyidx); 566e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(keyidx >= dev->max_nr_keys); 567e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 568e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { 569f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison wlhdr_len = ieee80211_hdrlen(fctl); 570e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (wlhdr_len + 3))) { 571e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, 572e4d6b7951812d98417feb10784e400e253caf633Michael Buesch "RX: Packet size underrun (3)\n"); 573e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.flag |= RX_FLAG_DECRYPTED; 576e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 578e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 5797b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch /* Link quality statistics */ 580e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.noise = dev->stats.link_noise; 5817b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) { 5827b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch// s8 rssi = max(rxhdr->power0, rxhdr->power1); 5837b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch //TODO: Find out what the rssi value is (dBm or percentage?) 5847b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch // and also find out what the maximum possible value is. 5857b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch // Fill status.ssi and status.signal fields. 5867b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch } else { 587566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf status.signal = b43_rssi_postprocess(dev, rxhdr->jssi, 5887b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch (phystat0 & B43_RX_PHYST0_OFDM), 5897b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch (phystat0 & B43_RX_PHYST0_GAINCTL), 5907b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch (phystat3 & B43_RX_PHYST3_TRSTATE)); 591566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI; 5927b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch } 5937b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch 594e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phystat0 & B43_RX_PHYST0_OFDM) 5958318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, 5968318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg phytype == B43_PHYTYPE_A); 597e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 5988318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); 599e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); 600c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville 601c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville /* 602d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * All frames on monitor interfaces and beacons always need a full 603d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * 64-bit timestamp. Monitor interfaces need it for diagnostic 604d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * purposes and beacons for IBSS merging. 605d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * This code assumes we get to process the packet within 16 bits 606d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * of timestamp, i.e. about 65 milliseconds after the PHY received 607d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * the first symbol. 608c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville */ 609f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { 610c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville u16 low_mactime_now; 611c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville 612c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville b43_tsf_read(dev, &status.mactime); 613c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville low_mactime_now = status.mactime; 614c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime = status.mactime & ~0xFFFFULL; 615c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime += mactime; 616c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville if (low_mactime_now <= mactime) 617c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime -= 0x10000; 618c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.flag |= RX_FLAG_TSFT; 619c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville } 620e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 621e4d6b7951812d98417feb10784e400e253caf633Michael Buesch chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; 622e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (chanstat & B43_RX_CHAN_PHYTYPE) { 623e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_PHYTYPE_A: 6248318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_5GHZ; 625d987160b710c98997015832422a05e18d9f0f925Michael Buesch B43_WARN_ON(1); 626d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* FIXME: We don't really know which value the "chanid" contains. 627d987160b710c98997015832422a05e18d9f0f925Michael Buesch * So the following assignment might be wrong. */ 6288318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.freq = b43_channel_to_freq_5ghz(chanid); 629e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 630e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_PHYTYPE_G: 6318318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_2GHZ; 632d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* chanid is the radio channel cookie value as used 633d987160b710c98997015832422a05e18d9f0f925Michael Buesch * to tune the radio. */ 634e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.freq = chanid + 2400; 635d987160b710c98997015832422a05e18d9f0f925Michael Buesch break; 636d987160b710c98997015832422a05e18d9f0f925Michael Buesch case B43_PHYTYPE_N: 637d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* chanid is the SHM channel cookie. Which is the plain 638d987160b710c98997015832422a05e18d9f0f925Michael Buesch * channel number in b43. */ 6398318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (chanstat & B43_RX_CHAN_5GHZ) { 6408318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_5GHZ; 6418318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.freq = b43_freq_to_channel_5ghz(chanid); 6428318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } else { 6438318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_2GHZ; 6448318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.freq = b43_freq_to_channel_2ghz(chanid); 6458318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 646e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 647e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 648e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 649d987160b710c98997015832422a05e18d9f0f925Michael Buesch goto drop; 650e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 651e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 652e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->stats.last_rx = jiffies; 653e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ieee80211_rx_irqsafe(dev->wl->hw, skb, &status); 654e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 655e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 656e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop: 657e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet dropped\n"); 658e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev_kfree_skb_any(skb); 659e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 660e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 661e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev, 662e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_txstatus *status) 663e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 664e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_debugfs_log_txstat(dev, status); 665e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 666e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->intermediate) 667e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 668e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->for_ampdu) 669e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 670e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (!status->acked) 671e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11ACKFailureCount++; 672e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->rts_count) { 673e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->rts_count == 0xF) //FIXME 674e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11RTSFailureCount++; 675e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 676e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11RTSSuccessCount++; 677e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 678e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 6795100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (b43_using_pio_transfers(dev)) 6805100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_pio_handle_txstatus(dev, status); 6815100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch else 6825100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_dma_handle_txstatus(dev, status); 68318c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch 68418c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch b43_phy_txpower_check(dev, 0); 685e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 686e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 6875100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch/* Fill out the mac80211 TXstatus report based on the b43-specific 6885100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * txstatus report data. This returns a boolean whether the frame was 6895100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * successfully transmitted. */ 690e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Bergbool b43_fill_txstatus_report(struct ieee80211_tx_info *report, 6915100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch const struct b43_txstatus *status) 692e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 6935100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch bool frame_success = 1; 6945100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch 6955100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (status->acked) { 6965100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch /* The frame was ACKed. */ 697e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg report->flags |= IEEE80211_TX_STAT_ACK; 6985100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch } else { 6995100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch /* The frame was not ACKed... */ 700e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { 7015100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch /* ...but we expected an ACK. */ 7025100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch frame_success = 0; 703e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg report->status.excessive_retries = 1; 7045100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch } 7055100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch } 7065100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (status->frame_count == 0) { 7075100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch /* The frame was not transmitted at all. */ 708e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg report->status.retry_count = 0; 7095100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch } else 710e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg report->status.retry_count = status->frame_count - 1; 7115100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch 7125100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch return frame_success; 713e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 714e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 715e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */ 716e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev) 717e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 7185100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (b43_using_pio_transfers(dev)) 7195100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_pio_tx_suspend(dev); 7205100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch else 7215100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_dma_tx_suspend(dev); 722e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 723e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 724e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */ 725e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev) 726e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 7275100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (b43_using_pio_transfers(dev)) 7285100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_pio_tx_resume(dev); 7295100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch else 7305100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_dma_tx_resume(dev); 731e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 732