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