18fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang/****************************************************************************** 28fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 38fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. 48fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 58fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang This program is free software; you can redistribute it and/or modify it 68fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang under the terms of version 2 of the GNU General Public License as 78fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang published by the Free Software Foundation. 88fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 98fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang This program is distributed in the hope that it will be useful, but WITHOUT 108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang more details. 138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang You should have received a copy of the GNU General Public License along with 158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang this program; if not, write to the Free Software Foundation, Inc., 59 168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Temple Place - Suite 330, Boston, MA 02111-1307, USA. 178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang The full GNU General Public License is included in this distribution in the 198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang file called LICENSE. 208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Contact Information: 228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang James P. Ketrenos <ipw2100-admin@linux.intel.com> 238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang****************************************************************************** 268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Few modifications for Realtek's Wi-Fi drivers by 288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Andrea Merello <andreamrl@tiscali.it> 298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang A special thanks goes to Realtek for their support ! 318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang******************************************************************************/ 338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/compiler.h> 358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang//#include <linux/config.h> 368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/errno.h> 378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/if_arp.h> 388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/in6.h> 398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/in.h> 408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/ip.h> 418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/kernel.h> 428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/module.h> 438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/netdevice.h> 448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/pci.h> 458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/proc_fs.h> 468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/skbuff.h> 478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/slab.h> 488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/tcp.h> 498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/types.h> 508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/wireless.h> 518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/etherdevice.h> 528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <asm/uaccess.h> 538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include <linux/if_vlan.h> 548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#include "ieee80211.h" 568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang/* 598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang802.11 Data Frame 628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang802.11 frame_contorl for data frames - 2 bytes 658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ,-----------------------------------------------------------------------------------------. 668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangbits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | 678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| 688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangval | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | 698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| 708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangdesc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep | 718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | | 728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang '-----------------------------------------------------------------------------------------' 738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /\ 748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | 758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang802.11 Data Frame | 768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ,--------- 'ctrl' expands to >-----------' 778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | 788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ,--'---,-------------------------------------------------------------. 798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangBytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | 808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang |------|------|---------|---------|---------|------|---------|------| 818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangDesc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | 828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | | tion | (BSSID) | | | ence | data | | 838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang `--------------------------------------------------| |------' 848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangTotal: 28 non-data bytes `----.----' 858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | 868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .- 'Frame data' expands to <---------------------------' 878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | 888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang V 898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ,---------------------------------------------------. 908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangBytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | 918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang |------|------|---------|----------|------|---------| 928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangDesc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | 938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | DSAP | SSAP | | | | Packet | 948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | 958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang `-----------------------------------------| | 968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangTotal: 8 non-data bytes `----.----' 978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | 988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .- 'IP Packet' expands, if WEP enabled, to <--' 998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | 1008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang V 1018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ,-----------------------. 1028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangBytes | 4 | 0-2296 | 4 | 1038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang |-----|-----------|-----| 1048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangDesc. | IV | Encrypted | ICV | 1058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | | IP Packet | | 1068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang `-----------------------' 1078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangTotal: 8 non-data bytes 1088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang802.3 Ethernet Data Frame 1118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ,-----------------------------------------. 1138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangBytes | 6 | 6 | 2 | Variable | 4 | 1148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang |-------|-------|------|-----------|------| 1158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangDesc. | Dest. | Source| Type | IP Packet | fcs | 1168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang | MAC | MAC | | | | 1178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang `-----------------------------------------' 1188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangTotal: 18 non-data bytes 1198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangIn the event that fragmentation is required, the incoming payload is split into 1218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangN parts of size ieee->fts. The first fragment contains the SNAP header and the 1228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangremaining packets are just data. 1238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangIf encryption is enabled, each fragment payload size is reduced by enough space 1258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangto add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) 1268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangSo if you have 1500 bytes of payload with ieee->fts set to 500 without 1278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangencryption it will take 3 frames. With WEP it will take 4 frames as the 1288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangpayload of each frame is reduced to 492 bytes. 1298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* SKB visualization 1318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* 1328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* ,- skb->data 1338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | 1348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | ETHERNET HEADER ,-<-- PAYLOAD 1358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | | 14 bytes from skb->data 1368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | 2 bytes for Type --> ,T. | (sizeof ethhdr) 1378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | | | | 1388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* |,-Dest.--. ,--Src.---. | | | 1398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | 6 bytes| | 6 bytes | | | | 1408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* v | | | | | | 1418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* 0 | v 1 | v | v 2 1428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* 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 1438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* ^ | ^ | ^ | 1448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | | | | | | 1458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | | | | `T' <---- 2 bytes for Type 1468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | | | | 1478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | | '---SNAP--' <-------- 6 bytes for SNAP 1488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* | | 1498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* `-IV--' <-------------------- 4 bytes for IV (WEP) 1508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* 1518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* SNAP HEADER 1528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang* 1538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang*/ 1548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; 1568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; 1578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic inline int ieee80211_put_snap(u8 *data, u16 h_proto) 1598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_snap_hdr *snap; 1618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 *oui; 1628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang snap = (struct ieee80211_snap_hdr *)data; 1648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang snap->dsap = 0xaa; 1658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang snap->ssap = 0xaa; 1668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang snap->ctrl = 0x03; 1678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (h_proto == 0x8137 || h_proto == 0x80f3) 1698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang oui = P802_1H_OUI; 1708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 1718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang oui = RFC1042_OUI; 1728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang snap->oui[0] = oui[0]; 1738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang snap->oui[1] = oui[1]; 1748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang snap->oui[2] = oui[2]; 1758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang *(u16 *)(data + SNAP_SIZE) = htons(h_proto); 1778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return SNAP_SIZE + sizeof(u16); 1798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 1808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangint ieee80211_encrypt_fragment( 1828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_device *ieee, 1838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct sk_buff *frag, 1848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int hdr_len) 1858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 1868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx]; 1878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int res; 1888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!(crypt && crypt->ops)) 1908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 1918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk("=========>%s(), crypt is null\n", __FUNCTION__); 1928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 1938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 1948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#ifdef CONFIG_IEEE80211_CRYPT_TKIP 1958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr *header; 1968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 1978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->tkip_countermeasures && 1988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { 1998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang header = (struct ieee80211_hdr *) frag->data; 2008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (net_ratelimit()) { 2018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " 2020ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches "TX packet to %pM\n", 2030ee9f67c4028500a4348e8bc87ee7ec1139b8259Joe Perches ieee->dev->name, header->addr1); 2048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 2058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 2068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 2078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#endif 2088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* To encrypt, frame format is: 2098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ 2108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption. 2128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so 2138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * call both MSDU and MPDU encryption functions from here. */ 2148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang atomic_inc(&crypt->refcnt); 2158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang res = 0; 2168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (crypt->ops->encrypt_msdu) 2178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); 2188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (res == 0 && crypt->ops->encrypt_mpdu) 2198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); 2208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang atomic_dec(&crypt->refcnt); 2228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (res < 0) { 2238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_INFO "%s: Encryption failed: len=%d.\n", 2248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->dev->name, frag->len); 2258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->ieee_stats.tx_discards++; 2268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return -1; 2278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 2288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 2308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 2318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid ieee80211_txb_free(struct ieee80211_txb *txb) { 2348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //int i; 2358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (unlikely(!txb)) 2368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 2378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang kfree(txb); 2388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 2398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstruct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, 2418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int gfp_mask) 2428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 2438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_txb *txb; 2448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int i; 2458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb = kmalloc( 2468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags), 2478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang gfp_mask); 2488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!txb) 2498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return NULL; 2508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memset(txb, 0, sizeof(struct ieee80211_txb)); 2528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb->nr_frags = nr_frags; 2538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb->frag_size = txb_size; 2548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang for (i = 0; i < nr_frags; i++) { 2568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb->fragments[i] = dev_alloc_skb(txb_size); 2578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (unlikely(!txb->fragments[i])) { 2588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang i--; 2598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 2608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 2618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb)); 2628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 2638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (unlikely(i != nr_frags)) { 2648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang while (i >= 0) 2658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang dev_kfree_skb_any(txb->fragments[i--]); 2668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang kfree(txb); 2678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return NULL; 2688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 2698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return txb; 2708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 2718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang// Classify the to-be send data packet 2738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang// Need to acquire the sent queue index. 2748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangstatic int 2758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network) 2768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 2778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ethhdr *eth; 2788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct iphdr *ip; 2798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eth = (struct ethhdr *)skb->data; 2808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (eth->h_proto != htons(ETH_P_IP)) 2818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 2828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 2838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len); 2848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ip = ip_hdr(skb); 2858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang switch (ip->tos & 0xfc) { 2868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case 0x20: 2878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 2; 2888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case 0x40: 2898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 1; 2908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case 0x60: 2918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 3; 2928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case 0x80: 2938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 4; 2948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case 0xa0: 2958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 5; 2968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case 0xc0: 2978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 6; 2988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case 0xe0: 2998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 7; 3008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang default: 3018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 3028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 3048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#define SN_LESS(a, b) (((a-b)&0x800)!=0) 3068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc) 3078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 3088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; 3098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PTX_TS_RECORD pTxTs = NULL; 3108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data; 3118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) 3138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!IsQoSDataFrame(skb->data)) 3158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)) 3188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //check packet and mode later 3208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#ifdef TO_DO_LIST 3218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(pTcb->PacketLength >= 4096) 3228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation. 3248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) 3258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#endif 3278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(!ieee->GetNmodeSupportBySecCfg(ieee->dev)) 3288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(pHTInfo->bCurrentAMPDUEnable) 3328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)) 3348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk("===>can't get TS\n"); 3368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (pTxTs->TxAdmittedBARecord.bValid == false) 3398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang TsStartAddBaProcess(ieee, pTxTs); 3418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto FORCED_AGG_SETTING; 3428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else if (pTxTs->bUsingBa == false) 3448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096)) 3468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pTxTs->bUsingBa = true; 3478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 3488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto FORCED_AGG_SETTING; 3498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->iw_mode == IW_MODE_INFRA) 3528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bAMPDUEnable = true; 3548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor; 3558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity; 3568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangFORCED_AGG_SETTING: 3598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang switch(pHTInfo->ForcedAMPDUMode ) 3608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case HT_AGG_AUTO: 3628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 3638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case HT_AGG_FORCE_ENABLE: 3658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bAMPDUEnable = true; 3668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity; 3678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor; 3688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 3698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang case HT_AGG_FORCE_DISABLE: 3718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bAMPDUEnable = false; 3728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->ampdu_density = 0; 3738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->ampdu_factor = 0; 3748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 3758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 3798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangextern void ieee80211_qurey_ShortPreambleMode(struct ieee80211_device* ieee, cb_desc* tcb_desc) 3818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 3828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bUseShortPreamble = false; 3838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (tcb_desc->data_rate == 2) 3848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang {//// 1M can only use Long Preamble. 11B spec 3858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) 3888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 3898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bUseShortPreamble = true; 3908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 3918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 3928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 3938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangextern void 3948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, cb_desc *tcb_desc) 3958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 3968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; 3978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 3988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bUseShortGI = false; 3998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) 4018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(pHTInfo->bForcedShortGI) 4048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bUseShortGI = true; 4068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz) 4108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bUseShortGI = true; 4118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz) 4128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bUseShortGI = true; 4138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 4148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid ieee80211_query_BandwidthMode(struct ieee80211_device* ieee, cb_desc *tcb_desc) 4168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 4178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; 4188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bPacketBW = false; 4208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) 4228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(tcb_desc->bMulticast || tcb_desc->bBroadcast) 4258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel. 4288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance 4308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) 4318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bPacketBW = true; 4328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 4348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid ieee80211_query_protectionmode(struct ieee80211_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb) 4368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 4378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // Common Settings 4388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSSTBC = false; 4398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSUseShortGI = false; // Since protection frames are always sent by legacy rate, ShortGI will never be used. 4408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bCTSEnable = false; // Most of protection using RTS/CTS 4418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate. 4428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz 4438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts 4458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA. 4488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 4508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->mode < IEEE_N_24G) //b, g mode 4518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // (1) RTS_Threshold is compared to the MPDU, not MSDU. 4538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. 4548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // Other fragments are protected by previous fragment. 4558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // So we only need to check the length of first fragment. 4568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (skb->len > ieee->rts) 4578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = true; 4598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = MGN_24M; 4608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else if (ieee->current_network.buseprotection) 4628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // Use CTS-to-SELF in protection mode. 4648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = true; 4658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bCTSEnable = true; 4668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = MGN_24M; 4678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //otherwise return; 4698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 4708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 4728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang {// 11n High throughput case. 4738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; 4748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang while (true) 4758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //check ERP protection 4778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->current_network.buseprotection) 4788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang {// CTS-to-SELF 4798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = true; 4808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bCTSEnable = true; 4818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = MGN_24M; 4828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 4838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //check HT op mode 4858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) 4868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 HTOpMode = pHTInfo->CurrentOpMode; 4888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || 4898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (!pHTInfo->bCurBW40MHz && HTOpMode == 3) ) 4908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. 4928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = true; 4938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 4948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 4968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //check rts 4978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (skb->len > ieee->rts) 4988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 4998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. 5008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = true; 5018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 5028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //to do list: check MIMO power save condition. 5048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //check AMPDU aggregation for TXOP 5058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(tcb_desc->bAMPDUEnable) 5068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 5078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. 5088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads 5098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily 5108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = false; 5118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 5128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //check IOT action 5148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) 5158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 5168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bCTSEnable = true; 5178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = MGN_24M; 5188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = true; 5198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang break; 5208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // Totally no protection case!! 5228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto NO_PROTECTION; 5238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // For test , CTS replace with RTS 5268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if( 0 ) 5278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 5288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bCTSEnable = true; 5298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = MGN_24M; 5308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = true; 5318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) 5338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bUseShortPreamble = true; 5348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->mode == IW_MODE_MASTER) 5358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto NO_PROTECTION; 5368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 5378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangNO_PROTECTION: 5388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSEnable = false; 5398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bCTSEnable = false; 5408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->rts_rate = 0; 5418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->RTSSC = 0; 5428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bRTSBW = false; 5438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 5448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid ieee80211_txrate_selectmode(struct ieee80211_device* ieee, cb_desc* tcb_desc) 5478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 5488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#ifdef TO_DO_LIST 5498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(!IsDataFrame(pFrame)) 5508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 5518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pTcb->bTxDisableRateFallBack = TRUE; 5528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pTcb->bTxUseDriverAssingedRate = TRUE; 5538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pTcb->RATRIndex = 7; 5548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 5558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(pMgntInfo->ForcedDataRate!= 0) 5588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 5598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pTcb->bTxDisableRateFallBack = TRUE; 5608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pTcb->bTxUseDriverAssingedRate = TRUE; 5618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 5628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang#endif 5648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(ieee->bTxDisableRateFallBack) 5658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bTxDisableRateFallBack = true; 5668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(ieee->bTxUseDriverAssingedRate) 5688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bTxUseDriverAssingedRate = true; 5698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) 5708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 5718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) 5728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->RATRIndex = 0; 5738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 5758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangvoid ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst) 5778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 5788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) 5798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 5808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (IsQoSDataFrame(skb->data)) //we deal qos data only 5818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 5828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang PTX_TS_RECORD pTS = NULL; 5838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true)) 5848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 5858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return; 5868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096; 5888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 5898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 5908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 5918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuangint ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) 5928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang{ 5938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_device *ieee = netdev_priv(dev); 5948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_txb *txb = NULL; 5958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_3addrqos *frag_hdr; 5968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; 5978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang unsigned long flags; 5988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct net_device_stats *stats = &ieee->stats; 5998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int ether_type = 0, encrypt; 6008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int bytes, fc, qos_ctl = 0, hdr_len; 6018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct sk_buff *skb_frag; 6028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */ 6038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .duration_id = 0, 6048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .seq_ctl = 0, 6058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang .qos_ctl = 0 6068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang }; 6078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang u8 dest[ETH_ALEN], src[ETH_ALEN]; 6088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang int qos_actived = ieee->current_network.qos_data.active; 6098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct ieee80211_crypt_data* crypt; 6118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang cb_desc *tcb_desc; 6138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang spin_lock_irqsave(&ieee->lock, flags); 6158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* If there is no driver handler to take the TXB, dont' bother 6178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * creating it... */ 6188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| 6198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { 6208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_WARNING "%s: No xmit handler.\n", 6218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->dev->name); 6228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto success; 6238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 6248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(likely(ieee->raw_tx == 0)){ 6278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { 6288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_WARNING "%s: skb too small (%d).\n", 6298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->dev->name, skb->len); 6308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto success; 6318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 6328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memset(skb->cb, 0, sizeof(skb->cb)); 6348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); 6358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypt = ieee->crypt[ieee->tx_keyidx]; 6378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && 6398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->host_encrypt && crypt && crypt->ops; 6408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (!encrypt && ieee->ieee802_1x && 6428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->drop_unencrypted && ether_type != ETH_P_PAE) { 6438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang stats->tx_dropped++; 6448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto success; 6458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 6468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang #ifdef CONFIG_IEEE80211_DEBUG 6478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (crypt && !encrypt && ether_type == ETH_P_PAE) { 6488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang struct eapol *eap = (struct eapol *)(skb->data + 6498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); 6508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", 6518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang eap_get_type(eap->type)); 6528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 6538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang #endif 6548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Save source and destination addresses */ 6568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(&dest, skb->data, ETH_ALEN); 6578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); 6588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Advance the SKB to the start of the payload */ 6608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_pull(skb, sizeof(struct ethhdr)); 6618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Determine total amount of storage required for TXB packets */ 6638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes = skb->len + SNAP_SIZE + sizeof(u16); 6648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (encrypt) 6668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP; 6678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 6688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang fc = IEEE80211_FTYPE_DATA; 6708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //if(ieee->current_network.QoS_Enable) 6728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(qos_actived) 6738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang fc |= IEEE80211_STYPE_QOS_DATA; 6748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 6758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang fc |= IEEE80211_STYPE_DATA; 6768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->iw_mode == IW_MODE_INFRA) { 6788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang fc |= IEEE80211_FCTL_TODS; 6798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* To DS: Addr1 = BSSID, Addr2 = SA, 6808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Addr3 = DA */ 6818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); 6828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(&header.addr2, &src, ETH_ALEN); 6838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(&header.addr3, &dest, ETH_ALEN); 6848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } else if (ieee->iw_mode == IW_MODE_ADHOC) { 6858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* not From/To DS: Addr1 = DA, Addr2 = SA, 6868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang Addr3 = BSSID */ 6878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(&header.addr1, dest, ETH_ALEN); 6888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(&header.addr2, src, ETH_ALEN); 6898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); 6908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 6918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang header.frame_ctl = cpu_to_le16(fc); 6938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 6948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Determine fragmentation size based on destination (multicast 6958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * and broadcast are not fragmented) */ 6968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (is_multicast_ether_addr(header.addr1) || 6978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang is_broadcast_ether_addr(header.addr1)) { 6988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang frag_size = MAX_FRAG_THRESHOLD; 6998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; 7008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else { 7028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang frag_size = ieee->fts;//default:392 7038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang qos_ctl = 0; 7048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //if (ieee->current_network.QoS_Enable) 7078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(qos_actived) 7088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 7098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr_len = IEEE80211_3ADDR_LEN + 2; 7108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb->priority = ieee80211_classify(skb, &ieee->current_network); 7128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang qos_ctl |= skb->priority; //set in the ieee80211_classify 7138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID); 7148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } else { 7158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang hdr_len = IEEE80211_3ADDR_LEN; 7168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Determine amount of payload per fragment. Regardless of if 7188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * this stack is providing the full 802.11 header, one will 7198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * eventually be affixed to this fragment -- so we must account for 7208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * it when determining the amount of payload space. */ 7218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes_per_frag = frag_size - hdr_len; 7228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->config & 7238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) 7248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes_per_frag -= IEEE80211_FCS_LEN; 7258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 72694c97e8e0692ee3a58868a013b973fcf7fed348cJustin P. Mattock /* Each fragment may need to have room for encryption pre/postfix */ 7278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (encrypt) 7288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes_per_frag -= crypt->ops->extra_prefix_len + 7298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang crypt->ops->extra_postfix_len; 7308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Number of fragments is the total bytes_per_frag / 7328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * payload_per_fragment */ 7338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang nr_frags = bytes / bytes_per_frag; 7348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes_last_frag = bytes % bytes_per_frag; 7358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (bytes_last_frag) 7368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang nr_frags++; 7378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 7388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes_last_frag = bytes_per_frag; 7398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* When we allocate the TXB we allocate enough space for the reserve 7418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * and full fragment bytes (bytes_per_frag doesn't include prefix, 7428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * postfix, header, FCS, etc.) */ 7438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); 7448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (unlikely(!txb)) { 7458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_WARNING "%s: Could not allocate TXB\n", 7468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->dev->name); 7478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto failed; 7488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb->encrypted = encrypt; 7508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb->payload_size = bytes; 7518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //if (ieee->current_network.QoS_Enable) 7538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(qos_actived) 7548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 7558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb->queue_index = UP2AC(skb->priority); 7568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } else { 757859171ca92f2865453b4b2e17bf679c67044a833Joe Perches txb->queue_index = WME_AC_BK; 7588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang for (i = 0; i < nr_frags; i++) { 7638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_frag = txb->fragments[i]; 7648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); 7658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(qos_actived){ 7668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_frag->priority = skb->priority;//UP2AC(skb->priority); 7678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->queue_index = UP2AC(skb->priority); 7688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } else { 7698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_frag->priority = WME_AC_BK; 7708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->queue_index = WME_AC_BK; 7718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_reserve(skb_frag, ieee->tx_headroom); 7738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (encrypt){ 7758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->hwsec_active) 7768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bHwSec = 1; 7778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 7788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bHwSec = 0; 7798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_reserve(skb_frag, crypt->ops->extra_prefix_len); 7808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 7828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 7838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bHwSec = 0; 7848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); 7868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(frag_hdr, &header, hdr_len); 7878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* If this is not the last fragment, then add the MOREFRAGS 7898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * bit to the frame control */ 7908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (i != nr_frags - 1) { 7918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang frag_hdr->frame_ctl = cpu_to_le16( 7928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang fc | IEEE80211_FCTL_MOREFRAGS); 7938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes = bytes_per_frag; 7948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 7958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } else { 7968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* The last fragment takes the remaining length */ 7978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes = bytes_last_frag; 7988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 7998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //if(ieee->current_network.QoS_Enable) 8008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(qos_actived) 8018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 8028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang // add 1 only indicate to corresponding seq number control 2006/7/12 8038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); 8048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } else { 8058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); 8068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 8088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Put a SNAP header on the first fragment */ 8098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (i == 0) { 8108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_put_snap( 8118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), 8128fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ether_type); 8138fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang bytes -= SNAP_SIZE + sizeof(u16); 8148fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8158fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 8168fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(skb_put(skb_frag, bytes), skb->data, bytes); 8178fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 8188fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Advance the SKB... */ 8198fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_pull(skb, bytes); 8208fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 8218fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang /* Encryption routine will move the header forward in order 8228fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang * to insert the IV between the header and the payload */ 8238fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (encrypt) 8248fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); 8258fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->config & 8268fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) 8278fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang skb_put(skb_frag, 4); 8288fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8298fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 8308fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(qos_actived) 8318fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 8328fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) 8338fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; 8348fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 8358fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; 8368fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } else { 8378fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->seq_ctrl[0] == 0xFFF) 8388fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->seq_ctrl[0] = 0; 8398fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 8408fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->seq_ctrl[0]++; 8418fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8428fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang }else{ 8438fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { 8448fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_WARNING "%s: skb too small (%d).\n", 8458fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->dev->name, skb->len); 8468fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto success; 8478fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8488fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 8498fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); 8508fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if(!txb){ 8518fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang printk(KERN_WARNING "%s: Could not allocate TXB\n", 8528fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee->dev->name); 8538fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang goto failed; 8548fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8558fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 8568fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb->encrypted = 0; 8578fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang txb->payload_size = skb->len; 8588fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); 8598fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8608fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 8618fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang success: 8628fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang//WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. 8638fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (txb) 8648fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang { 8658fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); 8668fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bTxEnableFwCalcDur = 1; 8678fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (is_multicast_ether_addr(header.addr1)) 8688fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bMulticast = 1; 8698fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (is_broadcast_ether_addr(header.addr1)) 8708fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->bBroadcast = 1; 8718fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_txrate_selectmode(ieee, tcb_desc); 8728fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if ( tcb_desc->bMulticast || tcb_desc->bBroadcast) 8738fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->data_rate = ieee->basic_rate; 8748fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang else 8758fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate); 8768fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); 8778fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc); 8788fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); 8798fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_query_HTCapShortGI(ieee, tcb_desc); 8808fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_query_BandwidthMode(ieee, tcb_desc); 8818fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); 8828fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1); 8838fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len); 8848fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, tcb_desc, sizeof(cb_desc)); 8858fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8868fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang spin_unlock_irqrestore(&ieee->lock, flags); 8878fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang dev_kfree_skb_any(skb); 8888fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (txb) { 8898fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ 8908fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_softmac_xmit(txb, ieee); 8918fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang }else{ 8928fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang if ((*ieee->hard_start_xmit)(txb, dev) == 0) { 8938fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang stats->tx_packets++; 8948fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang stats->tx_bytes += txb->payload_size; 8958fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 8968fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8978fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang ieee80211_txb_free(txb); 8988fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 8998fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang } 9008fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 9018fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 0; 9028fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 9038fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang failed: 9048fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang spin_unlock_irqrestore(&ieee->lock, flags); 9058fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang netif_stop_queue(dev); 9068fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang stats->tx_errors++; 9078fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang return 1; 9088fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 9098fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang} 9108fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry Chuang 9118fc8598e61f6f384f3eaf1d9b09500c12af47b37Jerry ChuangEXPORT_SYMBOL(ieee80211_txb_free); 912