1ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman/****************************************************************************** 2ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 3ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. 4ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 5ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman This program is free software; you can redistribute it and/or modify it 6ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman under the terms of version 2 of the GNU General Public License as 7ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman published by the Free Software Foundation. 8ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 9ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman This program is distributed in the hope that it will be useful, but WITHOUT 10ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman more details. 13ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 14ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman You should have received a copy of the GNU General Public License along with 15ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman this program; if not, write to the Free Software Foundation, Inc., 59 16ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 18ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman The full GNU General Public License is included in this distribution in the 19ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman file called LICENSE. 20ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 21ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman Contact Information: 22ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman James P. Ketrenos <ipw2100-admin@linux.intel.com> 23ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 24ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 25ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman****************************************************************************** 26ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 27ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman Few modifications for Realtek's Wi-Fi drivers by 28ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman Andrea Merello <andreamrl@tiscali.it> 29ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 30ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman A special thanks goes to Realtek for their support ! 31ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 32ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman******************************************************************************/ 33ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 34ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/compiler.h> 35ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/errno.h> 36ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/if_arp.h> 37ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/in6.h> 38ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/in.h> 39ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/ip.h> 40ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/kernel.h> 41ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/module.h> 42ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/netdevice.h> 43ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/pci.h> 44ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/proc_fs.h> 45ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/skbuff.h> 46ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/slab.h> 47ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/tcp.h> 48ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/types.h> 49ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/wireless.h> 50ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/etherdevice.h> 51f38d223b692742e77c70033d145245615c8f3aa5Larry Finger#include <linux/uaccess.h> 52ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman#include <linux/if_vlan.h> 53ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 5494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger#include "rtllib.h" 55ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 56ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman/* 57ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 58ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 59ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman802.11 Data Frame 60ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 61ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 62ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman802.11 frame_contorl for data frames - 2 bytes 63ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ,-----------------------------------------------------------------------------------------. 64ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanbits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | 65ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| 66ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanval | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | 67ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| 68ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmandesc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep | 69f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | | 70ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman '-----------------------------------------------------------------------------------------' 71f38d223b692742e77c70033d145245615c8f3aa5Larry Finger /\ 72f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | 73f38d223b692742e77c70033d145245615c8f3aa5Larry Finger802.11 Data Frame | 74f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ,--------- 'ctrl' expands to >-----------' 75f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | 76ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ,--'---,-------------------------------------------------------------. 77ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanBytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | 78ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman |------|------|---------|---------|---------|------|---------|------| 79ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanDesc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | 80f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | | tion | (BSSID) | | | ence | data | | 81f38d223b692742e77c70033d145245615c8f3aa5Larry Finger `--------------------------------------------------| |------' 82f38d223b692742e77c70033d145245615c8f3aa5Larry FingerTotal: 28 non-data bytes `----.----' 83f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | 84ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman .- 'Frame data' expands to <---------------------------' 85ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman | 86ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman V 87ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ,---------------------------------------------------. 88ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanBytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | 89ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman |------|------|---------|----------|------|---------| 90ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanDesc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | 91f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | DSAP | SSAP | | | | Packet | 92f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | 93f38d223b692742e77c70033d145245615c8f3aa5Larry Finger `-----------------------------------------| | 94f38d223b692742e77c70033d145245615c8f3aa5Larry FingerTotal: 8 non-data bytes `----.----' 95f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | 96ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman .- 'IP Packet' expands, if WEP enabled, to <--' 97ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman | 98ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman V 99ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ,-----------------------. 100ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanBytes | 4 | 0-2296 | 4 | 101ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman |-----|-----------|-----| 102ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanDesc. | IV | Encrypted | ICV | 103ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman | | IP Packet | | 104ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman `-----------------------' 105ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanTotal: 8 non-data bytes 106ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 107ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 108ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman802.3 Ethernet Data Frame 109ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 110ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ,-----------------------------------------. 111ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanBytes | 6 | 6 | 2 | Variable | 4 | 112ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman |-------|-------|------|-----------|------| 113ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanDesc. | Dest. | Source| Type | IP Packet | fcs | 114f38d223b692742e77c70033d145245615c8f3aa5Larry Finger | MAC | MAC | | | | 115ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman `-----------------------------------------' 116ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanTotal: 18 non-data bytes 117ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 118ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanIn the event that fragmentation is required, the incoming payload is split into 119ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanN parts of size ieee->fts. The first fragment contains the SNAP header and the 120ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanremaining packets are just data. 121ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 122ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanIf encryption is enabled, each fragment payload size is reduced by enough space 123ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanto add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) 124ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanSo if you have 1500 bytes of payload with ieee->fts set to 500 without 125ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanencryption it will take 3 frames. With WEP it will take 4 frames as the 126ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanpayload of each frame is reduced to 492 bytes. 127ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 128ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* SKB visualization 129ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* 130ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* ,- skb->data 131ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* | 132f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* | ETHERNET HEADER ,-<-- PAYLOAD 133f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* | | 14 bytes from skb->data 134ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* | 2 bytes for Type --> ,T. | (sizeof ethhdr) 135f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* | | | | 136ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* |,-Dest.--. ,--Src.---. | | | 137ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* | 6 bytes| | 6 bytes | | | | 138f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* v | | | | | | 139f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* 0 | v 1 | v | v 2 140ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 141f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* ^ | ^ | ^ | 142f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* | | | | | | 143f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* | | | | `T' <---- 2 bytes for Type 144f38d223b692742e77c70033d145245615c8f3aa5Larry Finger* | | | | 145ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* | | '---SNAP--' <-------- 6 bytes for SNAP 146ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* | | 147ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* `-IV--' <-------------------- 4 bytes for IV (WEP) 148ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* 149ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* SNAP HEADER 150ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman* 151ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman*/ 152ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 153ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanstatic u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; 154ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartmanstatic u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; 155ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 15694a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerinline int rtllib_put_snap(u8 *data, u16 h_proto) 157ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 15894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_snap_hdr *snap; 159ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 *oui; 160ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 16194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger snap = (struct rtllib_snap_hdr *)data; 162ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman snap->dsap = 0xaa; 163ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman snap->ssap = 0xaa; 164ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman snap->ctrl = 0x03; 165ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 166ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (h_proto == 0x8137 || h_proto == 0x80f3) 167ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman oui = P802_1H_OUI; 168ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman else 169ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman oui = RFC1042_OUI; 170ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman snap->oui[0] = oui[0]; 171ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman snap->oui[1] = oui[1]; 172ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman snap->oui[2] = oui[2]; 173ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 174ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman *(u16 *)(data + SNAP_SIZE) = htons(h_proto); 175ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 176ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return SNAP_SIZE + sizeof(u16); 177ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 178ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 179f38d223b692742e77c70033d145245615c8f3aa5Larry Fingerint rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag, 180f38d223b692742e77c70033d145245615c8f3aa5Larry Finger int hdr_len) 181ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 18232c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan struct lib80211_crypt_data *crypt = NULL; 183ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int res; 184ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 1850ddcf5fdfac6bd80e153ee5c405bdfc9cb868b95Sean MacLennan crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; 18694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 187f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (!(crypt && crypt->ops)) { 188f38d223b692742e77c70033d145245615c8f3aa5Larry Finger printk(KERN_INFO "=========>%s(), crypt is null\n", __func__); 189ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -1; 190ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 191ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* To encrypt, frame format is: 192ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ 193ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 194ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so 195ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * call both MSDU and MPDU encryption functions from here. */ 196ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman atomic_inc(&crypt->refcnt); 197ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman res = 0; 198ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (crypt->ops->encrypt_msdu) 199ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); 200ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (res == 0 && crypt->ops->encrypt_mpdu) 201ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); 202ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 203ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman atomic_dec(&crypt->refcnt); 204ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (res < 0) { 205ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman printk(KERN_INFO "%s: Encryption failed: len=%d.\n", 206ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ieee->dev->name, frag->len); 207ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ieee->ieee_stats.tx_discards++; 208ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return -1; 209ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 210ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 211ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return 0; 212ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 213ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 214ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 215f38d223b692742e77c70033d145245615c8f3aa5Larry Fingervoid rtllib_txb_free(struct rtllib_txb *txb) 216f38d223b692742e77c70033d145245615c8f3aa5Larry Finger{ 217ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (unlikely(!txb)) 218ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 219ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman kfree(txb); 220ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 221ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 222ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size, 223ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Finger gfp_t gfp_mask) 224ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 22594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_txb *txb; 226ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int i; 227f38d223b692742e77c70033d145245615c8f3aa5Larry Finger txb = kmalloc(sizeof(struct rtllib_txb) + (sizeof(u8 *) * nr_frags), 228f38d223b692742e77c70033d145245615c8f3aa5Larry Finger gfp_mask); 229ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (!txb) 230ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return NULL; 231ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 23294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger memset(txb, 0, sizeof(struct rtllib_txb)); 233ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman txb->nr_frags = nr_frags; 234ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman txb->frag_size = txb_size; 235ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 236ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman for (i = 0; i < nr_frags; i++) { 237ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman txb->fragments[i] = dev_alloc_skb(txb_size); 238ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (unlikely(!txb->fragments[i])) { 239ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman i--; 240ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman break; 241ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 242ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb)); 243ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 244ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (unlikely(i != nr_frags)) { 245ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman while (i >= 0) 246ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman dev_kfree_skb_any(txb->fragments[i--]); 247ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman kfree(txb); 248ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return NULL; 249ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 250ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return txb; 251ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 252ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 253ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu) 254ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 255ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman struct ethhdr *eth; 256ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman struct iphdr *ip; 25794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 258ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman eth = (struct ethhdr *)skb->data; 259ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (eth->h_proto != htons(ETH_P_IP)) 260ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return 0; 261ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 26294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, skb->data, skb->len); 263ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ip = ip_hdr(skb); 264ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman switch (ip->tos & 0xfc) { 26594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger case 0x20: 26694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 2; 26794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger case 0x40: 26894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 1; 26994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger case 0x60: 27094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 3; 27194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger case 0x80: 27294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 4; 27394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger case 0xa0: 27494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 5; 27594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger case 0xc0: 27694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 6; 27794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger case 0xe0: 27894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 7; 27994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger default: 28094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 0; 281ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 282ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 283ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 284ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic void rtllib_tx_query_agg_cap(struct rtllib_device *ieee, 285ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Finger struct sk_buff *skb, 286ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Finger struct cb_desc *tcb_desc) 287ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 2887796d93eae46054d5a3bb5411fde735801998dc5Larry Finger struct rt_hi_throughput *pHTInfo = ieee->pHTInfo; 28960554f2bdb1579ca54631e99642025797f860eb7Larry Finger struct tx_ts_record *pTxTs = NULL; 290f38d223b692742e77c70033d145245615c8f3aa5Larry Finger struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr *)skb->data; 29194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 292f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (rtllib_act_scanning(ieee, false)) 29394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return; 294ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 295f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) 296ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 297ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (!IsQoSDataFrame(skb->data)) 298ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 299f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (is_multicast_ether_addr(hdr->addr1) || 300f38d223b692742e77c70033d145245615c8f3aa5Larry Finger is_broadcast_ether_addr(hdr->addr1)) 301ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 30265a4378471510787e080188f933913315f1afa0cdavid woo 303f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (tcb_desc->bdhcp || ieee->CntAfterLink < 2) 30494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return; 30565a4378471510787e080188f933913315f1afa0cdavid woo 30694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION) 30794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return; 30865a4378471510787e080188f933913315f1afa0cdavid woo 30994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) 310ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 311f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (pHTInfo->bCurrentAMPDUEnable) { 312f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1, 313f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb->priority, TX_DIR, true)) { 314f38d223b692742e77c70033d145245615c8f3aa5Larry Finger printk(KERN_INFO "%s: can't get TS\n", __func__); 315ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 316ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 317f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (pTxTs->TxAdmittedBARecord.bValid == false) { 318f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->wpa_ie_len && (ieee->pairwise_key_type == 319f38d223b692742e77c70033d145245615c8f3aa5Larry Finger KEY_TYPE_NA)) { 32094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger ; 321f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else if (tcb_desc->bdhcp == 1) { 32294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger ; 323f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else if (!pTxTs->bDisable_AddBa) { 32494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger TsStartAddBaProcess(ieee, pTxTs); 32594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 326ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto FORCED_AGG_SETTING; 32794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } else if (pTxTs->bUsingBa == false) { 328f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, 329f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (pTxTs->TxCurSeq+1)%4096)) 330ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pTxTs->bUsingBa = true; 331ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman else 332ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto FORCED_AGG_SETTING; 333ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 33494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (ieee->iw_mode == IW_MODE_INFRA) { 335ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bAMPDUEnable = true; 336ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor; 337ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity; 338ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 339ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 340ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanFORCED_AGG_SETTING: 34194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger switch (pHTInfo->ForcedAMPDUMode) { 342f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case HT_AGG_AUTO: 343f38d223b692742e77c70033d145245615c8f3aa5Larry Finger break; 344f38d223b692742e77c70033d145245615c8f3aa5Larry Finger 345f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case HT_AGG_FORCE_ENABLE: 346f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->bAMPDUEnable = true; 347f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity; 348f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor; 349f38d223b692742e77c70033d145245615c8f3aa5Larry Finger break; 350f38d223b692742e77c70033d145245615c8f3aa5Larry Finger 351f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case HT_AGG_FORCE_DISABLE: 352f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->bAMPDUEnable = false; 353f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->ampdu_density = 0; 354f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->ampdu_factor = 0; 355f38d223b692742e77c70033d145245615c8f3aa5Larry Finger break; 356ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 357f38d223b692742e77c70033d145245615c8f3aa5Larry Finger return; 358ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 359ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 360ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic void rtllib_qurey_ShortPreambleMode(struct rtllib_device *ieee, 361f38d223b692742e77c70033d145245615c8f3aa5Larry Finger struct cb_desc *tcb_desc) 362ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 363ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bUseShortPreamble = false; 364ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (tcb_desc->data_rate == 2) 365ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 366f38d223b692742e77c70033d145245615c8f3aa5Larry Finger else if (ieee->current_network.capability & 367f38d223b692742e77c70033d145245615c8f3aa5Larry Finger WLAN_CAPABILITY_SHORT_PREAMBLE) 368ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bUseShortPreamble = true; 369ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 370ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 37194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 372ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic void rtllib_query_HTCapShortGI(struct rtllib_device *ieee, 373f38d223b692742e77c70033d145245615c8f3aa5Larry Finger struct cb_desc *tcb_desc) 374ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 3757796d93eae46054d5a3bb5411fde735801998dc5Larry Finger struct rt_hi_throughput *pHTInfo = ieee->pHTInfo; 376ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 37794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bUseShortGI = false; 378ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 379f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) 380ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 381ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 382f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (pHTInfo->bForcedShortGI) { 383ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bUseShortGI = true; 384ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 385ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 386ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 387f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz) 388ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bUseShortGI = true; 389f38d223b692742e77c70033d145245615c8f3aa5Larry Finger else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz) 390ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bUseShortGI = true; 391ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 392ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 393ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic void rtllib_query_BandwidthMode(struct rtllib_device *ieee, 394ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Finger struct cb_desc *tcb_desc) 395ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 3967796d93eae46054d5a3bb5411fde735801998dc5Larry Finger struct rt_hi_throughput *pHTInfo = ieee->pHTInfo; 397ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 398ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bPacketBW = false; 399ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 400f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) 401ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 402ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 40394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (tcb_desc->bMulticast || tcb_desc->bBroadcast) 404ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 405ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 406f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if ((tcb_desc->data_rate & 0x80) == 0) 407ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 408f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && 409f38d223b692742e77c70033d145245615c8f3aa5Larry Finger !ieee->bandwidth_auto_switch.bforced_tx20Mhz) 410ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bPacketBW = true; 411ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 412ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 41394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 414ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic void rtllib_query_protectionmode(struct rtllib_device *ieee, 415ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Finger struct cb_desc *tcb_desc, 416ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Finger struct sk_buff *skb) 417ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 418ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bRTSSTBC = false; 41994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bRTSUseShortGI = false; 42094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bCTSEnable = false; 42194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->RTSSC = 0; 42294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bRTSBW = false; 423ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 42494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (tcb_desc->bBroadcast || tcb_desc->bMulticast) 425ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 426ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 42794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (is_broadcast_ether_addr(skb->data+16)) 428ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 429ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 430f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->mode < IEEE_N_24G) { 431f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (skb->len > ieee->rts) { 432ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bRTSEnable = true; 433ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->rts_rate = MGN_24M; 434f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else if (ieee->current_network.buseprotection) { 435ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bRTSEnable = true; 436ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bCTSEnable = true; 437ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->rts_rate = MGN_24M; 438ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 439ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 440f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else { 4417796d93eae46054d5a3bb5411fde735801998dc5Larry Finger struct rt_hi_throughput *pHTInfo = ieee->pHTInfo; 442f38d223b692742e77c70033d145245615c8f3aa5Larry Finger while (true) { 443f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) { 44494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bCTSEnable = true; 44594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->rts_rate = MGN_24M; 44694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bRTSEnable = true; 44794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger break; 448f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS | 449f38d223b692742e77c70033d145245615c8f3aa5Larry Finger HT_IOT_ACT_PURE_N_MODE)) { 45094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bRTSEnable = true; 45194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->rts_rate = MGN_24M; 45294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger break; 45394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 454f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->current_network.buseprotection) { 455ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bRTSEnable = true; 456ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bCTSEnable = true; 457ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->rts_rate = MGN_24M; 458ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman break; 459ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 460f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) { 461ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 HTOpMode = pHTInfo->CurrentOpMode; 462f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || 463f38d223b692742e77c70033d145245615c8f3aa5Larry Finger HTOpMode == 3)) || 464f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) { 46594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->rts_rate = MGN_24M; 466ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bRTSEnable = true; 467ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman break; 468ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 469ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 470f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (skb->len > ieee->rts) { 47194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->rts_rate = MGN_24M; 472ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bRTSEnable = true; 473ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman break; 474ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 475f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (tcb_desc->bAMPDUEnable) { 47694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->rts_rate = MGN_24M; 477ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bRTSEnable = false; 478ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman break; 479ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 480ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto NO_PROTECTION; 481ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 482ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 483ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) 484ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bUseShortPreamble = true; 48594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (ieee->iw_mode == IW_MODE_MASTER) 486ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto NO_PROTECTION; 487ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return; 488ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-HartmanNO_PROTECTION: 489ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bRTSEnable = false; 490ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bCTSEnable = false; 491f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->rts_rate = 0; 492ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->RTSSC = 0; 493f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->bRTSBW = false; 494ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 495ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 496ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 497ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Fingerstatic void rtllib_txrate_selectmode(struct rtllib_device *ieee, 498ec0dc6beea5436c037707dc0f501cf07878a8e2aLarry Finger struct cb_desc *tcb_desc) 499ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 50094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (ieee->bTxDisableRateFallBack) 501ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bTxDisableRateFallBack = true; 502ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 50394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (ieee->bTxUseDriverAssingedRate) 504ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bTxUseDriverAssingedRate = true; 505f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (!tcb_desc->bTxDisableRateFallBack || 506f38d223b692742e77c70033d145245615c8f3aa5Larry Finger !tcb_desc->bTxUseDriverAssingedRate) { 507f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->iw_mode == IW_MODE_INFRA || 508f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->iw_mode == IW_MODE_ADHOC) 509ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->RATRIndex = 0; 510ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 511ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 512ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 513f38d223b692742e77c70033d145245615c8f3aa5Larry Fingeru16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb, 514f38d223b692742e77c70033d145245615c8f3aa5Larry Finger u8 *dst) 515ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 51694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger u16 seqnum = 0; 51794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 518ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) 51994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 0; 520f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (IsQoSDataFrame(skb->data)) { 52160554f2bdb1579ca54631e99642025797f860eb7Larry Finger struct tx_ts_record *pTS = NULL; 522f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, 523f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb->priority, TX_DIR, true)) 52494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 0; 52594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger seqnum = pTS->TxCurSeq; 526ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096; 52794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return seqnum; 52894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 52994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return 0; 53094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger} 53194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 53294a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerstatic int wme_downgrade_ac(struct sk_buff *skb) 53394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger{ 53494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger switch (skb->priority) { 535f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case 6: 536f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case 7: 537f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb->priority = 5; /* VO -> VI */ 538f38d223b692742e77c70033d145245615c8f3aa5Larry Finger return 0; 539f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case 4: 540f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case 5: 541f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb->priority = 3; /* VI -> BE */ 542f38d223b692742e77c70033d145245615c8f3aa5Larry Finger return 0; 543f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case 0: 544f38d223b692742e77c70033d145245615c8f3aa5Larry Finger case 3: 545f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb->priority = 1; /* BE -> BK */ 546f38d223b692742e77c70033d145245615c8f3aa5Larry Finger return 0; 547f38d223b692742e77c70033d145245615c8f3aa5Larry Finger default: 548f38d223b692742e77c70033d145245615c8f3aa5Larry Finger return -1; 549ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 550ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 551ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 55294a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerint rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) 553ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman{ 554f38d223b692742e77c70033d145245615c8f3aa5Larry Finger struct rtllib_device *ieee = (struct rtllib_device *) 555f38d223b692742e77c70033d145245615c8f3aa5Larry Finger netdev_priv_rsl(dev); 55694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_txb *txb = NULL; 55794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_hdr_3addrqos *frag_hdr; 558ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; 559ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman unsigned long flags; 560ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman struct net_device_stats *stats = &ieee->stats; 561ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int ether_type = 0, encrypt; 562ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int bytes, fc, qos_ctl = 0, hdr_len; 563ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman struct sk_buff *skb_frag; 56494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */ 565ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman .duration_id = 0, 566ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman .seq_ctl = 0, 567ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman .qos_ctl = 0 568ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman }; 569ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman u8 dest[ETH_ALEN], src[ETH_ALEN]; 570ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman int qos_actived = ieee->current_network.qos_data.active; 57132c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan struct lib80211_crypt_data *crypt = NULL; 5723b83db43ccbb26863f38caccc1e7fae370f31e57Larry Finger struct cb_desc *tcb_desc; 57394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger u8 bIsMulticast = false; 57494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger u8 IsAmsdu = false; 575f38d223b692742e77c70033d145245615c8f3aa5Larry Finger bool bdhcp = false; 576ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 577ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman spin_lock_irqsave(&ieee->lock, flags); 578ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 579ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* If there is no driver handler to take the TXB, dont' bother 580ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * creating it... */ 581f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if ((!ieee->hard_start_xmit && !(ieee->softmac_features & 582f38d223b692742e77c70033d145245615c8f3aa5Larry Finger IEEE_SOFTMAC_TX_QUEUE)) || 583f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ((!ieee->softmac_data_hard_start_xmit && 584f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { 585ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman printk(KERN_WARNING "%s: No xmit handler.\n", 586ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ieee->dev->name); 587ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto success; 588ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 589ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 590ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 591f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (likely(ieee->raw_tx == 0)) { 592ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { 593ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman printk(KERN_WARNING "%s: skb too small (%d).\n", 594ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ieee->dev->name, skb->len); 595ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto success; 596ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 59794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger /* Save source and destination addresses */ 59894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger memcpy(dest, skb->data, ETH_ALEN); 59994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger memcpy(src, skb->data+ETH_ALEN, ETH_ALEN); 600ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 601ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memset(skb->cb, 0, sizeof(skb->cb)); 602ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); 603ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 604f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->iw_mode == IW_MODE_MONITOR) { 60594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); 60694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (unlikely(!txb)) { 607f38d223b692742e77c70033d145245615c8f3aa5Larry Finger printk(KERN_WARNING "%s: Could not allocate " 608f38d223b692742e77c70033d145245615c8f3aa5Larry Finger "TXB\n", 60994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger ieee->dev->name); 61094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger goto failed; 61194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 612ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 61394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger txb->encrypted = 0; 61494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger txb->payload_size = skb->len; 615f38d223b692742e77c70033d145245615c8f3aa5Larry Finger memcpy(skb_put(txb->fragments[0], skb->len), skb->data, 616f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb->len); 617ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 618ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto success; 619ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 620ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 62155dc4eb35f7c191db2767c887c158a8de0e6e4f7Larry Finger if (skb->len > 282) { 62294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (ETH_P_IP == ether_type) { 623f38d223b692742e77c70033d145245615c8f3aa5Larry Finger const struct iphdr *ip = (struct iphdr *) 624f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ((u8 *)skb->data+14); 62594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (IPPROTO_UDP == ip->protocol) { 626f38d223b692742e77c70033d145245615c8f3aa5Larry Finger struct udphdr *udp; 627f38d223b692742e77c70033d145245615c8f3aa5Larry Finger 628f38d223b692742e77c70033d145245615c8f3aa5Larry Finger udp = (struct udphdr *)((u8 *)ip + 629f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (ip->ihl << 2)); 630f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (((((u8 *)udp)[1] == 68) && 631f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (((u8 *)udp)[3] == 67)) || 632f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ((((u8 *)udp)[1] == 67) && 633f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (((u8 *)udp)[3] == 68))) { 63465a4378471510787e080188f933913315f1afa0cdavid woo bdhcp = true; 63594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger ieee->LPSDelayCnt = 200; 63665a4378471510787e080188f933913315f1afa0cdavid woo } 63765a4378471510787e080188f933913315f1afa0cdavid woo } 638f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else if (ETH_P_ARP == ether_type) { 639f38d223b692742e77c70033d145245615c8f3aa5Larry Finger printk(KERN_INFO "=================>DHCP " 640f38d223b692742e77c70033d145245615c8f3aa5Larry Finger "Protocol start tx ARP pkt!!\n"); 64194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger bdhcp = true; 642f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->LPSDelayCnt = 643f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->current_network.tim.tim_count; 64465a4378471510787e080188f933913315f1afa0cdavid woo } 64594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 64665a4378471510787e080188f933913315f1afa0cdavid woo 64794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger skb->priority = rtllib_classify(skb, IsAmsdu); 6480ddcf5fdfac6bd80e153ee5c405bdfc9cb868b95Sean MacLennan crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; 64994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && 65094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger ieee->host_encrypt && crypt && crypt->ops; 65194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (!encrypt && ieee->ieee802_1x && 652f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->drop_unencrypted && ether_type != ETH_P_PAE) { 65394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger stats->tx_dropped++; 65494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger goto success; 65594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 65694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (crypt && !encrypt && ether_type == ETH_P_PAE) { 65794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger struct eapol *eap = (struct eapol *)(skb->data + 658f38d223b692742e77c70033d145245615c8f3aa5Larry Finger sizeof(struct ethhdr) - SNAP_SIZE - 659f38d223b692742e77c70033d145245615c8f3aa5Larry Finger sizeof(u16)); 66094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", 66194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger eap_get_type(eap->type)); 66294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 663ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 66494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger /* Advance the SKB to the start of the payload */ 66594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger skb_pull(skb, sizeof(struct ethhdr)); 666ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 667f38d223b692742e77c70033d145245615c8f3aa5Larry Finger /* Determine total amount of storage required for TXB packets */ 66894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger bytes = skb->len + SNAP_SIZE + sizeof(u16); 669ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 670ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (encrypt) 67194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP; 672ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman else 67394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger fc = RTLLIB_FTYPE_DATA; 674ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 67594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (qos_actived) 67694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger fc |= RTLLIB_STYPE_QOS_DATA; 677ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman else 67894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger fc |= RTLLIB_STYPE_DATA; 679ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 680ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (ieee->iw_mode == IW_MODE_INFRA) { 68194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger fc |= RTLLIB_FCTL_TODS; 682ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* To DS: Addr1 = BSSID, Addr2 = SA, 683ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman Addr3 = DA */ 684f38d223b692742e77c70033d145245615c8f3aa5Larry Finger memcpy(&header.addr1, ieee->current_network.bssid, 685f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ETH_ALEN); 686ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(&header.addr2, &src, ETH_ALEN); 68794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (IsAmsdu) 688f38d223b692742e77c70033d145245615c8f3aa5Larry Finger memcpy(&header.addr3, 689f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->current_network.bssid, ETH_ALEN); 69094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger else 69194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger memcpy(&header.addr3, &dest, ETH_ALEN); 692ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } else if (ieee->iw_mode == IW_MODE_ADHOC) { 693ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* not From/To DS: Addr1 = DA, Addr2 = SA, 694ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman Addr3 = BSSID */ 695ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(&header.addr1, dest, ETH_ALEN); 696ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(&header.addr2, src, ETH_ALEN); 697f38d223b692742e77c70033d145245615c8f3aa5Larry Finger memcpy(&header.addr3, ieee->current_network.bssid, 698f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ETH_ALEN); 699ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 700ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 701f38d223b692742e77c70033d145245615c8f3aa5Larry Finger bIsMulticast = is_broadcast_ether_addr(header.addr1) || 702f38d223b692742e77c70033d145245615c8f3aa5Larry Finger is_multicast_ether_addr(header.addr1); 70394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 704f38d223b692742e77c70033d145245615c8f3aa5Larry Finger header.frame_ctl = cpu_to_le16(fc); 705ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 706ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Determine fragmentation size based on destination (multicast 707ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * and broadcast are not fragmented) */ 70894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (bIsMulticast) { 709ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman frag_size = MAX_FRAG_THRESHOLD; 710ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; 71194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } else { 71294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger frag_size = ieee->fts; 713ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman qos_ctl = 0; 714ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 715ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 71694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (qos_actived) { 71794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger hdr_len = RTLLIB_3ADDR_LEN + 2; 71894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 719f38d223b692742e77c70033d145245615c8f3aa5Larry Finger /* in case we are a client verify acm is not set for this ac */ 720f38d223b692742e77c70033d145245615c8f3aa5Larry Finger while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { 721f38d223b692742e77c70033d145245615c8f3aa5Larry Finger printk(KERN_INFO "skb->priority = %x\n", skb->priority); 722f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (wme_downgrade_ac(skb)) 723f38d223b692742e77c70033d145245615c8f3aa5Larry Finger break; 724f38d223b692742e77c70033d145245615c8f3aa5Larry Finger printk(KERN_INFO "converted skb->priority = %x\n", 725f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb->priority); 726f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } 727f38d223b692742e77c70033d145245615c8f3aa5Larry Finger qos_ctl |= skb->priority; 728f38d223b692742e77c70033d145245615c8f3aa5Larry Finger header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID); 729ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } else { 73094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger hdr_len = RTLLIB_3ADDR_LEN; 731ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 732ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Determine amount of payload per fragment. Regardless of if 733f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * this stack is providing the full 802.11 header, one will 734f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * eventually be affixed to this fragment -- so we must account 735f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * for it when determining the amount of payload space. */ 736ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman bytes_per_frag = frag_size - hdr_len; 737ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (ieee->config & 738f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) 73994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger bytes_per_frag -= RTLLIB_FCS_LEN; 740ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 741f38d223b692742e77c70033d145245615c8f3aa5Larry Finger /* Each fragment may need to have room for encryptiong 742f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * pre/postfix */ 74394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (encrypt) { 74432c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len + 74532c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan crypt->ops->extra_mpdu_postfix_len + 74632c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan crypt->ops->extra_msdu_prefix_len + 74732c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan crypt->ops->extra_msdu_postfix_len; 74894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 749ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Number of fragments is the total bytes_per_frag / 750ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman * payload_per_fragment */ 751ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman nr_frags = bytes / bytes_per_frag; 752ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman bytes_last_frag = bytes % bytes_per_frag; 753ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (bytes_last_frag) 754ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman nr_frags++; 755ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman else 756ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman bytes_last_frag = bytes_per_frag; 757ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 758f38d223b692742e77c70033d145245615c8f3aa5Larry Finger /* When we allocate the TXB we allocate enough space for the 759f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * reserve and full fragment bytes (bytes_per_frag doesn't 760f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * include prefix, postfix, header, FCS, etc.) */ 761f38d223b692742e77c70033d145245615c8f3aa5Larry Finger txb = rtllib_alloc_txb(nr_frags, frag_size + 762f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->tx_headroom, GFP_ATOMIC); 763ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (unlikely(!txb)) { 764ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman printk(KERN_WARNING "%s: Could not allocate TXB\n", 765ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ieee->dev->name); 766ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto failed; 767ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 768ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman txb->encrypted = encrypt; 769ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman txb->payload_size = bytes; 770ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 77194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (qos_actived) 772ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman txb->queue_index = UP2AC(skb->priority); 773f38d223b692742e77c70033d145245615c8f3aa5Larry Finger else 774f38d223b692742e77c70033d145245615c8f3aa5Larry Finger txb->queue_index = WME_AC_BE; 775ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 776ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman for (i = 0; i < nr_frags; i++) { 777ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman skb_frag = txb->fragments[i]; 778f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc = (struct cb_desc *)(skb_frag->cb + 779f38d223b692742e77c70033d145245615c8f3aa5Larry Finger MAX_DEV_ADDR_SIZE); 780f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (qos_actived) { 78194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger skb_frag->priority = skb->priority; 782ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->queue_index = UP2AC(skb->priority); 783ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } else { 78494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger skb_frag->priority = WME_AC_BE; 78594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->queue_index = WME_AC_BE; 786ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 787ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman skb_reserve(skb_frag, ieee->tx_headroom); 788ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 789f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (encrypt) { 790ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (ieee->hwsec_active) 791ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bHwSec = 1; 792ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman else 793ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bHwSec = 0; 794f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb_reserve(skb_frag, 79532c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan crypt->ops->extra_mpdu_prefix_len + 79632c44cb5b9fdc6eaa445bd622008dd672a3dd1a7Sean MacLennan crypt->ops->extra_msdu_prefix_len); 79794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } else { 798ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bHwSec = 0; 799ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 800f38d223b692742e77c70033d145245615c8f3aa5Larry Finger frag_hdr = (struct rtllib_hdr_3addrqos *) 801f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb_put(skb_frag, hdr_len); 802ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(frag_hdr, &header, hdr_len); 803ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 804f38d223b692742e77c70033d145245615c8f3aa5Larry Finger /* If this is not the last fragment, then add the 805f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * MOREFRAGS bit to the frame control */ 806ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (i != nr_frags - 1) { 807ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman frag_hdr->frame_ctl = cpu_to_le16( 80894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger fc | RTLLIB_FCTL_MOREFRAGS); 809ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman bytes = bytes_per_frag; 810ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 811ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } else { 812f38d223b692742e77c70033d145245615c8f3aa5Larry Finger /* The last fragment has the remaining length */ 813ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman bytes = bytes_last_frag; 814ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 815f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if ((qos_actived) && (!bIsMulticast)) { 816f38d223b692742e77c70033d145245615c8f3aa5Larry Finger frag_hdr->seq_ctl = 817f38d223b692742e77c70033d145245615c8f3aa5Larry Finger rtllib_query_seqnum(ieee, skb_frag, 818f38d223b692742e77c70033d145245615c8f3aa5Larry Finger header.addr1); 819f38d223b692742e77c70033d145245615c8f3aa5Larry Finger frag_hdr->seq_ctl = 820f38d223b692742e77c70033d145245615c8f3aa5Larry Finger cpu_to_le16(frag_hdr->seq_ctl<<4 | i); 821ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } else { 822f38d223b692742e77c70033d145245615c8f3aa5Larry Finger frag_hdr->seq_ctl = 823f38d223b692742e77c70033d145245615c8f3aa5Larry Finger cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); 824ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 825ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Put a SNAP header on the first fragment */ 826ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (i == 0) { 82794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_put_snap( 828f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb_put(skb_frag, SNAP_SIZE + 829f38d223b692742e77c70033d145245615c8f3aa5Larry Finger sizeof(u16)), ether_type); 830ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman bytes -= SNAP_SIZE + sizeof(u16); 831ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 832ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 833ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman memcpy(skb_put(skb_frag, bytes), skb->data, bytes); 834ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 835ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman /* Advance the SKB... */ 836ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman skb_pull(skb, bytes); 837ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 838f38d223b692742e77c70033d145245615c8f3aa5Larry Finger /* Encryption routine will move the header forward in 839f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * order to insert the IV between the header and the 840f38d223b692742e77c70033d145245615c8f3aa5Larry Finger * payload */ 841ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (encrypt) 842f38d223b692742e77c70033d145245615c8f3aa5Larry Finger rtllib_encrypt_fragment(ieee, skb_frag, 843f38d223b692742e77c70033d145245615c8f3aa5Larry Finger hdr_len); 844ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (ieee->config & 845f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) 846ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman skb_put(skb_frag, 4); 847ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 848ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 84994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if ((qos_actived) && (!bIsMulticast)) { 850f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) 851f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; 852f38d223b692742e77c70033d145245615c8f3aa5Larry Finger else 853f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; 854ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } else { 855f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->seq_ctrl[0] == 0xFFF) 856f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->seq_ctrl[0] = 0; 857f38d223b692742e77c70033d145245615c8f3aa5Larry Finger else 858f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->seq_ctrl[0]++; 859ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 860f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else { 86194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) { 862ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman printk(KERN_WARNING "%s: skb too small (%d).\n", 863ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ieee->dev->name, skb->len); 864ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto success; 865ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 866ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 86794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); 868f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (!txb) { 869ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman printk(KERN_WARNING "%s: Could not allocate TXB\n", 870ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman ieee->dev->name); 871ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman goto failed; 872ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 873ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 874ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman txb->encrypted = 0; 875ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman txb->payload_size = skb->len; 876f38d223b692742e77c70033d145245615c8f3aa5Larry Finger memcpy(skb_put(txb->fragments[0], skb->len), skb->data, 877f38d223b692742e77c70033d145245615c8f3aa5Larry Finger skb->len); 878ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 879ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 880ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman success: 881f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (txb) { 882f38d223b692742e77c70033d145245615c8f3aa5Larry Finger struct cb_desc *tcb_desc = (struct cb_desc *) 883f38d223b692742e77c70033d145245615c8f3aa5Larry Finger (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); 884ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman tcb_desc->bTxEnableFwCalcDur = 1; 88594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->priority = skb->priority; 88665a4378471510787e080188f933913315f1afa0cdavid woo 88794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (ether_type == ETH_P_PAE) { 888f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->pHTInfo->IOTAction & 889f38d223b692742e77c70033d145245615c8f3aa5Larry Finger HT_IOT_ACT_WA_IOT_Broadcom) { 890f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->data_rate = 891f38d223b692742e77c70033d145245615c8f3aa5Larry Finger MgntQuery_TxRateExcludeCCKRates(ieee); 89294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bTxDisableRateFallBack = false; 893f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else { 89494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->data_rate = ieee->basic_rate; 89565a4378471510787e080188f933913315f1afa0cdavid woo tcb_desc->bTxDisableRateFallBack = 1; 89694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 89794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 89865a4378471510787e080188f933913315f1afa0cdavid woo 89965a4378471510787e080188f933913315f1afa0cdavid woo tcb_desc->RATRIndex = 7; 90065a4378471510787e080188f933913315f1afa0cdavid woo tcb_desc->bTxUseDriverAssingedRate = 1; 90194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } else { 90294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (is_multicast_ether_addr(header.addr1)) 90394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bMulticast = 1; 90494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if (is_broadcast_ether_addr(header.addr1)) 90594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bBroadcast = 1; 90694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_txrate_selectmode(ieee, tcb_desc); 907f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (tcb_desc->bMulticast || tcb_desc->bBroadcast) 90894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->data_rate = ieee->basic_rate; 90994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger else 910f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->data_rate = CURRENT_RATE(ieee->mode, 911f38d223b692742e77c70033d145245615c8f3aa5Larry Finger ieee->rate, ieee->HTCurrentOperaRate); 912f38d223b692742e77c70033d145245615c8f3aa5Larry Finger 913f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (bdhcp == true) { 914f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->pHTInfo->IOTAction & 915f38d223b692742e77c70033d145245615c8f3aa5Larry Finger HT_IOT_ACT_WA_IOT_Broadcom) { 916f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc->data_rate = 917f38d223b692742e77c70033d145245615c8f3aa5Larry Finger MgntQuery_TxRateExcludeCCKRates(ieee); 91894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bTxDisableRateFallBack = false; 919f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else { 92094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->data_rate = MGN_1M; 92194a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bTxDisableRateFallBack = 1; 92294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 92365a4378471510787e080188f933913315f1afa0cdavid woo 92465a4378471510787e080188f933913315f1afa0cdavid woo 92594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->RATRIndex = 7; 92694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bTxUseDriverAssingedRate = 1; 92794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger tcb_desc->bdhcp = 1; 92894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 92994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger 93094a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); 931f38d223b692742e77c70033d145245615c8f3aa5Larry Finger rtllib_tx_query_agg_cap(ieee, txb->fragments[0], 932f38d223b692742e77c70033d145245615c8f3aa5Larry Finger tcb_desc); 93394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_query_HTCapShortGI(ieee, tcb_desc); 93494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_query_BandwidthMode(ieee, tcb_desc); 935f38d223b692742e77c70033d145245615c8f3aa5Larry Finger rtllib_query_protectionmode(ieee, tcb_desc, 936f38d223b692742e77c70033d145245615c8f3aa5Larry Finger txb->fragments[0]); 93794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger } 938ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 939ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman spin_unlock_irqrestore(&ieee->lock, flags); 940ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman dev_kfree_skb_any(skb); 941ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman if (txb) { 942f38d223b692742e77c70033d145245615c8f3aa5Larry Finger if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) { 94394a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger dev->stats.tx_packets++; 94494a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger dev->stats.tx_bytes += txb->payload_size; 94594a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_softmac_xmit(txb, ieee); 946f38d223b692742e77c70033d145245615c8f3aa5Larry Finger } else { 94794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger if ((*ieee->hard_start_xmit)(txb, dev) == 0) { 948ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman stats->tx_packets++; 949ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman stats->tx_bytes += txb->payload_size; 950ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return 0; 951ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 95294a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger rtllib_txb_free(txb); 953ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 954ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman } 955ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 956ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return 0; 957ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 958ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman failed: 959ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman spin_unlock_irqrestore(&ieee->lock, flags); 960ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman netif_stop_queue(dev); 961ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman stats->tx_errors++; 962ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman return 1; 963ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman 964ecdfa44610fa18678c3dd481af75368b9800c6c7Greg Kroah-Hartman} 96594a799425eee8225a1e3fbe5f473d2ef04002577Larry Fingerint rtllib_xmit(struct sk_buff *skb, struct net_device *dev) 96694a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger{ 96794a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger memset(skb->cb, 0, sizeof(skb->cb)); 96894a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger return rtllib_xmit_inter(skb, dev); 96994a799425eee8225a1e3fbe5f473d2ef04002577Larry Finger} 9703b28499c5519e59fbe9c2dea49ece5a3665be787Sean MacLennanEXPORT_SYMBOL(rtllib_xmit); 971