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