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