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