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