xmit.c revision 66d2d089c394c7e31020947d682523f77a93244b
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 } 498318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return -1; 50e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 51e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 528318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg/* Extract the bitrate index out of an OFDM PLCP header. */ 53a3c0b87c4f21911fb7185902dd13f0e3cd7f33f7Lorenzo Navastatic int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) 54e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 558318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg int base = aphy ? 0 : 4; 568318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg 57e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (plcp->raw[0] & 0xF) { 58e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xB: 598318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 0; 60e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xF: 618318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 1; 62e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xA: 638318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 2; 64e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xE: 658318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 3; 66e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x9: 678318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 4; 68e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xD: 698318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 5; 70e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x8: 718318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 6; 72e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0xC: 738318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return base + 7; 74e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 758318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg return -1; 76e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 77e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 78e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_cck(const u8 bitrate) 79e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 80e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 81e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_1MB: 82e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x0A; 83e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_2MB: 84e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x14; 85e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_5MB: 86e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x37; 87e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_11MB: 88e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x6E; 89e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 90e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 91e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 92e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 93e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 94e4d6b7951812d98417feb10784e400e253caf633Michael Bueschu8 b43_plcp_get_ratecode_ofdm(const u8 bitrate) 95e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 96e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 97e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_6MB: 98e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xB; 99e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_9MB: 100e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xF; 101e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_12MB: 102e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xA; 103e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_18MB: 104e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xE; 105e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_24MB: 106e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x9; 107e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_36MB: 108e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xD; 109e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_48MB: 110e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0x8; 111e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_54MB: 112e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0xC; 113e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 114e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 115e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 116e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 117e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 118e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, 119e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const u16 octets, const u8 bitrate) 120e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 121e4d6b7951812d98417feb10784e400e253caf633Michael Buesch __u8 *raw = plcp->raw; 122e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 123e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (b43_is_ofdm_rate(bitrate)) { 1241a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch u32 d; 1251a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch 1261a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch d = b43_plcp_get_ratecode_ofdm(bitrate); 127e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(octets & 0xF000); 1281a09404a2338163f181d170c7abdc2242b6c6f03Michael Buesch d |= (octets << 5); 129b52a033c2c501a8015df3727a4bd73389ccb1641Matthieu CASTET plcp->data = cpu_to_le32(d); 130e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 131e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 plen; 132e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 133e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plen = octets * 16 / bitrate; 134e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((octets * 16 % bitrate) > 0) { 135e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plen++; 136e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((bitrate == B43_CCK_RATE_11MB) 137e4d6b7951812d98417feb10784e400e253caf633Michael Buesch && ((octets * 8 % 11) < 4)) { 138e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x84; 139e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 140e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x04; 141e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 142e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[1] = 0x04; 143b52a033c2c501a8015df3727a4bd73389ccb1641Matthieu CASTET plcp->data |= cpu_to_le32(plen << 16); 144e4d6b7951812d98417feb10784e400e253caf633Michael Buesch raw[0] = b43_plcp_get_ratecode_cck(bitrate); 145e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 146e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 147e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 148e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic u8 b43_calc_fallback_rate(u8 bitrate) 149e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 150e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (bitrate) { 151e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_1MB: 152e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_1MB; 153e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_2MB: 154e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_1MB; 155e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_5MB: 156e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_2MB; 157e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_CCK_RATE_11MB: 158e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_5MB; 159e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_6MB: 160e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_CCK_RATE_5MB; 161e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_9MB: 162e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_6MB; 163e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_12MB: 164e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_9MB; 165e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_18MB: 166e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_12MB; 167e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_24MB: 168e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_18MB; 169e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_36MB: 170e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_24MB; 171e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_48MB: 172e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_36MB; 173e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_OFDM_RATE_54MB: 174e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return B43_OFDM_RATE_48MB; 175e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 176e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 177e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return 0; 178e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 179e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 180eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch/* Generate a TX data header. */ 18109552ccd8277e6382097e93a40f7311a09449367Michael Bueschint b43_generate_txhdr(struct b43_wldev *dev, 18209552ccd8277e6382097e93a40f7311a09449367Michael Buesch u8 *_txhdr, 18309552ccd8277e6382097e93a40f7311a09449367Michael Buesch const unsigned char *fragment_data, 18409552ccd8277e6382097e93a40f7311a09449367Michael Buesch unsigned int fragment_len, 185e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg struct ieee80211_tx_info *info, 18609552ccd8277e6382097e93a40f7311a09449367Michael Buesch u16 cookie) 187e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 188eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; 189e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_phy *phy = &dev->phy; 190e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct ieee80211_hdr *wlhdr = 191e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (const struct ieee80211_hdr *)fragment_data; 192d0f09804144fd9471a13cf4d80e66842c7fa114fJohannes Berg int use_encryption = !!info->control.hw_key; 193f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison __le16 fctl = wlhdr->frame_control; 1948318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg struct ieee80211_rate *fbrate; 195e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 rate, rate_fb; 196e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rate_ofdm, rate_fb_ofdm; 197e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int plcp_fragment_len; 198e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 mac_ctl = 0; 199e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 phy_ctl = 0; 200e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 extra_ft = 0; 2012e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg struct ieee80211_rate *txrate; 202e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg struct ieee80211_tx_rate *rates; 203e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 204e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memset(txhdr, 0, sizeof(*txhdr)); 205e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 206e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg txrate = ieee80211_get_tx_rate(dev->wl->hw, info); 2072e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; 208e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rate_ofdm = b43_is_ofdm_rate(rate); 209870abdf67170daa9f1022e55a35c469239fcc74cFelix Fietkau fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate; 2108318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg rate_fb = fbrate->hw_value; 211e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); 212e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 213e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_ofdm) 214e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate); 215e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 216e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate); 217e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->mac_frame_ctl = wlhdr->frame_control; 218e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); 219e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 220e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Calculate duration for fallback rate */ 221e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if ((rate_fb == rate) || 222e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (wlhdr->duration_id & cpu_to_le16(0x8000)) || 223e4d6b7951812d98417feb10784e400e253caf633Michael Buesch (wlhdr->duration_id == cpu_to_le16(0))) { 224e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* If the fallback rate equals the normal rate or the 225e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * dur_id field contains an AID, CFP magic or 0, 226e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * use the original dur_id field. */ 227e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->dur_fb = wlhdr->duration_id; 228e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 229e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg txhdr->dur_fb = ieee80211_generic_frame_duration( 230e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg dev->wl->hw, info->control.vif, fragment_len, fbrate); 231e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 232e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 233e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp_fragment_len = fragment_len + FCS_LEN; 234e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (use_encryption) { 235e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg u8 key_idx = info->control.hw_key->hw_key_idx; 236e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_key *key; 237e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int wlhdr_len; 238e4d6b7951812d98417feb10784e400e253caf633Michael Buesch size_t iv_len; 239e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 24066d2d089c394c7e31020947d682523f77a93244bMichael Buesch B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key)); 241e4d6b7951812d98417feb10784e400e253caf633Michael Buesch key = &(dev->key[key_idx]); 2427be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch 24309552ccd8277e6382097e93a40f7311a09449367Michael Buesch if (unlikely(!key->keyconf)) { 24409552ccd8277e6382097e93a40f7311a09449367Michael Buesch /* This key is invalid. This might only happen 24509552ccd8277e6382097e93a40f7311a09449367Michael Buesch * in a short timeframe after machine resume before 24609552ccd8277e6382097e93a40f7311a09449367Michael Buesch * we were able to reconfigure keys. 24709552ccd8277e6382097e93a40f7311a09449367Michael Buesch * Drop this packet completely. Do not transmit it 24809552ccd8277e6382097e93a40f7311a09449367Michael Buesch * unencrypted to avoid leaking information. */ 24909552ccd8277e6382097e93a40f7311a09449367Michael Buesch return -ENOKEY; 2507be1bb6b798d506693d2d8668e801951996b5a4aMichael Buesch } 25109552ccd8277e6382097e93a40f7311a09449367Michael Buesch 25209552ccd8277e6382097e93a40f7311a09449367Michael Buesch /* Hardware appends ICV. */ 25376708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau plcp_fragment_len += info->control.hw_key->icv_len; 25409552ccd8277e6382097e93a40f7311a09449367Michael Buesch 25509552ccd8277e6382097e93a40f7311a09449367Michael Buesch key_idx = b43_kidx_to_fw(dev, key_idx); 25609552ccd8277e6382097e93a40f7311a09449367Michael Buesch mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & 25709552ccd8277e6382097e93a40f7311a09449367Michael Buesch B43_TXH_MAC_KEYIDX; 25809552ccd8277e6382097e93a40f7311a09449367Michael Buesch mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & 25909552ccd8277e6382097e93a40f7311a09449367Michael Buesch B43_TXH_MAC_KEYALG; 260f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison wlhdr_len = ieee80211_hdrlen(fctl); 26176708dee382a69b2f9d0e50f413f99fefb2dc509Felix Fietkau iv_len = min((size_t) info->control.hw_key->iv_len, 26209552ccd8277e6382097e93a40f7311a09449367Michael Buesch ARRAY_SIZE(txhdr->iv)); 26309552ccd8277e6382097e93a40f7311a09449367Michael Buesch memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); 264e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 265eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) { 266eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), 267eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp_fragment_len, rate); 268eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 269eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), 270eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp_fragment_len, rate); 271eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 272e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), 273e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp_fragment_len, rate_fb); 274e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 275e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Extra Frame Types */ 276e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_fb_ofdm) 277eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_FB_OFDM; 278eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 279eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_FB_CCK; 280e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 281e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Set channel radio code. Note that the micrcode ORs 0x100 to 282e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * this value before comparing it to the value in SHM, if this 283e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * is a 5Ghz packet. 284e4d6b7951812d98417feb10784e400e253caf633Michael Buesch */ 285e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->chan_radio_code = phy->channel; 286e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 287e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* PHY TX Control word */ 288e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rate_ofdm) 289eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ENC_OFDM; 290eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 291eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ENC_CCK; 292e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) 293eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_SHORTPRMBL; 2949db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch 295e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { 2969db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch case 0: /* Default */ 297eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT01AUTO; 298e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 2999db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch case 1: /* Antenna 0 */ 300eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT0; 301e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 3029db1f6d725921c413cc344beda5e7e7d011b02e7Michael Buesch case 2: /* Antenna 1 */ 303eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT1; 304eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch break; 305eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch case 3: /* Antenna 2 */ 306eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT2; 307eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch break; 308eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch case 4: /* Antenna 3 */ 309eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch phy_ctl |= B43_TXH_PHY_ANT3; 310e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 311e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 312e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 313e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 314e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 315e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg rates = info->control.rates; 316e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* MAC control */ 317e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) 318eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_ACK; 319f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg /* use hardware sequence counter as the non-TID counter */ 320f591fa5dbbbeaebd95c9c019b3a536a327fb79deJohannes Berg if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) 321eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_HWSEQ; 322e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) 323eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_STMSDU; 324e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_A) 325eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_5GHZ; 326e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg 327e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg /* Overwrite rates[0].count to make the retry calculation 328e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * in the tx status easier. need the actual retry limit to 329e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * detect whether the fallback rate was used. 330e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg */ 331e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || 332e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { 333e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; 334eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_LONGFRAME; 335e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } else { 336e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; 337e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } 338e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 339e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Generate the RTS or CTS-to-self frame */ 340e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || 341e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { 342e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int len; 343e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_hdr *hdr; 344e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rts_rate, rts_rate_fb; 345e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int rts_rate_ofdm, rts_rate_fb_ofdm; 346eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch struct b43_plcp_hdr6 *plcp; 3472e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg struct ieee80211_rate *rts_cts_rate; 348e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 349e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); 3502e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg 3512e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39Johannes Berg rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB; 352e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); 353e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_fb = b43_calc_fallback_rate(rts_rate); 354e4d6b7951812d98417feb10784e400e253caf633Michael Buesch rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); 355e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 356e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { 357eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch struct ieee80211_cts *cts; 358eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 359eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) { 360eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch cts = (struct ieee80211_cts *) 361eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (txhdr->old_format.rts_frame); 362eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 363eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch cts = (struct ieee80211_cts *) 364eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (txhdr->new_format.rts_frame); 365eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 366e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, 367e4d6b7951812d98417feb10784e400e253caf633Michael Buesch fragment_data, fragment_len, 368e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info, cts); 369eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_SENDCTS; 370e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len = sizeof(struct ieee80211_cts); 371e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 372eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch struct ieee80211_rts *rts; 373eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 374eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) { 375eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch rts = (struct ieee80211_rts *) 376eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (txhdr->old_format.rts_frame); 377eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 378eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch rts = (struct ieee80211_rts *) 379eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (txhdr->new_format.rts_frame); 380eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 381e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg ieee80211_rts_get(dev->wl->hw, info->control.vif, 382eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch fragment_data, fragment_len, 383e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg info, rts); 384eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch mac_ctl |= B43_TXH_MAC_SENDRTS; 385e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len = sizeof(struct ieee80211_rts); 386e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 387e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len += FCS_LEN; 388eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 389eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch /* Generate the PLCP headers for the RTS/CTS frame */ 390eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) 391eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp = &txhdr->old_format.rts_plcp; 392eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 393eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp = &txhdr->new_format.rts_plcp; 394eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, 395eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch len, rts_rate); 396eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch plcp = &txhdr->rts_plcp_fb; 397eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, 398e4d6b7951812d98417feb10784e400e253caf633Michael Buesch len, rts_rate_fb); 399eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 400eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) { 401eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch hdr = (struct ieee80211_hdr *) 402eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (&txhdr->old_format.rts_frame); 403eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 404eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch hdr = (struct ieee80211_hdr *) 405eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch (&txhdr->new_format.rts_frame); 406eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 407e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->rts_dur_fb = hdr->duration_id; 408eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch 409e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rts_rate_ofdm) { 410eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_RTS_OFDM; 411e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate_rts = 412e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_plcp_get_ratecode_ofdm(rts_rate); 413eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } else { 414eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_RTS_CCK; 415e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_rate_rts = 416e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_plcp_get_ratecode_cck(rts_rate); 417eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch } 418e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (rts_rate_fb_ofdm) 419eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_RTSFB_OFDM; 420eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 421eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch extra_ft |= B43_TXH_EFT_RTSFB_CCK; 422e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 423e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 424e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Magic cookie */ 425eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch if (b43_is_old_txhdr_format(dev)) 426eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch txhdr->old_format.cookie = cpu_to_le16(cookie); 427eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch else 428eb189d8bc9824bcb2187ffdab27d77ab469264c3Michael Buesch txhdr->new_format.cookie = cpu_to_le16(cookie); 429e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 430e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Apply the bitfields */ 431e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->mac_ctl = cpu_to_le32(mac_ctl); 432e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->phy_ctl = cpu_to_le16(phy_ctl); 433e4d6b7951812d98417feb10784e400e253caf633Michael Buesch txhdr->extra_ft = extra_ft; 434e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 43509552ccd8277e6382097e93a40f7311a09449367Michael Buesch return 0; 436e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 437e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 438e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssi_postprocess(struct b43_wldev *dev, 439e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u8 in_rssi, int ofdm, 440e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int adjust_2053, int adjust_2050) 441e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 442e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_phy *phy = &dev->phy; 443ef1a628d83fc0423c36e773281162be790503168Michael Buesch struct b43_phy_g *gphy = phy->g; 444e4d6b7951812d98417feb10784e400e253caf633Michael Buesch s32 tmp; 445e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 446e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (phy->radio_ver) { 447e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x2050: 448e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (ofdm) { 449e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 450e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (tmp > 127) 451e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 256; 452e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= 73; 453e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 64; 454e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (adjust_2050) 455e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp += 25; 456e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 457e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 3; 458e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 45995de2841aad971867851b59c0c5253ecc2e19832Larry Finger if (dev->dev->bus->sprom. 460e4d6b7951812d98417feb10784e400e253caf633Michael Buesch boardflags_lo & B43_BFL_RSSI) { 461e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (in_rssi > 63) 462e4d6b7951812d98417feb10784e400e253caf633Michael Buesch in_rssi = 63; 463ef1a628d83fc0423c36e773281162be790503168Michael Buesch B43_WARN_ON(phy->type != B43_PHYTYPE_G); 464ef1a628d83fc0423c36e773281162be790503168Michael Buesch tmp = gphy->nrssi_lt[in_rssi]; 465e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = 31 - tmp; 466e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= -131; 467e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 128; 468e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 57; 469e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else { 470e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 471e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = 31 - tmp; 472e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= -149; 473e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 128; 474e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 68; 475e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 476e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_G && adjust_2050) 477e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp += 25; 478e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 479e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 480e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case 0x2060: 481e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (in_rssi > 127) 482e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi - 256; 483e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 484e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 485e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 486e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 487e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp = in_rssi; 488e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 11; 489e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp *= 103; 490e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp /= 64; 491e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (adjust_2053) 492e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 109; 493e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 494e4d6b7951812d98417feb10784e400e253caf633Michael Buesch tmp -= 83; 495e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 496e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 497e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return (s8) tmp; 498e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 499e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 500e4d6b7951812d98417feb10784e400e253caf633Michael Buesch//TODO 501e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#if 0 502e4d6b7951812d98417feb10784e400e253caf633Michael Bueschstatic s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi) 503e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 504e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_phy *phy = &dev->phy; 505e4d6b7951812d98417feb10784e400e253caf633Michael Buesch s8 ret; 506e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 507e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phy->type == B43_PHYTYPE_A) { 508e4d6b7951812d98417feb10784e400e253caf633Michael Buesch //TODO: Incomplete specs. 509e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ret = 0; 510e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } else 511e4d6b7951812d98417feb10784e400e253caf633Michael Buesch ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1); 512e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 513e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return ret; 514e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 515e4d6b7951812d98417feb10784e400e253caf633Michael Buesch#endif 516e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 517e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) 518e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 519e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_rx_status status; 520e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct b43_plcp_hdr6 *plcp; 521e4d6b7951812d98417feb10784e400e253caf633Michael Buesch struct ieee80211_hdr *wlhdr; 522e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; 523f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison __le16 fctl; 524e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 phystat0, phystat3, chanstat, mactime; 525e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u32 macstat; 526e4d6b7951812d98417feb10784e400e253caf633Michael Buesch u16 chanid; 5278318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg u16 phytype; 528e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int padding; 529e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 530e4d6b7951812d98417feb10784e400e253caf633Michael Buesch memset(&status, 0, sizeof(status)); 531e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 532e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Get metadata about the frame from the header. */ 533e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phystat0 = le16_to_cpu(rxhdr->phy_status0); 534e4d6b7951812d98417feb10784e400e253caf633Michael Buesch phystat3 = le16_to_cpu(rxhdr->phy_status3); 535e4d6b7951812d98417feb10784e400e253caf633Michael Buesch macstat = le32_to_cpu(rxhdr->mac_status); 536e4d6b7951812d98417feb10784e400e253caf633Michael Buesch mactime = le16_to_cpu(rxhdr->mac_time); 537e4d6b7951812d98417feb10784e400e253caf633Michael Buesch chanstat = le16_to_cpu(rxhdr->channel); 5388318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg phytype = chanstat & B43_RX_CHAN_PHYTYPE; 539e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 540ce4fbdbf161b2676b3833412367113572d739253Michael Buesch if (unlikely(macstat & B43_RX_MAC_FCSERR)) { 541e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11FCSErrorCount++; 542ce4fbdbf161b2676b3833412367113572d739253Michael Buesch status.flag |= RX_FLAG_FAILED_FCS_CRC; 543ce4fbdbf161b2676b3833412367113572d739253Michael Buesch } 544ce4fbdbf161b2676b3833412367113572d739253Michael Buesch if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV))) 545ce4fbdbf161b2676b3833412367113572d739253Michael Buesch status.flag |= RX_FLAG_FAILED_PLCP_CRC; 546ce4fbdbf161b2676b3833412367113572d739253Michael Buesch if (phystat0 & B43_RX_PHYST0_SHORTPRMBL) 547ce4fbdbf161b2676b3833412367113572d739253Michael Buesch status.flag |= RX_FLAG_SHORTPRE; 548e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_DECERR) { 549e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Decryption with the given key failed. 550e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * Drop the packet. We also won't be able to decrypt it with 551e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * the key in software. */ 552e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 553e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 554e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 555e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* Skip PLCP and padding */ 556e4d6b7951812d98417feb10784e400e253caf633Michael Buesch padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0; 557e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) { 558e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet size underrun (1)\n"); 559e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 560e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 561e4d6b7951812d98417feb10784e400e253caf633Michael Buesch plcp = (struct b43_plcp_hdr6 *)(skb->data + padding); 562e4d6b7951812d98417feb10784e400e253caf633Michael Buesch skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding); 563e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* The skb contains the Wireless Header + payload data now */ 564e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */ + FCS_LEN))) { 565e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet size underrun (2)\n"); 566e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 567e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 568e4d6b7951812d98417feb10784e400e253caf633Michael Buesch wlhdr = (struct ieee80211_hdr *)(skb->data); 569f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison fctl = wlhdr->frame_control; 570e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 571e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (macstat & B43_RX_MAC_DEC) { 572e4d6b7951812d98417feb10784e400e253caf633Michael Buesch unsigned int keyidx; 573e4d6b7951812d98417feb10784e400e253caf633Michael Buesch int wlhdr_len; 574e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 575e4d6b7951812d98417feb10784e400e253caf633Michael Buesch keyidx = ((macstat & B43_RX_MAC_KEYIDX) 576e4d6b7951812d98417feb10784e400e253caf633Michael Buesch >> B43_RX_MAC_KEYIDX_SHIFT); 577e4d6b7951812d98417feb10784e400e253caf633Michael Buesch /* We must adjust the key index here. We want the "physical" 578e4d6b7951812d98417feb10784e400e253caf633Michael Buesch * key index, but the ucode passed it slightly different. 579e4d6b7951812d98417feb10784e400e253caf633Michael Buesch */ 580e4d6b7951812d98417feb10784e400e253caf633Michael Buesch keyidx = b43_kidx_to_raw(dev, keyidx); 58166d2d089c394c7e31020947d682523f77a93244bMichael Buesch B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key)); 582e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 583e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { 584f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison wlhdr_len = ieee80211_hdrlen(fctl); 585e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (unlikely(skb->len < (wlhdr_len + 3))) { 586e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, 587e4d6b7951812d98417feb10784e400e253caf633Michael Buesch "RX: Packet size underrun (3)\n"); 588e4d6b7951812d98417feb10784e400e253caf633Michael Buesch goto drop; 589e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 590e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.flag |= RX_FLAG_DECRYPTED; 591e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 592e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 593e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 5947b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch /* Link quality statistics */ 595e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.noise = dev->stats.link_noise; 5967b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) { 5977b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch// s8 rssi = max(rxhdr->power0, rxhdr->power1); 5987b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch //TODO: Find out what the rssi value is (dBm or percentage?) 5997b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch // and also find out what the maximum possible value is. 6007b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch // Fill status.ssi and status.signal fields. 6017b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch } else { 602566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf status.signal = b43_rssi_postprocess(dev, rxhdr->jssi, 6037b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch (phystat0 & B43_RX_PHYST0_OFDM), 6047b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch (phystat0 & B43_RX_PHYST0_GAINCTL), 6057b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch (phystat3 & B43_RX_PHYST3_TRSTATE)); 606566bfe5a8bcde13188a356f77666f8115813cf31Bruno Randolf status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI; 6077b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch } 6087b584163979a9fe2ebfdd57a9d64cbe27166ab70Michael Buesch 609e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (phystat0 & B43_RX_PHYST0_OFDM) 6108318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, 6118318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg phytype == B43_PHYTYPE_A); 612e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 6138318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); 614ce4fbdbf161b2676b3833412367113572d739253Michael Buesch if (unlikely(status.rate_idx == -1)) { 615ce4fbdbf161b2676b3833412367113572d739253Michael Buesch /* PLCP seems to be corrupted. 616ce4fbdbf161b2676b3833412367113572d739253Michael Buesch * Drop the frame, if we are not interested in corrupted frames. */ 617ce4fbdbf161b2676b3833412367113572d739253Michael Buesch if (!(dev->wl->filter_flags & FIF_PLCPFAIL)) 618ce4fbdbf161b2676b3833412367113572d739253Michael Buesch goto drop; 619ce4fbdbf161b2676b3833412367113572d739253Michael Buesch } 620e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); 621c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville 622c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville /* 623d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * All frames on monitor interfaces and beacons always need a full 624d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * 64-bit timestamp. Monitor interfaces need it for diagnostic 625d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * purposes and beacons for IBSS merging. 626d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * This code assumes we get to process the packet within 16 bits 627d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * of timestamp, i.e. about 65 milliseconds after the PHY received 628d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736Johannes Berg * the first symbol. 629c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville */ 630f37d923422b61884a75a2a64865ed03ca5ccfc6dHarvey Harrison if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { 631c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville u16 low_mactime_now; 632c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville 633c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville b43_tsf_read(dev, &status.mactime); 634c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville low_mactime_now = status.mactime; 635c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime = status.mactime & ~0xFFFFULL; 636c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime += mactime; 637c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville if (low_mactime_now <= mactime) 638c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.mactime -= 0x10000; 639c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville status.flag |= RX_FLAG_TSFT; 640c0ddd04d55e0a4d1506b6b8a4eb9e2b62f3aa41dJohn W. Linville } 641e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 642e4d6b7951812d98417feb10784e400e253caf633Michael Buesch chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; 643e4d6b7951812d98417feb10784e400e253caf633Michael Buesch switch (chanstat & B43_RX_CHAN_PHYTYPE) { 644e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_PHYTYPE_A: 6458318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_5GHZ; 646d987160b710c98997015832422a05e18d9f0f925Michael Buesch B43_WARN_ON(1); 647d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* FIXME: We don't really know which value the "chanid" contains. 648d987160b710c98997015832422a05e18d9f0f925Michael Buesch * So the following assignment might be wrong. */ 6498318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.freq = b43_channel_to_freq_5ghz(chanid); 650e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 651e4d6b7951812d98417feb10784e400e253caf633Michael Buesch case B43_PHYTYPE_G: 6528318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_2GHZ; 653d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* chanid is the radio channel cookie value as used 654d987160b710c98997015832422a05e18d9f0f925Michael Buesch * to tune the radio. */ 655e4d6b7951812d98417feb10784e400e253caf633Michael Buesch status.freq = chanid + 2400; 656d987160b710c98997015832422a05e18d9f0f925Michael Buesch break; 657d987160b710c98997015832422a05e18d9f0f925Michael Buesch case B43_PHYTYPE_N: 658d987160b710c98997015832422a05e18d9f0f925Michael Buesch /* chanid is the SHM channel cookie. Which is the plain 659d987160b710c98997015832422a05e18d9f0f925Michael Buesch * channel number in b43. */ 6608318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg if (chanstat & B43_RX_CHAN_5GHZ) { 6618318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_5GHZ; 6628318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.freq = b43_freq_to_channel_5ghz(chanid); 6638318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } else { 6648318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.band = IEEE80211_BAND_2GHZ; 6658318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg status.freq = b43_freq_to_channel_2ghz(chanid); 6668318d78a44d49ac1edf2bdec7299de3617c4232eJohannes Berg } 667e4d6b7951812d98417feb10784e400e253caf633Michael Buesch break; 668e4d6b7951812d98417feb10784e400e253caf633Michael Buesch default: 669e4d6b7951812d98417feb10784e400e253caf633Michael Buesch B43_WARN_ON(1); 670d987160b710c98997015832422a05e18d9f0f925Michael Buesch goto drop; 671e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 672e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 673f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); 674f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg ieee80211_rx_irqsafe(dev->wl->hw, skb); 675e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 676e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 677e4d6b7951812d98417feb10784e400e253caf633Michael Bueschdrop: 678e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43dbg(dev->wl, "RX: Packet dropped\n"); 679e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev_kfree_skb_any(skb); 680e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 681e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 682e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_handle_txstatus(struct b43_wldev *dev, 683e4d6b7951812d98417feb10784e400e253caf633Michael Buesch const struct b43_txstatus *status) 684e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 685e4d6b7951812d98417feb10784e400e253caf633Michael Buesch b43_debugfs_log_txstat(dev, status); 686e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 687e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->intermediate) 688e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 689e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->for_ampdu) 690e4d6b7951812d98417feb10784e400e253caf633Michael Buesch return; 691e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (!status->acked) 692e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11ACKFailureCount++; 693e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->rts_count) { 694e4d6b7951812d98417feb10784e400e253caf633Michael Buesch if (status->rts_count == 0xF) //FIXME 695e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11RTSFailureCount++; 696e4d6b7951812d98417feb10784e400e253caf633Michael Buesch else 697e4d6b7951812d98417feb10784e400e253caf633Michael Buesch dev->wl->ieee_stats.dot11RTSSuccessCount++; 698e4d6b7951812d98417feb10784e400e253caf633Michael Buesch } 699e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 7005100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (b43_using_pio_transfers(dev)) 7015100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_pio_handle_txstatus(dev, status); 7025100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch else 7035100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_dma_handle_txstatus(dev, status); 70418c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch 70518c8adeb0244f823ba78a51e23f813fe68bc3c54Michael Buesch b43_phy_txpower_check(dev, 0); 706e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 707e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 7085100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch/* Fill out the mac80211 TXstatus report based on the b43-specific 7095100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * txstatus report data. This returns a boolean whether the frame was 7105100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch * successfully transmitted. */ 711e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Bergbool b43_fill_txstatus_report(struct b43_wldev *dev, 712e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg struct ieee80211_tx_info *report, 7135100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch const struct b43_txstatus *status) 714e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 7155100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch bool frame_success = 1; 716e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg int retry_limit; 717e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg 718e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg /* preserve the confiured retry limit before clearing the status 719e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * The xmit function has overwritten the rc's value with the actual 720e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * retry limit done by the hardware */ 721e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg retry_limit = report->status.rates[0].count; 722e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg ieee80211_tx_info_clear_status(report); 7235100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch 7245100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (status->acked) { 7255100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch /* The frame was ACKed. */ 726e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg report->flags |= IEEE80211_TX_STAT_ACK; 7275100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch } else { 7285100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch /* The frame was not ACKed... */ 729e039fa4a4195ac4ee895e6f3d1334beed63256feJohannes Berg if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { 7305100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch /* ...but we expected an ACK. */ 7315100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch frame_success = 0; 7325100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch } 7335100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch } 7345100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (status->frame_count == 0) { 7355100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch /* The frame was not transmitted at all. */ 736e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg report->status.rates[0].count = 0; 737e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { 738e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg /* 739e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * If the short retries (RTS, not data frame) have exceeded 740e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * the limit, the hw will not have tried the selected rate, 741e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * but will have used the fallback rate instead. 742e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * Don't let the rate control count attempts for the selected 743e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg * rate in this case, otherwise the statistics will be off. 744e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg */ 745e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg report->status.rates[0].count = 0; 746e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg report->status.rates[1].count = status->frame_count; 747e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } else { 748e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg if (status->frame_count > retry_limit) { 749e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg report->status.rates[0].count = retry_limit; 750e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg report->status.rates[1].count = status->frame_count - 751e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg retry_limit; 752e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg 753e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } else { 754e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg report->status.rates[0].count = status->frame_count; 755e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg report->status.rates[1].idx = -1; 756e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } 757e6a9854b05c1a6af1308fe2b8c68f35abf28a3eeJohannes Berg } 7585100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch 7595100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch return frame_success; 760e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 761e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 762e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Stop any TX operation on the device (suspend the hardware queues) */ 763e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_suspend(struct b43_wldev *dev) 764e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 7655100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (b43_using_pio_transfers(dev)) 7665100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_pio_tx_suspend(dev); 7675100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch else 7685100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_dma_tx_suspend(dev); 769e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 770e4d6b7951812d98417feb10784e400e253caf633Michael Buesch 771e4d6b7951812d98417feb10784e400e253caf633Michael Buesch/* Resume any TX operation on the device (resume the hardware queues) */ 772e4d6b7951812d98417feb10784e400e253caf633Michael Bueschvoid b43_tx_resume(struct b43_wldev *dev) 773e4d6b7951812d98417feb10784e400e253caf633Michael Buesch{ 7745100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch if (b43_using_pio_transfers(dev)) 7755100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_pio_tx_resume(dev); 7765100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch else 7775100d5ac81b9330dc57e35adbe50923ba6107b8fMichael Buesch b43_dma_tx_resume(dev); 778e4d6b7951812d98417feb10784e400e253caf633Michael Buesch} 779