PageRenderTime 88ms CodeModel.GetById 51ms app.highlight 32ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 911 lines | 623 code | 93 blank | 195 comment | 166 complexity | b664c88dbbb43df79492e3e3596a270d MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1/******************************************************************************
  2
  3  Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
  4
  5  This program is free software; you can redistribute it and/or modify it
  6  under the terms of version 2 of the GNU General Public License as
  7  published by the Free Software Foundation.
  8
  9  This program is distributed in the hope that it will be useful, but WITHOUT
 10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 12  more details.
 13
 14  You should have received a copy of the GNU General Public License along with
 15  this program; if not, write to the Free Software Foundation, Inc., 59
 16  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 17
 18  The full GNU General Public License is included in this distribution in the
 19  file called LICENSE.
 20
 21  Contact Information:
 22  James P. Ketrenos <ipw2100-admin@linux.intel.com>
 23  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 24
 25******************************************************************************
 26
 27  Few modifications for Realtek's Wi-Fi drivers by
 28  Andrea Merello <andreamrl@tiscali.it>
 29
 30  A special thanks goes to Realtek for their support !
 31
 32******************************************************************************/
 33
 34#include <linux/compiler.h>
 35//#include <linux/config.h>
 36#include <linux/errno.h>
 37#include <linux/if_arp.h>
 38#include <linux/in6.h>
 39#include <linux/in.h>
 40#include <linux/ip.h>
 41#include <linux/kernel.h>
 42#include <linux/module.h>
 43#include <linux/netdevice.h>
 44#include <linux/pci.h>
 45#include <linux/proc_fs.h>
 46#include <linux/skbuff.h>
 47#include <linux/slab.h>
 48#include <linux/tcp.h>
 49#include <linux/types.h>
 50#include <linux/wireless.h>
 51#include <linux/etherdevice.h>
 52#include <asm/uaccess.h>
 53#include <linux/if_vlan.h>
 54
 55#include "ieee80211.h"
 56
 57
 58/*
 59
 60
 61802.11 Data Frame
 62
 63
 64802.11 frame_contorl for data frames - 2 bytes
 65     ,-----------------------------------------------------------------------------------------.
 66bits | 0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  a  |  b  |  c  |  d  |  e   |
 67     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
 68val  | 0  |  0  |  0  |  1  |  x  |  0  |  0  |  0  |  1  |  0  |  x  |  x  |  x  |  x  |  x   |
 69     |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
 70desc | ^-ver-^  |  ^type-^  |  ^-----subtype-----^  | to  |from |more |retry| pwr |more |wep   |
 71     |          |           | x=0 data,x=1 data+ack | DS  | DS  |frag |     | mgm |data |      |
 72     '-----------------------------------------------------------------------------------------'
 73		                                    /\
 74                                                    |
 75802.11 Data Frame                                   |
 76           ,--------- 'ctrl' expands to >-----------'
 77          |
 78      ,--'---,-------------------------------------------------------------.
 79Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
 80      |------|------|---------|---------|---------|------|---------|------|
 81Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  Frame  |  fcs |
 82      |      | tion | (BSSID) |         |         | ence |  data   |      |
 83      `--------------------------------------------------|         |------'
 84Total: 28 non-data bytes                                 `----.----'
 85                                                              |
 86       .- 'Frame data' expands to <---------------------------'
 87       |
 88       V
 89      ,---------------------------------------------------.
 90Bytes |  1   |  1   |    1    |    3     |  2   |  0-2304 |
 91      |------|------|---------|----------|------|---------|
 92Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP      |
 93      | DSAP | SSAP |         |          |      | Packet  |
 94      | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8|      |         |
 95      `-----------------------------------------|         |
 96Total: 8 non-data bytes                         `----.----'
 97                                                     |
 98       .- 'IP Packet' expands, if WEP enabled, to <--'
 99       |
100       V
101      ,-----------------------.
102Bytes |  4  |   0-2296  |  4  |
103      |-----|-----------|-----|
104Desc. | IV  | Encrypted | ICV |
105      |     | IP Packet |     |
106      `-----------------------'
107Total: 8 non-data bytes
108
109
110802.3 Ethernet Data Frame
111
112      ,-----------------------------------------.
113Bytes |   6   |   6   |  2   |  Variable |   4  |
114      |-------|-------|------|-----------|------|
115Desc. | Dest. | Source| Type | IP Packet |  fcs |
116      |  MAC  |  MAC  |      |           |      |
117      `-----------------------------------------'
118Total: 18 non-data bytes
119
120In the event that fragmentation is required, the incoming payload is split into
121N parts of size ieee->fts.  The first fragment contains the SNAP header and the
122remaining packets are just data.
123
124If encryption is enabled, each fragment payload size is reduced by enough space
125to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
126So if you have 1500 bytes of payload with ieee->fts set to 500 without
127encryption it will take 3 frames.  With WEP it will take 4 frames as the
128payload of each frame is reduced to 492 bytes.
129
130* SKB visualization
131*
132*  ,- skb->data
133* |
134* |    ETHERNET HEADER        ,-<-- PAYLOAD
135* |                           |     14 bytes from skb->data
136* |  2 bytes for Type --> ,T. |     (sizeof ethhdr)
137* |                       | | |
138* |,-Dest.--. ,--Src.---. | | |
139* |  6 bytes| | 6 bytes | | | |
140* v         | |         | | | |
141* 0         | v       1 | v | v           2
142* 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
143*     ^     | ^         | ^ |
144*     |     | |         | | |
145*     |     | |         | `T' <---- 2 bytes for Type
146*     |     | |         |
147*     |     | '---SNAP--' <-------- 6 bytes for SNAP
148*     |     |
149*     `-IV--' <-------------------- 4 bytes for IV (WEP)
150*
151*      SNAP HEADER
152*
153*/
154
155static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
156static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
157
158static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
159{
160	struct ieee80211_snap_hdr *snap;
161	u8 *oui;
162
163	snap = (struct ieee80211_snap_hdr *)data;
164	snap->dsap = 0xaa;
165	snap->ssap = 0xaa;
166	snap->ctrl = 0x03;
167
168	if (h_proto == 0x8137 || h_proto == 0x80f3)
169		oui = P802_1H_OUI;
170	else
171		oui = RFC1042_OUI;
172	snap->oui[0] = oui[0];
173	snap->oui[1] = oui[1];
174	snap->oui[2] = oui[2];
175
176	*(u16 *)(data + SNAP_SIZE) = htons(h_proto);
177
178	return SNAP_SIZE + sizeof(u16);
179}
180
181int ieee80211_encrypt_fragment(
182	struct ieee80211_device *ieee,
183	struct sk_buff *frag,
184	int hdr_len)
185{
186	struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
187	int res;
188
189	if (!(crypt && crypt->ops))
190	{
191		printk("=========>%s(), crypt is null\n", __FUNCTION__);
192		return -1;
193	}
194#ifdef CONFIG_IEEE80211_CRYPT_TKIP
195	struct ieee80211_hdr *header;
196
197	if (ieee->tkip_countermeasures &&
198	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
199		header = (struct ieee80211_hdr *) frag->data;
200		if (net_ratelimit()) {
201			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
202			       "TX packet to %pM\n",
203			       ieee->dev->name, header->addr1);
204		}
205		return -1;
206	}
207#endif
208	/* To encrypt, frame format is:
209	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
210
211	// PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
212	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
213	 * call both MSDU and MPDU encryption functions from here. */
214	atomic_inc(&crypt->refcnt);
215	res = 0;
216	if (crypt->ops->encrypt_msdu)
217		res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
218	if (res == 0 && crypt->ops->encrypt_mpdu)
219		res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
220
221	atomic_dec(&crypt->refcnt);
222	if (res < 0) {
223		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
224		       ieee->dev->name, frag->len);
225		ieee->ieee_stats.tx_discards++;
226		return -1;
227	}
228
229	return 0;
230}
231
232
233void ieee80211_txb_free(struct ieee80211_txb *txb) {
234	//int i;
235	if (unlikely(!txb))
236		return;
237	kfree(txb);
238}
239
240struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
241					  int gfp_mask)
242{
243	struct ieee80211_txb *txb;
244	int i;
245	txb = kmalloc(
246		sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
247		gfp_mask);
248	if (!txb)
249		return NULL;
250
251	memset(txb, 0, sizeof(struct ieee80211_txb));
252	txb->nr_frags = nr_frags;
253	txb->frag_size = txb_size;
254
255	for (i = 0; i < nr_frags; i++) {
256		txb->fragments[i] = dev_alloc_skb(txb_size);
257		if (unlikely(!txb->fragments[i])) {
258			i--;
259			break;
260		}
261		memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
262	}
263	if (unlikely(i != nr_frags)) {
264		while (i >= 0)
265			dev_kfree_skb_any(txb->fragments[i--]);
266		kfree(txb);
267		return NULL;
268	}
269	return txb;
270}
271
272// Classify the to-be send data packet
273// Need to acquire the sent queue index.
274static int
275ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
276{
277	struct ethhdr *eth;
278	struct iphdr *ip;
279	eth = (struct ethhdr *)skb->data;
280	if (eth->h_proto != htons(ETH_P_IP))
281		return 0;
282
283//	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
284	ip = ip_hdr(skb);
285	switch (ip->tos & 0xfc) {
286		case 0x20:
287			return 2;
288		case 0x40:
289			return 1;
290		case 0x60:
291			return 3;
292		case 0x80:
293			return 4;
294		case 0xa0:
295			return 5;
296		case 0xc0:
297			return 6;
298		case 0xe0:
299			return 7;
300		default:
301			return 0;
302	}
303}
304
305#define SN_LESS(a, b)		(((a-b)&0x800)!=0)
306void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
307{
308	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
309	PTX_TS_RECORD			pTxTs = NULL;
310	struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data;
311
312	if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
313		return;
314	if (!IsQoSDataFrame(skb->data))
315		return;
316
317	if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1))
318		return;
319	//check packet and mode later
320#ifdef TO_DO_LIST
321	if(pTcb->PacketLength >= 4096)
322		return;
323	// For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation.
324	if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
325		return;
326#endif
327	if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
328	{
329		return;
330	}
331	if(pHTInfo->bCurrentAMPDUEnable)
332	{
333		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true))
334		{
335			printk("===>can't get TS\n");
336			return;
337		}
338		if (pTxTs->TxAdmittedBARecord.bValid == false)
339		{
340			TsStartAddBaProcess(ieee, pTxTs);
341			goto FORCED_AGG_SETTING;
342		}
343		else if (pTxTs->bUsingBa == false)
344		{
345			if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
346				pTxTs->bUsingBa = true;
347			else
348				goto FORCED_AGG_SETTING;
349		}
350
351		if (ieee->iw_mode == IW_MODE_INFRA)
352		{
353			tcb_desc->bAMPDUEnable = true;
354			tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
355			tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
356		}
357	}
358FORCED_AGG_SETTING:
359	switch(pHTInfo->ForcedAMPDUMode )
360	{
361		case HT_AGG_AUTO:
362			break;
363
364		case HT_AGG_FORCE_ENABLE:
365			tcb_desc->bAMPDUEnable = true;
366			tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
367			tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
368			break;
369
370		case HT_AGG_FORCE_DISABLE:
371			tcb_desc->bAMPDUEnable = false;
372			tcb_desc->ampdu_density = 0;
373			tcb_desc->ampdu_factor = 0;
374			break;
375
376	}
377		return;
378}
379
380extern void ieee80211_qurey_ShortPreambleMode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
381{
382	tcb_desc->bUseShortPreamble = false;
383	if (tcb_desc->data_rate == 2)
384	{//// 1M can only use Long Preamble. 11B spec
385		return;
386	}
387	else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
388	{
389		tcb_desc->bUseShortPreamble = true;
390	}
391	return;
392}
393extern	void
394ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, cb_desc *tcb_desc)
395{
396	PRT_HIGH_THROUGHPUT		pHTInfo = ieee->pHTInfo;
397
398	tcb_desc->bUseShortGI 		= false;
399
400	if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
401		return;
402
403	if(pHTInfo->bForcedShortGI)
404	{
405		tcb_desc->bUseShortGI = true;
406		return;
407	}
408
409	if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz)
410		tcb_desc->bUseShortGI = true;
411	else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz)
412		tcb_desc->bUseShortGI = true;
413}
414
415void ieee80211_query_BandwidthMode(struct ieee80211_device* ieee, cb_desc *tcb_desc)
416{
417	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
418
419	tcb_desc->bPacketBW = false;
420
421	if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
422		return;
423
424	if(tcb_desc->bMulticast || tcb_desc->bBroadcast)
425		return;
426
427	if((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel.
428		return;
429	//BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance
430	if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
431		tcb_desc->bPacketBW = true;
432	return;
433}
434
435void ieee80211_query_protectionmode(struct ieee80211_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb)
436{
437	// Common Settings
438	tcb_desc->bRTSSTBC			= false;
439	tcb_desc->bRTSUseShortGI		= false; // Since protection frames are always sent by legacy rate, ShortGI will never be used.
440	tcb_desc->bCTSEnable			= false; // Most of protection using RTS/CTS
441	tcb_desc->RTSSC				= 0;		// 20MHz: Don't care;  40MHz: Duplicate.
442	tcb_desc->bRTSBW			= false; // RTS frame bandwidth is always 20MHz
443
444	if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts
445		return;
446
447	if (is_broadcast_ether_addr(skb->data+16))  //check addr3 as infrastructure add3 is DA.
448		return;
449
450	if (ieee->mode < IEEE_N_24G) //b, g mode
451	{
452			// (1) RTS_Threshold is compared to the MPDU, not MSDU.
453			// (2) If there are more than one frag in  this MSDU, only the first frag uses protection frame.
454			//		Other fragments are protected by previous fragment.
455			//		So we only need to check the length of first fragment.
456		if (skb->len > ieee->rts)
457		{
458			tcb_desc->bRTSEnable = true;
459			tcb_desc->rts_rate = MGN_24M;
460		}
461		else if (ieee->current_network.buseprotection)
462		{
463			// Use CTS-to-SELF in protection mode.
464			tcb_desc->bRTSEnable = true;
465			tcb_desc->bCTSEnable = true;
466			tcb_desc->rts_rate = MGN_24M;
467		}
468		//otherwise return;
469		return;
470	}
471	else
472	{// 11n High throughput case.
473		PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
474		while (true)
475		{
476			//check ERP protection
477			if (ieee->current_network.buseprotection)
478			{// CTS-to-SELF
479				tcb_desc->bRTSEnable = true;
480				tcb_desc->bCTSEnable = true;
481				tcb_desc->rts_rate = MGN_24M;
482				break;
483			}
484			//check HT op mode
485			if(pHTInfo->bCurrentHTSupport  && pHTInfo->bEnableHT)
486			{
487				u8 HTOpMode = pHTInfo->CurrentOpMode;
488				if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) ||
489							(!pHTInfo->bCurBW40MHz && HTOpMode == 3) )
490				{
491					tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
492					tcb_desc->bRTSEnable = true;
493					break;
494				}
495			}
496			//check rts
497			if (skb->len > ieee->rts)
498			{
499				tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
500				tcb_desc->bRTSEnable = true;
501				break;
502			}
503			//to do list: check MIMO power save condition.
504			//check AMPDU aggregation for TXOP
505			if(tcb_desc->bAMPDUEnable)
506			{
507				tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
508				// According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads
509				// throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily
510				tcb_desc->bRTSEnable = false;
511				break;
512			}
513			//check IOT action
514			if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF)
515			{
516				tcb_desc->bCTSEnable	= true;
517				tcb_desc->rts_rate  = 	MGN_24M;
518				tcb_desc->bRTSEnable = true;
519				break;
520			}
521			// Totally no protection case!!
522			goto NO_PROTECTION;
523		}
524		}
525	// For test , CTS replace with RTS
526	if( 0 )
527	{
528		tcb_desc->bCTSEnable	= true;
529		tcb_desc->rts_rate = MGN_24M;
530		tcb_desc->bRTSEnable 	= true;
531	}
532	if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
533		tcb_desc->bUseShortPreamble = true;
534	if (ieee->mode == IW_MODE_MASTER)
535			goto NO_PROTECTION;
536	return;
537NO_PROTECTION:
538	tcb_desc->bRTSEnable	= false;
539	tcb_desc->bCTSEnable	= false;
540	tcb_desc->rts_rate		= 0;
541	tcb_desc->RTSSC		= 0;
542	tcb_desc->bRTSBW		= false;
543}
544
545
546void ieee80211_txrate_selectmode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
547{
548#ifdef TO_DO_LIST
549	if(!IsDataFrame(pFrame))
550	{
551		pTcb->bTxDisableRateFallBack = TRUE;
552		pTcb->bTxUseDriverAssingedRate = TRUE;
553		pTcb->RATRIndex = 7;
554		return;
555	}
556
557	if(pMgntInfo->ForcedDataRate!= 0)
558	{
559		pTcb->bTxDisableRateFallBack = TRUE;
560		pTcb->bTxUseDriverAssingedRate = TRUE;
561		return;
562	}
563#endif
564	if(ieee->bTxDisableRateFallBack)
565		tcb_desc->bTxDisableRateFallBack = true;
566
567	if(ieee->bTxUseDriverAssingedRate)
568		tcb_desc->bTxUseDriverAssingedRate = true;
569	if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate)
570	{
571		if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
572			tcb_desc->RATRIndex = 0;
573	}
574}
575
576void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst)
577{
578	if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
579		return;
580	if (IsQoSDataFrame(skb->data)) //we deal qos data only
581	{
582		PTX_TS_RECORD pTS = NULL;
583		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true))
584		{
585			return;
586		}
587		pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
588	}
589}
590
591int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
592{
593	struct ieee80211_device *ieee = netdev_priv(dev);
594	struct ieee80211_txb *txb = NULL;
595	struct ieee80211_hdr_3addrqos *frag_hdr;
596	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
597	unsigned long flags;
598	struct net_device_stats *stats = &ieee->stats;
599	int ether_type = 0, encrypt;
600	int bytes, fc, qos_ctl = 0, hdr_len;
601	struct sk_buff *skb_frag;
602	struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
603		.duration_id = 0,
604		.seq_ctl = 0,
605		.qos_ctl = 0
606	};
607	u8 dest[ETH_ALEN], src[ETH_ALEN];
608	int qos_actived = ieee->current_network.qos_data.active;
609
610	struct ieee80211_crypt_data* crypt;
611
612	cb_desc *tcb_desc;
613
614	spin_lock_irqsave(&ieee->lock, flags);
615
616	/* If there is no driver handler to take the TXB, dont' bother
617	 * creating it... */
618	if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
619	   ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
620		printk(KERN_WARNING "%s: No xmit handler.\n",
621		       ieee->dev->name);
622		goto success;
623	}
624
625
626	if(likely(ieee->raw_tx == 0)){
627		if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
628			printk(KERN_WARNING "%s: skb too small (%d).\n",
629			ieee->dev->name, skb->len);
630			goto success;
631		}
632
633		memset(skb->cb, 0, sizeof(skb->cb));
634		ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
635
636		crypt = ieee->crypt[ieee->tx_keyidx];
637
638		encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
639			ieee->host_encrypt && crypt && crypt->ops;
640
641		if (!encrypt && ieee->ieee802_1x &&
642		ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
643			stats->tx_dropped++;
644			goto success;
645		}
646	#ifdef CONFIG_IEEE80211_DEBUG
647		if (crypt && !encrypt && ether_type == ETH_P_PAE) {
648			struct eapol *eap = (struct eapol *)(skb->data +
649				sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
650			IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
651				eap_get_type(eap->type));
652		}
653	#endif
654
655		/* Save source and destination addresses */
656		memcpy(&dest, skb->data, ETH_ALEN);
657		memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
658
659                /* Advance the SKB to the start of the payload */
660                skb_pull(skb, sizeof(struct ethhdr));
661
662                /* Determine total amount of storage required for TXB packets */
663                bytes = skb->len + SNAP_SIZE + sizeof(u16);
664
665		if (encrypt)
666			fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP;
667		else
668
669                        fc = IEEE80211_FTYPE_DATA;
670
671		//if(ieee->current_network.QoS_Enable)
672		if(qos_actived)
673			fc |= IEEE80211_STYPE_QOS_DATA;
674		else
675			fc |= IEEE80211_STYPE_DATA;
676
677		if (ieee->iw_mode == IW_MODE_INFRA) {
678			fc |= IEEE80211_FCTL_TODS;
679			/* To DS: Addr1 = BSSID, Addr2 = SA,
680			Addr3 = DA */
681			memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
682			memcpy(&header.addr2, &src, ETH_ALEN);
683			memcpy(&header.addr3, &dest, ETH_ALEN);
684		} else if (ieee->iw_mode == IW_MODE_ADHOC) {
685			/* not From/To DS: Addr1 = DA, Addr2 = SA,
686			Addr3 = BSSID */
687			memcpy(&header.addr1, dest, ETH_ALEN);
688			memcpy(&header.addr2, src, ETH_ALEN);
689			memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
690		}
691
692                header.frame_ctl = cpu_to_le16(fc);
693
694		/* Determine fragmentation size based on destination (multicast
695		* and broadcast are not fragmented) */
696		if (is_multicast_ether_addr(header.addr1) ||
697		is_broadcast_ether_addr(header.addr1)) {
698			frag_size = MAX_FRAG_THRESHOLD;
699			qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
700		}
701		else {
702			frag_size = ieee->fts;//default:392
703			qos_ctl = 0;
704		}
705
706		//if (ieee->current_network.QoS_Enable)
707		if(qos_actived)
708		{
709			hdr_len = IEEE80211_3ADDR_LEN + 2;
710
711			skb->priority = ieee80211_classify(skb, &ieee->current_network);
712			qos_ctl |= skb->priority; //set in the ieee80211_classify
713			header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID);
714		} else {
715			hdr_len = IEEE80211_3ADDR_LEN;
716		}
717		/* Determine amount of payload per fragment.  Regardless of if
718		* this stack is providing the full 802.11 header, one will
719		* eventually be affixed to this fragment -- so we must account for
720		* it when determining the amount of payload space. */
721		bytes_per_frag = frag_size - hdr_len;
722		if (ieee->config &
723		(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
724			bytes_per_frag -= IEEE80211_FCS_LEN;
725
726		/* Each fragment may need to have room for encryption pre/postfix */
727		if (encrypt)
728			bytes_per_frag -= crypt->ops->extra_prefix_len +
729				crypt->ops->extra_postfix_len;
730
731		/* Number of fragments is the total bytes_per_frag /
732		* payload_per_fragment */
733		nr_frags = bytes / bytes_per_frag;
734		bytes_last_frag = bytes % bytes_per_frag;
735		if (bytes_last_frag)
736			nr_frags++;
737		else
738			bytes_last_frag = bytes_per_frag;
739
740		/* When we allocate the TXB we allocate enough space for the reserve
741		* and full fragment bytes (bytes_per_frag doesn't include prefix,
742		* postfix, header, FCS, etc.) */
743		txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC);
744		if (unlikely(!txb)) {
745			printk(KERN_WARNING "%s: Could not allocate TXB\n",
746			ieee->dev->name);
747			goto failed;
748		}
749		txb->encrypted = encrypt;
750		txb->payload_size = bytes;
751
752		//if (ieee->current_network.QoS_Enable)
753		if(qos_actived)
754		{
755			txb->queue_index = UP2AC(skb->priority);
756		} else {
757			txb->queue_index = WME_AC_BK;
758		}
759
760
761
762		for (i = 0; i < nr_frags; i++) {
763			skb_frag = txb->fragments[i];
764			tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE);
765			if(qos_actived){
766				skb_frag->priority = skb->priority;//UP2AC(skb->priority);
767				tcb_desc->queue_index =  UP2AC(skb->priority);
768			} else {
769				skb_frag->priority = WME_AC_BK;
770				tcb_desc->queue_index = WME_AC_BK;
771			}
772			skb_reserve(skb_frag, ieee->tx_headroom);
773
774			if (encrypt){
775				if (ieee->hwsec_active)
776					tcb_desc->bHwSec = 1;
777				else
778					tcb_desc->bHwSec = 0;
779				skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
780			}
781			else
782			{
783				tcb_desc->bHwSec = 0;
784			}
785			frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
786			memcpy(frag_hdr, &header, hdr_len);
787
788			/* If this is not the last fragment, then add the MOREFRAGS
789			* bit to the frame control */
790			if (i != nr_frags - 1) {
791				frag_hdr->frame_ctl = cpu_to_le16(
792					fc | IEEE80211_FCTL_MOREFRAGS);
793				bytes = bytes_per_frag;
794
795			} else {
796				/* The last fragment takes the remaining length */
797				bytes = bytes_last_frag;
798			}
799			//if(ieee->current_network.QoS_Enable)
800			if(qos_actived)
801			{
802				// add 1 only indicate to corresponding seq number control 2006/7/12
803				frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
804			} else {
805				frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
806			}
807
808			/* Put a SNAP header on the first fragment */
809			if (i == 0) {
810				ieee80211_put_snap(
811					skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
812					ether_type);
813				bytes -= SNAP_SIZE + sizeof(u16);
814			}
815
816			memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
817
818			/* Advance the SKB... */
819			skb_pull(skb, bytes);
820
821			/* Encryption routine will move the header forward in order
822			* to insert the IV between the header and the payload */
823			if (encrypt)
824				ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
825			if (ieee->config &
826			(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
827				skb_put(skb_frag, 4);
828		}
829
830		if(qos_actived)
831		{
832		  if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
833			ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
834		  else
835			ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
836		} else {
837  		  if (ieee->seq_ctrl[0] == 0xFFF)
838			ieee->seq_ctrl[0] = 0;
839		  else
840			ieee->seq_ctrl[0]++;
841		}
842	}else{
843		if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
844			printk(KERN_WARNING "%s: skb too small (%d).\n",
845			ieee->dev->name, skb->len);
846			goto success;
847		}
848
849		txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
850		if(!txb){
851			printk(KERN_WARNING "%s: Could not allocate TXB\n",
852			ieee->dev->name);
853			goto failed;
854		}
855
856		txb->encrypted = 0;
857		txb->payload_size = skb->len;
858		memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
859	}
860
861 success:
862//WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place.
863	if (txb)
864	{
865		cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
866		tcb_desc->bTxEnableFwCalcDur = 1;
867		if (is_multicast_ether_addr(header.addr1))
868			tcb_desc->bMulticast = 1;
869		if (is_broadcast_ether_addr(header.addr1))
870			tcb_desc->bBroadcast = 1;
871		ieee80211_txrate_selectmode(ieee, tcb_desc);
872		if ( tcb_desc->bMulticast ||  tcb_desc->bBroadcast)
873			tcb_desc->data_rate = ieee->basic_rate;
874		else
875			//tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate);
876			tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
877		ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
878		ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
879		ieee80211_query_HTCapShortGI(ieee, tcb_desc);
880		ieee80211_query_BandwidthMode(ieee, tcb_desc);
881		ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
882		ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1);
883//		IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len);
884		//IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, tcb_desc, sizeof(cb_desc));
885	}
886	spin_unlock_irqrestore(&ieee->lock, flags);
887	dev_kfree_skb_any(skb);
888	if (txb) {
889		if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
890			ieee80211_softmac_xmit(txb, ieee);
891		}else{
892			if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
893				stats->tx_packets++;
894				stats->tx_bytes += txb->payload_size;
895				return 0;
896			}
897			ieee80211_txb_free(txb);
898		}
899	}
900
901	return 0;
902
903 failed:
904	spin_unlock_irqrestore(&ieee->lock, flags);
905	netif_stop_queue(dev);
906	stats->tx_errors++;
907	return 1;
908
909}
910
911EXPORT_SYMBOL(ieee80211_txb_free);