• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rtl8192u/ieee80211/
1/********************************************************************************************************************************
2 * This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is
3 * related to TS, this part need some struture defined in QOS side code. Also TX RX is going to be resturctured, so how to send
4 * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
5 * WB 2008-05-27
6 * *****************************************************************************************************************************/
7#include "ieee80211.h"
8#include "rtl819x_BA.h"
9
10/********************************************************************************************************************
11 *function:  Activate BA entry. And if Time is nozero, start timer.
12 *   input:  PBA_RECORD 		pBA  //BA entry to be enabled
13 *   	     u16 			Time //indicate time delay.
14 *  output:  none
15********************************************************************************************************************/
16void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
17{
18	pBA->bValid = true;
19	if(Time != 0)
20		mod_timer(&pBA->Timer, jiffies + MSECS(Time));
21}
22
23/********************************************************************************************************************
24 *function:  deactivate BA entry, including its timer.
25 *   input:  PBA_RECORD 		pBA  //BA entry to be disabled
26 *  output:  none
27********************************************************************************************************************/
28void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
29{
30	pBA->bValid = false;
31	del_timer_sync(&pBA->Timer);
32}
33u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD	pTxTs)
34{
35	PBA_RECORD		pAdmittedBa = &pTxTs->TxAdmittedBARecord;  //These two BA entries must exist in TS structure
36	PBA_RECORD		pPendingBa = &pTxTs->TxPendingBARecord;
37	u8			bSendDELBA = false;
38
39	// Delete pending BA
40	if(pPendingBa->bValid)
41	{
42		DeActivateBAEntry(ieee, pPendingBa);
43		bSendDELBA = true;
44	}
45
46	// Delete admitted BA
47	if(pAdmittedBa->bValid)
48	{
49		DeActivateBAEntry(ieee, pAdmittedBa);
50		bSendDELBA = true;
51	}
52
53	return bSendDELBA;
54}
55
56u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD	pRxTs)
57{
58	PBA_RECORD		pBa = &pRxTs->RxAdmittedBARecord;
59	u8			bSendDELBA = false;
60
61	if(pBa->bValid)
62	{
63		DeActivateBAEntry(ieee, pBa);
64		bSendDELBA = true;
65	}
66
67	return bSendDELBA;
68}
69
70/********************************************************************************************************************
71 *function: reset BA entry
72 *   input:
73 *   	     PBA_RECORD		pBA //entry to be reset
74 *  output:  none
75********************************************************************************************************************/
76void ResetBaEntry( PBA_RECORD pBA)
77{
78	pBA->bValid			= false;
79	pBA->BaParamSet.shortData	= 0;
80	pBA->BaTimeoutValue		= 0;
81	pBA->DialogToken		= 0;
82	pBA->BaStartSeqCtrl.ShortData	= 0;
83}
84//These functions need porting here or not?
85/*******************************************************************************************************************************
86 *function:  construct ADDBAREQ and ADDBARSP frame here together.
87 *   input:  u8* 		Dst 	//ADDBA frame's destination
88 *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA.
89 *   	     u16 		StatusCode  //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
90 *   	     u8			type	//indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
91 *  output:  none
92 *  return:  sk_buff* 		skb     //return constructed skb to xmit
93*******************************************************************************************************************************/
94static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
95{
96	struct sk_buff *skb = NULL;
97	 struct ieee80211_hdr_3addr* BAReq = NULL;
98	u8* tag = NULL;
99	u16 tmp = 0;
100	u16 len = ieee->tx_headroom + 9;
101	//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) +  BA Timeout Value(2) +  BA Start SeqCtrl(2)(or StatusCode(2))
102	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
103	if (pBA == NULL||ieee == NULL)
104	{
105		IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
106		return NULL;
107	}
108	skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr));
109	if (skb == NULL)
110	{
111		IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
112		return NULL;
113	}
114
115	memset(skb->data, 0, sizeof( struct ieee80211_hdr_3addr));  	//I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
116	skb_reserve(skb, ieee->tx_headroom);
117
118	BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
119
120	memcpy(BAReq->addr1, Dst, ETH_ALEN);
121	memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
122
123	memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
124
125	BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
126
127	//tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
128	tag = (u8*)skb_put(skb, 9);
129	*tag ++= ACT_CAT_BA;
130	*tag ++= type;
131	// Dialog Token
132	*tag ++= pBA->DialogToken;
133
134	if (ACT_ADDBARSP == type)
135	{
136		// Status Code
137		printk("=====>to send ADDBARSP\n");
138		tmp = cpu_to_le16(StatusCode);
139		memcpy(tag, (u8*)&tmp, 2);
140		tag += 2;
141	}
142	// BA Parameter Set
143	tmp = cpu_to_le16(pBA->BaParamSet.shortData);
144	memcpy(tag, (u8*)&tmp, 2);
145	tag += 2;
146	// BA Timeout Value
147	tmp = cpu_to_le16(pBA->BaTimeoutValue);
148	memcpy(tag, (u8*)&tmp, 2);
149	tag += 2;
150
151	if (ACT_ADDBAREQ == type)
152	{
153	// BA Start SeqCtrl
154		memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
155		tag += 2;
156	}
157
158	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
159	return skb;
160	//return NULL;
161}
162
163
164/********************************************************************************************************************
165 *function:  construct DELBA frame
166 *   input:  u8* 		dst 	//DELBA frame's destination
167 *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA
168 *   	     TR_SELECT	        TxRxSelect  //TX RX direction
169 *   	     u16 		ReasonCode  //status code.
170 *  output:  none
171 *  return:  sk_buff* 		skb     //return constructed skb to xmit
172********************************************************************************************************************/
173static struct sk_buff* ieee80211_DELBA(
174	struct ieee80211_device* ieee,
175	u8*		         dst,
176	PBA_RECORD		 pBA,
177	TR_SELECT		 TxRxSelect,
178	u16			 ReasonCode
179	)
180{
181	DELBA_PARAM_SET	DelbaParamSet;
182	struct sk_buff *skb = NULL;
183	 struct ieee80211_hdr_3addr* Delba = NULL;
184	u8* tag = NULL;
185	u16 tmp = 0;
186	//len = head len + DELBA Parameter Set(2) + Reason Code(2)
187	u16 len = 6 + ieee->tx_headroom;
188
189	if (net_ratelimit())
190	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
191
192	memset(&DelbaParamSet, 0, 2);
193
194	DelbaParamSet.field.Initiator	= (TxRxSelect==TX_DIR)?1:0;
195	DelbaParamSet.field.TID	= pBA->BaParamSet.field.TID;
196
197	skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr));
198	if (skb == NULL)
199	{
200		IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
201		return NULL;
202	}
203//	memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr));
204	skb_reserve(skb, ieee->tx_headroom);
205
206	Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
207
208	memcpy(Delba->addr1, dst, ETH_ALEN);
209	memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
210	memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
211	Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
212
213	tag = (u8*)skb_put(skb, 6);
214
215	*tag ++= ACT_CAT_BA;
216	*tag ++= ACT_DELBA;
217
218	// DELBA Parameter Set
219	tmp = cpu_to_le16(DelbaParamSet.shortData);
220	memcpy(tag, (u8*)&tmp, 2);
221	tag += 2;
222	// Reason Code
223	tmp = cpu_to_le16(ReasonCode);
224	memcpy(tag, (u8*)&tmp, 2);
225	tag += 2;
226
227	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
228	if (net_ratelimit())
229	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__);
230	return skb;
231}
232
233/********************************************************************************************************************
234 *function: send ADDBAReq frame out
235 *   input:  u8* 		dst 	//ADDBAReq frame's destination
236 *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA
237 *  output:  none
238 *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
239********************************************************************************************************************/
240void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8*	dst, PBA_RECORD	pBA)
241{
242	struct sk_buff *skb = NULL;
243	skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
244
245	if (skb)
246	{
247		softmac_mgmt_xmit(skb, ieee);
248		//add statistic needed here.
249		//and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
250		//WB
251	}
252	else
253	{
254		IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
255	}
256	return;
257}
258
259/********************************************************************************************************************
260 *function: send ADDBARSP frame out
261 *   input:  u8* 		dst 	//DELBA frame's destination
262 *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA
263 *   	     u16		StatusCode //RSP StatusCode
264 *  output:  none
265 *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
266********************************************************************************************************************/
267void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
268{
269	struct sk_buff *skb = NULL;
270	skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
271	if (skb)
272	{
273		softmac_mgmt_xmit(skb, ieee);
274		//same above
275	}
276	else
277	{
278		IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
279	}
280
281	return;
282
283}
284/********************************************************************************************************************
285 *function: send ADDBARSP frame out
286 *   input:  u8* 		dst 	//DELBA frame's destination
287 *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA
288 *   	     TR_SELECT          TxRxSelect //TX or RX
289 *   	     u16		ReasonCode //DEL ReasonCode
290 *  output:  none
291 *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
292********************************************************************************************************************/
293
294void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
295{
296	struct sk_buff *skb = NULL;
297	skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
298	if (skb)
299	{
300		softmac_mgmt_xmit(skb, ieee);
301		//same above
302	}
303	else
304	{
305		IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
306	}
307	return ;
308}
309
310/********************************************************************************************************************
311 *function: RX ADDBAReq
312 *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
313 *  return:  0(pass), other(fail)
314 *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
315********************************************************************************************************************/
316int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
317{
318	 struct ieee80211_hdr_3addr* req = NULL;
319	u16 rc = 0;
320	u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
321	PBA_RECORD pBA = NULL;
322	PBA_PARAM_SET	pBaParamSet = NULL;
323	u16* pBaTimeoutVal = NULL;
324	PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
325	PRX_TS_RECORD	pTS = NULL;
326
327	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
328	{
329		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, 	(sizeof( struct ieee80211_hdr_3addr) + 9));
330		return -1;
331	}
332
333	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
334
335	req = ( struct ieee80211_hdr_3addr*) skb->data;
336	tag = (u8*)req;
337	dst = (u8*)(&req->addr2[0]);
338	tag += sizeof( struct ieee80211_hdr_3addr);
339	pDialogToken = tag + 2;  //category+action
340	pBaParamSet = (PBA_PARAM_SET)(tag + 3);   //+DialogToken
341	pBaTimeoutVal = (u16*)(tag + 5);
342	pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
343
344	printk("====================>rx ADDBAREQ from :%pM\n", dst);
345//some other capability is not ready now.
346	if(	(ieee->current_network.qos_data.active == 0) ||
347		(ieee->pHTInfo->bCurrentHTSupport == false)) //||
348	//	(ieee->pStaQos->bEnableRxImmBA == false)	)
349	{
350		rc = ADDBA_STATUS_REFUSED;
351		IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
352		goto OnADDBAReq_Fail;
353	}
354	// Search for related traffic stream.
355	// If there is no matched TS, reject the ADDBA request.
356	if(	!GetTs(
357			ieee,
358			(PTS_COMMON_INFO*)(&pTS),
359			dst,
360			(u8)(pBaParamSet->field.TID),
361			RX_DIR,
362			true)	)
363	{
364		rc = ADDBA_STATUS_REFUSED;
365		IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
366		goto OnADDBAReq_Fail;
367	}
368	pBA = &pTS->RxAdmittedBARecord;
369	// To Determine the ADDBA Req content
370	// We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
371	// I want to check StartSeqCtrl to make sure when we start aggregation!!!
372	//
373	if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
374	{
375		rc = ADDBA_STATUS_INVALID_PARAM;
376		IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
377		goto OnADDBAReq_Fail;
378	}
379		// Admit the ADDBA Request
380	//
381	DeActivateBAEntry(ieee, pBA);
382	pBA->DialogToken = *pDialogToken;
383	pBA->BaParamSet = *pBaParamSet;
384	pBA->BaTimeoutValue = *pBaTimeoutVal;
385	pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
386	//for half N mode we only aggregate 1 frame
387	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
388	pBA->BaParamSet.field.BufferSize = 1;
389	else
390	pBA->BaParamSet.field.BufferSize = 32;
391	ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
392	ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
393
394	// End of procedure.
395	return 0;
396
397OnADDBAReq_Fail:
398	{
399		BA_RECORD	BA;
400		BA.BaParamSet = *pBaParamSet;
401		BA.BaTimeoutValue = *pBaTimeoutVal;
402		BA.DialogToken = *pDialogToken;
403		BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
404		ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
405		return 0; //we send RSP out.
406	}
407
408}
409
410/********************************************************************************************************************
411 *function: RX ADDBARSP
412 *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
413 *  return:  0(pass), other(fail)
414 *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
415********************************************************************************************************************/
416int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
417{
418	 struct ieee80211_hdr_3addr* rsp = NULL;
419	PBA_RECORD		pPendingBA, pAdmittedBA;
420	PTX_TS_RECORD		pTS = NULL;
421	u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
422	u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
423	PBA_PARAM_SET		pBaParamSet = NULL;
424	u16			ReasonCode;
425
426	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
427	{
428		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, 	(sizeof( struct ieee80211_hdr_3addr) + 9));
429		return -1;
430	}
431	rsp = ( struct ieee80211_hdr_3addr*)skb->data;
432	tag = (u8*)rsp;
433	dst = (u8*)(&rsp->addr2[0]);
434	tag += sizeof( struct ieee80211_hdr_3addr);
435	pDialogToken = tag + 2;
436	pStatusCode = (u16*)(tag + 3);
437	pBaParamSet = (PBA_PARAM_SET)(tag + 5);
438	pBaTimeoutVal = (u16*)(tag + 7);
439
440	// Check the capability
441	// Since we can always receive A-MPDU, we just check if it is under HT mode.
442	if(     ieee->current_network.qos_data.active == 0  ||
443		ieee->pHTInfo->bCurrentHTSupport == false ||
444		ieee->pHTInfo->bCurrentAMPDUEnable == false )
445	{
446		IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
447		ReasonCode = DELBA_REASON_UNKNOWN_BA;
448		goto OnADDBARsp_Reject;
449	}
450
451
452	//
453	// Search for related TS.
454	// If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
455	//
456	if (!GetTs(
457			ieee,
458			(PTS_COMMON_INFO*)(&pTS),
459			dst,
460			(u8)(pBaParamSet->field.TID),
461			TX_DIR,
462			false)	)
463	{
464		IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
465		ReasonCode = DELBA_REASON_UNKNOWN_BA;
466		goto OnADDBARsp_Reject;
467	}
468
469	pTS->bAddBaReqInProgress = false;
470	pPendingBA = &pTS->TxPendingBARecord;
471	pAdmittedBA = &pTS->TxAdmittedBARecord;
472
473
474	//
475	// Check if related BA is waiting for setup.
476	// If not, reject by sending DELBA frame.
477	//
478	if((pAdmittedBA->bValid==true))
479	{
480		// Since BA is already setup, we ignore all other ADDBA Response.
481		IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
482		return -1;
483	}
484	else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
485	{
486		IEEE80211_DEBUG(IEEE80211_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
487		ReasonCode = DELBA_REASON_UNKNOWN_BA;
488		goto OnADDBARsp_Reject;
489	}
490	else
491	{
492		IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
493		DeActivateBAEntry(ieee, pPendingBA);
494	}
495
496
497	if(*pStatusCode == ADDBA_STATUS_SUCCESS)
498	{
499		//
500		// Determine ADDBA Rsp content here.
501		// We can compare the value of BA parameter set that Peer returned and Self sent.
502		// If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
503		//
504		if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
505		{
506			// Since this is a kind of ADDBA failed, we delay next ADDBA process.
507			pTS->bAddBaReqDelayed = true;
508			DeActivateBAEntry(ieee, pAdmittedBA);
509			ReasonCode = DELBA_REASON_END_BA;
510			goto OnADDBARsp_Reject;
511		}
512
513
514		//
515		// Admitted condition
516		//
517		pAdmittedBA->DialogToken = *pDialogToken;
518		pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
519		pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
520		pAdmittedBA->BaParamSet = *pBaParamSet;
521		DeActivateBAEntry(ieee, pAdmittedBA);
522		ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
523	}
524	else
525	{
526		// Delay next ADDBA process.
527		pTS->bAddBaReqDelayed = true;
528	}
529
530	// End of procedure
531	return 0;
532
533OnADDBARsp_Reject:
534	{
535		BA_RECORD	BA;
536		BA.BaParamSet = *pBaParamSet;
537		ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
538		return 0;
539	}
540
541}
542
543/********************************************************************************************************************
544 *function: RX DELBA
545 *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
546 *  return:  0(pass), other(fail)
547 *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
548********************************************************************************************************************/
549int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
550{
551	 struct ieee80211_hdr_3addr* delba = NULL;
552	PDELBA_PARAM_SET	pDelBaParamSet = NULL;
553	u16*			pReasonCode = NULL;
554	u8*			dst = NULL;
555
556	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
557	{
558		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, 	(sizeof( struct ieee80211_hdr_3addr) + 6));
559		return -1;
560	}
561
562	if(ieee->current_network.qos_data.active == 0 ||
563		ieee->pHTInfo->bCurrentHTSupport == false )
564	{
565		IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
566		return -1;
567	}
568
569	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
570	delba = ( struct ieee80211_hdr_3addr*)skb->data;
571	dst = (u8*)(&delba->addr2[0]);
572	delba += sizeof( struct ieee80211_hdr_3addr);
573	pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
574	pReasonCode = (u16*)(delba+4);
575
576	if(pDelBaParamSet->field.Initiator == 1)
577	{
578		PRX_TS_RECORD 	pRxTs;
579
580		if( !GetTs(
581				ieee,
582				(PTS_COMMON_INFO*)&pRxTs,
583				dst,
584				(u8)pDelBaParamSet->field.TID,
585				RX_DIR,
586				false)	)
587		{
588			IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for RXTS in %s()\n", __FUNCTION__);
589			return -1;
590		}
591
592		RxTsDeleteBA(ieee, pRxTs);
593	}
594	else
595	{
596		PTX_TS_RECORD	pTxTs;
597
598		if(!GetTs(
599			ieee,
600			(PTS_COMMON_INFO*)&pTxTs,
601			dst,
602			(u8)pDelBaParamSet->field.TID,
603			TX_DIR,
604			false)	)
605		{
606			IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for TXTS in %s()\n", __FUNCTION__);
607			return -1;
608		}
609
610		pTxTs->bUsingBa = false;
611		pTxTs->bAddBaReqInProgress = false;
612		pTxTs->bAddBaReqDelayed = false;
613		del_timer_sync(&pTxTs->TsAddBaTimer);
614		//PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
615		TxTsDeleteBA(ieee, pTxTs);
616	}
617	return 0;
618}
619
620//
621// ADDBA initiate. This can only be called by TX side.
622//
623void
624TsInitAddBA(
625	struct ieee80211_device* ieee,
626	PTX_TS_RECORD	pTS,
627	u8		Policy,
628	u8		bOverwritePending
629	)
630{
631	PBA_RECORD			pBA = &pTS->TxPendingBARecord;
632
633	if(pBA->bValid==true && bOverwritePending==false)
634		return;
635
636	// Set parameters to "Pending" variable set
637	DeActivateBAEntry(ieee, pBA);
638
639	pBA->DialogToken++;						// DialogToken: Only keep the latest dialog token
640	pBA->BaParamSet.field.AMSDU_Support = 0;	// Do not support A-MSDU with A-MPDU now!!
641	pBA->BaParamSet.field.BAPolicy = Policy;	// Policy: Delayed or Immediate
642	pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;	// TID
643	// BufferSize: This need to be set according to A-MPDU vector
644	pBA->BaParamSet.field.BufferSize = 32;		// BufferSize: This need to be set according to A-MPDU vector
645	pBA->BaTimeoutValue = 0;					// Timeout value: Set 0 to disable Timer
646	pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; 	// Block Ack will start after 3 packets later.
647
648	ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
649
650	ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
651}
652
653void
654TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
655{
656
657	if(TxRxSelect == TX_DIR)
658	{
659		PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
660
661		if(TxTsDeleteBA(ieee, pTxTs))
662			ieee80211_send_DELBA(
663				ieee,
664				pTsCommonInfo->Addr,
665				(pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
666				TxRxSelect,
667				DELBA_REASON_END_BA);
668	}
669	else if(TxRxSelect == RX_DIR)
670	{
671		PRX_TS_RECORD	pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
672		if(RxTsDeleteBA(ieee, pRxTs))
673			ieee80211_send_DELBA(
674				ieee,
675				pTsCommonInfo->Addr,
676				&pRxTs->RxAdmittedBARecord,
677				TxRxSelect,
678				DELBA_REASON_END_BA	);
679	}
680}
681/********************************************************************************************************************
682 *function:  BA setup timer
683 *   input:  unsigned long	 data		//acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
684 *  return:  NULL
685 *  notice:
686********************************************************************************************************************/
687void BaSetupTimeOut(unsigned long data)
688{
689	PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)data;
690
691	pTxTs->bAddBaReqInProgress = false;
692	pTxTs->bAddBaReqDelayed = true;
693	pTxTs->TxPendingBARecord.bValid = false;
694}
695
696void TxBaInactTimeout(unsigned long data)
697{
698	PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)data;
699	struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
700	TxTsDeleteBA(ieee, pTxTs);
701	ieee80211_send_DELBA(
702		ieee,
703		pTxTs->TsCommonInfo.Addr,
704		&pTxTs->TxAdmittedBARecord,
705		TX_DIR,
706		DELBA_REASON_TIMEOUT);
707}
708
709void RxBaInactTimeout(unsigned long data)
710{
711	PRX_TS_RECORD	pRxTs = (PRX_TS_RECORD)data;
712	struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
713
714	RxTsDeleteBA(ieee, pRxTs);
715	ieee80211_send_DELBA(
716		ieee,
717		pRxTs->TsCommonInfo.Addr,
718		&pRxTs->RxAdmittedBARecord,
719		RX_DIR,
720		DELBA_REASON_TIMEOUT);
721	return ;
722}
723