rtl819x_BAProc.c revision 8cf33316817d8349fa3125584a0f4767b3e4b72d
1/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 *
4 * This program is distributed in the hope that it will be useful, but WITHOUT
5 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
7 * more details.
8 *
9 * You should have received a copy of the GNU General Public License along with
10 * this program; if not, write to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
12 *
13 * The full GNU General Public License is included in this distribution in the
14 * file called LICENSE.
15 *
16 * Contact Information:
17 * wlanfae <wlanfae@realtek.com>
18******************************************************************************/
19#include "rtllib.h"
20#include "rtl819x_BA.h"
21#include "rtl_core.h"
22
23void ActivateBAEntry(struct rtllib_device* ieee, struct ba_record *pBA, u16 Time)
24{
25	pBA->bValid = true;
26	if (Time != 0)
27		mod_timer(&pBA->Timer, jiffies + MSECS(Time));
28}
29
30void DeActivateBAEntry( struct rtllib_device* ieee, struct ba_record *pBA)
31{
32	pBA->bValid = false;
33	del_timer_sync(&pBA->Timer);
34}
35u8 TxTsDeleteBA( struct rtllib_device* ieee, struct tx_ts_record *pTxTs)
36{
37	struct ba_record *pAdmittedBa = &pTxTs->TxAdmittedBARecord;
38	struct ba_record *pPendingBa = &pTxTs->TxPendingBARecord;
39	u8			bSendDELBA = false;
40
41	if (pPendingBa->bValid)
42	{
43		DeActivateBAEntry(ieee, pPendingBa);
44		bSendDELBA = true;
45	}
46
47	if (pAdmittedBa->bValid)
48	{
49		DeActivateBAEntry(ieee, pAdmittedBa);
50		bSendDELBA = true;
51	}
52
53	return bSendDELBA;
54}
55
56u8 RxTsDeleteBA( struct rtllib_device* ieee, struct rx_ts_record *pRxTs)
57{
58	struct ba_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
70void ResetBaEntry( struct ba_record *pBA)
71{
72	pBA->bValid			= false;
73	pBA->BaParamSet.shortData	= 0;
74	pBA->BaTimeoutValue		= 0;
75	pBA->DialogToken		= 0;
76	pBA->BaStartSeqCtrl.ShortData	= 0;
77}
78static struct sk_buff* rtllib_ADDBA(struct rtllib_device* ieee, u8* Dst, struct ba_record *pBA, u16 StatusCode, u8 type)
79{
80	struct sk_buff *skb = NULL;
81	 struct rtllib_hdr_3addr* BAReq = NULL;
82	u8* tag = NULL;
83	u16 tmp = 0;
84	u16 len = ieee->tx_headroom + 9;
85	RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __func__, type, MAC_ARG(Dst), ieee->dev);
86	if (pBA == NULL||ieee == NULL)
87	{
88		RTLLIB_DEBUG(RTLLIB_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
89		return NULL;
90	}
91	skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr));
92	if (skb == NULL)
93	{
94		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
95		return NULL;
96	}
97
98	memset(skb->data, 0, sizeof( struct rtllib_hdr_3addr));
99
100	skb_reserve(skb, ieee->tx_headroom);
101
102	BAReq = ( struct rtllib_hdr_3addr *) skb_put(skb,sizeof( struct rtllib_hdr_3addr));
103
104	memcpy(BAReq->addr1, Dst, ETH_ALEN);
105	memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
106
107	memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
108	BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);
109
110	tag = (u8*)skb_put(skb, 9);
111	*tag ++= ACT_CAT_BA;
112	*tag ++= type;
113	*tag ++= pBA->DialogToken;
114
115	if (ACT_ADDBARSP == type)
116	{
117		RT_TRACE(COMP_DBG, "====>to send ADDBARSP\n");
118		tmp = cpu_to_le16(StatusCode);
119		memcpy(tag, (u8*)&tmp, 2);
120		tag += 2;
121	}
122	tmp = cpu_to_le16(pBA->BaParamSet.shortData);
123	memcpy(tag, (u8*)&tmp, 2);
124	tag += 2;
125	tmp = cpu_to_le16(pBA->BaTimeoutValue);
126	memcpy(tag, (u8*)&tmp, 2);
127	tag += 2;
128
129	if (ACT_ADDBAREQ == type)
130	{
131		memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
132		tag += 2;
133	}
134
135	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
136	return skb;
137}
138
139static struct sk_buff* rtllib_DELBA(
140	struct rtllib_device* ieee,
141	u8*		         dst,
142	struct ba_record *pBA,
143	TR_SELECT		 TxRxSelect,
144	u16			 ReasonCode
145	)
146{
147	DELBA_PARAM_SET	DelbaParamSet;
148	struct sk_buff *skb = NULL;
149	 struct rtllib_hdr_3addr* Delba = NULL;
150	u8* tag = NULL;
151	u16 tmp = 0;
152	u16 len = 6 + ieee->tx_headroom;
153
154	if (net_ratelimit())
155	RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __func__, ReasonCode, MAC_ARG(dst));
156
157	memset(&DelbaParamSet, 0, 2);
158
159	DelbaParamSet.field.Initiator	= (TxRxSelect==TX_DIR)?1:0;
160	DelbaParamSet.field.TID	= pBA->BaParamSet.field.TID;
161
162	skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr));
163	if (skb == NULL)
164	{
165		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
166		return NULL;
167	}
168
169	skb_reserve(skb, ieee->tx_headroom);
170
171	Delba = ( struct rtllib_hdr_3addr *) skb_put(skb,sizeof( struct rtllib_hdr_3addr));
172
173	memcpy(Delba->addr1, dst, ETH_ALEN);
174	memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
175	memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
176	Delba->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);
177
178	tag = (u8*)skb_put(skb, 6);
179
180	*tag ++= ACT_CAT_BA;
181	*tag ++= ACT_DELBA;
182
183	tmp = cpu_to_le16(DelbaParamSet.shortData);
184	memcpy(tag, (u8*)&tmp, 2);
185	tag += 2;
186	tmp = cpu_to_le16(ReasonCode);
187	memcpy(tag, (u8*)&tmp, 2);
188	tag += 2;
189
190	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
191	if (net_ratelimit())
192	RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "<=====%s()\n", __func__);
193	return skb;
194}
195
196void rtllib_send_ADDBAReq(struct rtllib_device* ieee, u8*	dst, struct ba_record *pBA)
197{
198	struct sk_buff *skb = NULL;
199	skb = rtllib_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ);
200
201	if (skb) {
202		RT_TRACE(COMP_DBG, "====>to send ADDBAREQ!!!!!\n");
203		softmac_mgmt_xmit(skb, ieee);
204	} else {
205		RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __func__);
206	}
207	return;
208}
209
210void rtllib_send_ADDBARsp(struct rtllib_device* ieee, u8* dst, struct ba_record *pBA, u16 StatusCode)
211{
212	struct sk_buff *skb = NULL;
213	skb = rtllib_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP);
214	if (skb)
215		softmac_mgmt_xmit(skb, ieee);
216	else
217		RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __func__);
218
219	return;
220
221}
222
223void rtllib_send_DELBA(struct rtllib_device* ieee, u8* dst, struct ba_record *pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
224{
225	struct sk_buff *skb = NULL;
226	skb = rtllib_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode);
227	if (skb)
228	{
229		softmac_mgmt_xmit(skb, ieee);
230	}
231	else
232	{
233		RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __func__);
234	}
235	return ;
236}
237
238int rtllib_rx_ADDBAReq( struct rtllib_device* ieee, struct sk_buff *skb)
239{
240	 struct rtllib_hdr_3addr* req = NULL;
241	u16 rc = 0;
242	u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
243	struct ba_record *pBA = NULL;
244	PBA_PARAM_SET	pBaParamSet = NULL;
245	u16* pBaTimeoutVal = NULL;
246	PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
247	struct rx_ts_record *pTS = NULL;
248
249	if (skb->len < sizeof( struct rtllib_hdr_3addr) + 9)
250	{
251		RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n",(int)skb->len,	(int)(sizeof( struct rtllib_hdr_3addr) + 9));
252		return -1;
253	}
254
255	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
256
257	req = ( struct rtllib_hdr_3addr*) skb->data;
258	tag = (u8*)req;
259	dst = (u8*)(&req->addr2[0]);
260	tag += sizeof( struct rtllib_hdr_3addr);
261	pDialogToken = tag + 2;
262	pBaParamSet = (PBA_PARAM_SET)(tag + 3);
263	pBaTimeoutVal = (u16*)(tag + 5);
264	pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
265
266	RT_TRACE(COMP_DBG, "====>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));
267	if (ieee->current_network.qos_data.active == 0  ||
268	    (ieee->pHTInfo->bCurrentHTSupport == false) ||
269	    (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) {
270		rc = ADDBA_STATUS_REFUSED;
271		RTLLIB_DEBUG(RTLLIB_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);
272		goto OnADDBAReq_Fail;
273	}
274	if (!GetTs(
275			ieee,
276			(struct ts_common_info **)(&pTS),
277			dst,
278			(u8)(pBaParamSet->field.TID),
279			RX_DIR,
280			true)	)
281	{
282		rc = ADDBA_STATUS_REFUSED;
283		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __func__);
284		goto OnADDBAReq_Fail;
285	}
286	pBA = &pTS->RxAdmittedBARecord;
287
288	if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
289	{
290		rc = ADDBA_STATUS_INVALID_PARAM;
291		RTLLIB_DEBUG(RTLLIB_DL_ERR, "BA Policy is not correct in %s()\n", __func__);
292		goto OnADDBAReq_Fail;
293	}
294
295
296	rtllib_FlushRxTsPendingPkts(ieee, pTS);
297
298	DeActivateBAEntry(ieee, pBA);
299	pBA->DialogToken = *pDialogToken;
300	pBA->BaParamSet = *pBaParamSet;
301	pBA->BaTimeoutValue = *pBaTimeoutVal;
302	pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
303
304	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)||
305	(ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT))
306	pBA->BaParamSet.field.BufferSize = 1;
307	else
308	pBA->BaParamSet.field.BufferSize = 32;
309
310	ActivateBAEntry(ieee, pBA, 0);
311	rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
312
313	return 0;
314
315OnADDBAReq_Fail:
316	{
317		struct ba_record BA;
318		BA.BaParamSet = *pBaParamSet;
319		BA.BaTimeoutValue = *pBaTimeoutVal;
320		BA.DialogToken = *pDialogToken;
321		BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
322		rtllib_send_ADDBARsp(ieee, dst, &BA, rc);
323		return 0;
324	}
325
326}
327
328int rtllib_rx_ADDBARsp( struct rtllib_device* ieee, struct sk_buff *skb)
329{
330	 struct rtllib_hdr_3addr* rsp = NULL;
331	struct ba_record *pPendingBA, *pAdmittedBA;
332	struct tx_ts_record *pTS = NULL;
333	u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
334	u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
335	PBA_PARAM_SET		pBaParamSet = NULL;
336	u16			ReasonCode;
337
338	if (skb->len < sizeof( struct rtllib_hdr_3addr) + 9)
339	{
340		RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", (int)skb->len,	(int)(sizeof( struct rtllib_hdr_3addr) + 9));
341		return -1;
342	}
343	rsp = ( struct rtllib_hdr_3addr*)skb->data;
344	tag = (u8*)rsp;
345	dst = (u8*)(&rsp->addr2[0]);
346	tag += sizeof( struct rtllib_hdr_3addr);
347	pDialogToken = tag + 2;
348	pStatusCode = (u16*)(tag + 3);
349	pBaParamSet = (PBA_PARAM_SET)(tag + 5);
350	pBaTimeoutVal = (u16*)(tag + 7);
351
352	RT_TRACE(COMP_DBG, "====>rx ADDBARSP from :"MAC_FMT"\n", MAC_ARG(dst));
353	if (
354		ieee->current_network.qos_data.active == 0  ||
355		ieee->pHTInfo->bCurrentHTSupport == false ||
356		ieee->pHTInfo->bCurrentAMPDUEnable == false )
357	{
358		RTLLIB_DEBUG(RTLLIB_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);
359		ReasonCode = DELBA_REASON_UNKNOWN_BA;
360		goto OnADDBARsp_Reject;
361	}
362
363
364	if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
365		   (u8)(pBaParamSet->field.TID), TX_DIR, false)) {
366		RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __func__);
367		ReasonCode = DELBA_REASON_UNKNOWN_BA;
368		goto OnADDBARsp_Reject;
369	}
370
371	pTS->bAddBaReqInProgress = false;
372	pPendingBA = &pTS->TxPendingBARecord;
373	pAdmittedBA = &pTS->TxAdmittedBARecord;
374
375
376	if ((pAdmittedBA->bValid==true))
377	{
378		RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
379		return -1;
380	}
381	else if ((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
382	{
383		RTLLIB_DEBUG(RTLLIB_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
384		ReasonCode = DELBA_REASON_UNKNOWN_BA;
385		goto OnADDBARsp_Reject;
386	}
387	else
388	{
389		RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
390		DeActivateBAEntry(ieee, pPendingBA);
391	}
392
393
394	if (*pStatusCode == ADDBA_STATUS_SUCCESS)
395	{
396		if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
397		{
398			pTS->bAddBaReqDelayed = true;
399			DeActivateBAEntry(ieee, pAdmittedBA);
400			ReasonCode = DELBA_REASON_END_BA;
401			goto OnADDBARsp_Reject;
402		}
403
404
405		pAdmittedBA->DialogToken = *pDialogToken;
406		pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
407		pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
408		pAdmittedBA->BaParamSet = *pBaParamSet;
409		DeActivateBAEntry(ieee, pAdmittedBA);
410		ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
411	} else {
412		pTS->bAddBaReqDelayed = true;
413		pTS->bDisable_AddBa = true;
414		ReasonCode = DELBA_REASON_END_BA;
415		goto OnADDBARsp_Reject;
416	}
417
418	return 0;
419
420OnADDBARsp_Reject:
421	{
422		struct ba_record BA;
423		BA.BaParamSet = *pBaParamSet;
424		rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
425		return 0;
426	}
427
428}
429
430int rtllib_rx_DELBA(struct rtllib_device* ieee,struct sk_buff *skb)
431{
432	 struct rtllib_hdr_3addr* delba = NULL;
433	PDELBA_PARAM_SET	pDelBaParamSet = NULL;
434	u16*			pReasonCode = NULL;
435	u8*			dst = NULL;
436
437	if (skb->len < sizeof( struct rtllib_hdr_3addr) + 6)
438	{
439		RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", (int)skb->len,	(int)(sizeof( struct rtllib_hdr_3addr) + 6));
440		return -1;
441	}
442
443	if (
444		ieee->current_network.qos_data.active == 0  ||
445		ieee->pHTInfo->bCurrentHTSupport == false )
446	{
447		RTLLIB_DEBUG(RTLLIB_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
448		return -1;
449	}
450
451	RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
452	delba = ( struct rtllib_hdr_3addr*)skb->data;
453	dst = (u8*)(&delba->addr2[0]);
454	delba += sizeof( struct rtllib_hdr_3addr);
455	pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
456	pReasonCode = (u16*)(delba+4);
457
458	if (pDelBaParamSet->field.Initiator == 1)
459	{
460		struct rx_ts_record *pRxTs;
461
462		if ( !GetTs(
463				ieee,
464				(struct ts_common_info **)&pRxTs,
465				dst,
466				(u8)pDelBaParamSet->field.TID,
467				RX_DIR,
468				false)	)
469		{
470			RTLLIB_DEBUG(RTLLIB_DL_ERR,  "can't get TS for RXTS in %s().dst:"MAC_FMT" TID:%d\n", __func__, MAC_ARG(dst), (u8)pDelBaParamSet->field.TID);
471			return -1;
472		}
473
474		RxTsDeleteBA(ieee, pRxTs);
475	}
476	else
477	{
478		struct tx_ts_record *pTxTs;
479
480		if (!GetTs(
481			ieee,
482			(struct ts_common_info **)&pTxTs,
483			dst,
484			(u8)pDelBaParamSet->field.TID,
485			TX_DIR,
486			false)	)
487		{
488			RTLLIB_DEBUG(RTLLIB_DL_ERR,  "can't get TS for TXTS in %s()\n", __func__);
489			return -1;
490		}
491
492		pTxTs->bUsingBa = false;
493		pTxTs->bAddBaReqInProgress = false;
494		pTxTs->bAddBaReqDelayed = false;
495		del_timer_sync(&pTxTs->TsAddBaTimer);
496		TxTsDeleteBA(ieee, pTxTs);
497	}
498	return 0;
499}
500
501void
502TsInitAddBA(
503	struct rtllib_device* ieee,
504	struct tx_ts_record *pTS,
505	u8		Policy,
506	u8		bOverwritePending
507	)
508{
509	struct ba_record *pBA = &pTS->TxPendingBARecord;
510
511	if (pBA->bValid==true && bOverwritePending==false)
512		return;
513
514	DeActivateBAEntry(ieee, pBA);
515
516	pBA->DialogToken++;
517	pBA->BaParamSet.field.AMSDU_Support = 0;
518	pBA->BaParamSet.field.BAPolicy = Policy;
519	pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;
520	pBA->BaParamSet.field.BufferSize = 32;
521	pBA->BaTimeoutValue = 0;
522	pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096;
523
524	ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
525
526	rtllib_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
527}
528
529void
530TsInitDelBA( struct rtllib_device* ieee, struct ts_common_info *pTsCommonInfo, TR_SELECT TxRxSelect)
531{
532
533	if (TxRxSelect == TX_DIR)
534	{
535		struct tx_ts_record *pTxTs = (struct tx_ts_record *)pTsCommonInfo;
536
537		if (TxTsDeleteBA(ieee, pTxTs))
538			rtllib_send_DELBA(
539				ieee,
540				pTsCommonInfo->Addr,
541				(pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
542				TxRxSelect,
543				DELBA_REASON_END_BA);
544	}
545	else if (TxRxSelect == RX_DIR)
546	{
547		struct rx_ts_record *pRxTs = (struct rx_ts_record *)pTsCommonInfo;
548		if (RxTsDeleteBA(ieee, pRxTs))
549			rtllib_send_DELBA(
550				ieee,
551				pTsCommonInfo->Addr,
552				&pRxTs->RxAdmittedBARecord,
553				TxRxSelect,
554				DELBA_REASON_END_BA	);
555	}
556}
557void BaSetupTimeOut(unsigned long data)
558{
559	struct tx_ts_record *pTxTs = (struct tx_ts_record *)data;
560
561	pTxTs->bAddBaReqInProgress = false;
562	pTxTs->bAddBaReqDelayed = true;
563	pTxTs->TxPendingBARecord.bValid = false;
564}
565
566void TxBaInactTimeout(unsigned long data)
567{
568	struct tx_ts_record *pTxTs = (struct tx_ts_record *)data;
569	struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device, TxTsRecord[pTxTs->num]);
570	TxTsDeleteBA(ieee, pTxTs);
571	rtllib_send_DELBA(
572		ieee,
573		pTxTs->TsCommonInfo.Addr,
574		&pTxTs->TxAdmittedBARecord,
575		TX_DIR,
576		DELBA_REASON_TIMEOUT);
577}
578
579void RxBaInactTimeout(unsigned long data)
580{
581	struct rx_ts_record *pRxTs = (struct rx_ts_record *)data;
582	struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, RxTsRecord[pRxTs->num]);
583
584	RxTsDeleteBA(ieee, pRxTs);
585	rtllib_send_DELBA(
586		ieee,
587		pRxTs->TsCommonInfo.Addr,
588		&pRxTs->RxAdmittedBARecord,
589		RX_DIR,
590		DELBA_REASON_TIMEOUT);
591	return ;
592}
593