Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtl819x_BAProc.c
Go to the documentation of this file.
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 <[email protected]>
18 ******************************************************************************/
19 #include "rtllib.h"
20 #include "rtl819x_BA.h"
21 
22 static void ActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA,
23  u16 Time)
24 {
25  pBA->bValid = true;
26  if (Time != 0)
27  mod_timer(&pBA->Timer, jiffies + MSECS(Time));
28 }
29 
30 static void DeActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA)
31 {
32  pBA->bValid = false;
33  del_timer_sync(&pBA->Timer);
34 }
35 
36 static u8 TxTsDeleteBA(struct rtllib_device *ieee, struct tx_ts_record *pTxTs)
37 {
38  struct ba_record *pAdmittedBa = &pTxTs->TxAdmittedBARecord;
39  struct ba_record *pPendingBa = &pTxTs->TxPendingBARecord;
40  u8 bSendDELBA = false;
41 
42  if (pPendingBa->bValid) {
43  DeActivateBAEntry(ieee, pPendingBa);
44  bSendDELBA = true;
45  }
46 
47  if (pAdmittedBa->bValid) {
48  DeActivateBAEntry(ieee, pAdmittedBa);
49  bSendDELBA = true;
50  }
51  return bSendDELBA;
52 }
53 
54 static u8 RxTsDeleteBA(struct rtllib_device *ieee, struct rx_ts_record *pRxTs)
55 {
56  struct ba_record *pBa = &pRxTs->RxAdmittedBARecord;
57  u8 bSendDELBA = false;
58 
59  if (pBa->bValid) {
60  DeActivateBAEntry(ieee, pBa);
61  bSendDELBA = true;
62  }
63 
64  return bSendDELBA;
65 }
66 
67 void ResetBaEntry(struct ba_record *pBA)
68 {
69  pBA->bValid = false;
70  pBA->BaParamSet.shortData = 0;
71  pBA->BaTimeoutValue = 0;
72  pBA->DialogToken = 0;
73  pBA->BaStartSeqCtrl.ShortData = 0;
74 }
75 static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *Dst,
76  struct ba_record *pBA,
77  u16 StatusCode, u8 type)
78 {
79  struct sk_buff *skb = NULL;
80  struct rtllib_hdr_3addr *BAReq = NULL;
81  u8 *tag = NULL;
82  u16 tmp = 0;
83  u16 len = ieee->tx_headroom + 9;
84 
85  RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), frame(%d)"
86  " sentd to: %pM, ieee->dev:%p\n", __func__,
87  type, Dst, ieee->dev);
88  if (pBA == NULL) {
89  RTLLIB_DEBUG(RTLLIB_DL_ERR, "pBA is NULL\n");
90  return NULL;
91  }
92  skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
93  if (skb == NULL) {
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,
103  sizeof(struct rtllib_hdr_3addr));
104 
105  memcpy(BAReq->addr1, Dst, ETH_ALEN);
106  memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
107 
108  memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
110 
111  tag = (u8 *)skb_put(skb, 9);
112  *tag ++= ACT_CAT_BA;
113  *tag ++= type;
114  *tag ++= pBA->DialogToken;
115 
116  if (ACT_ADDBARSP == type) {
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  memcpy(tag, (u8 *)&(pBA->BaStartSeqCtrl), 2);
131  tag += 2;
132  }
133 
135  return skb;
136 }
137 
138 static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst,
139  struct ba_record *pBA,
140  enum tr_select TxRxSelect, u16 ReasonCode)
141 {
142  union delba_param_set DelbaParamSet;
143  struct sk_buff *skb = NULL;
144  struct rtllib_hdr_3addr *Delba = NULL;
145  u8 *tag = NULL;
146  u16 tmp = 0;
147  u16 len = 6 + ieee->tx_headroom;
148 
149  if (net_ratelimit())
151  "========>%s(), Reason"
152  "Code(%d) sentd to: %pM\n", __func__,
153  ReasonCode, dst);
154 
155  memset(&DelbaParamSet, 0, 2);
156 
157  DelbaParamSet.field.Initiator = (TxRxSelect == TX_DIR) ? 1 : 0;
158  DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
159 
160  skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
161  if (skb == NULL) {
162  RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
163  return NULL;
164  }
165 
166  skb_reserve(skb, ieee->tx_headroom);
167 
168  Delba = (struct rtllib_hdr_3addr *) skb_put(skb,
169  sizeof(struct rtllib_hdr_3addr));
170 
171  memcpy(Delba->addr1, dst, ETH_ALEN);
172  memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
173  memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
175 
176  tag = (u8 *)skb_put(skb, 6);
177 
178  *tag ++= ACT_CAT_BA;
179  *tag ++= ACT_DELBA;
180 
181  tmp = cpu_to_le16(DelbaParamSet.shortData);
182  memcpy(tag, (u8 *)&tmp, 2);
183  tag += 2;
184  tmp = cpu_to_le16(ReasonCode);
185  memcpy(tag, (u8 *)&tmp, 2);
186  tag += 2;
187 
189  if (net_ratelimit())
190  RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "<=====%s()\n",
191  __func__);
192  return skb;
193 }
194 
195 static void rtllib_send_ADDBAReq(struct rtllib_device *ieee, u8 *dst,
196  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"
206  " %s()\n", __func__);
207  }
208  return;
209 }
210 
211 static void rtllib_send_ADDBARsp(struct rtllib_device *ieee, u8 *dst,
212  struct ba_record *pBA, u16 StatusCode)
213 {
214  struct sk_buff *skb = NULL;
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, "alloc skb error in function"
220  " %s()\n", __func__);
221  return;
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  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, "alloc skb error in func"
234  "tion %s()\n", __func__);
235  return ;
236 }
237 
238 int 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  union ba_param_set *pBaParamSet = NULL;
245  u16 *pBaTimeoutVal = NULL;
246  union sequence_control *pBaStartSeqCtrl = NULL;
247  struct rx_ts_record *pTS = NULL;
248 
249  if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
250  RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BAREQ(%d / "
251  "%d)\n", (int)skb->len,
252  (int)(sizeof(struct rtllib_hdr_3addr) + 9));
253  return -1;
254  }
255 
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)) {
272  RTLLIB_DEBUG(RTLLIB_DL_ERR, "Failed to reply on ADDBA_REQ as "
273  "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)) {
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) {
288  RTLLIB_DEBUG(RTLLIB_DL_ERR, "BA Policy is not correct in "
289  "%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 
312 OnADDBAReq_Fail:
313  {
314  struct ba_record BA;
315  BA.BaParamSet = *pBaParamSet;
316  BA.BaTimeoutValue = *pBaTimeoutVal;
317  BA.DialogToken = *pDialogToken;
318  BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
319  rtllib_send_ADDBARsp(ieee, dst, &BA, rc);
320  return 0;
321  }
322 }
323 
324 int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
325 {
326  struct rtllib_hdr_3addr *rsp = NULL;
327  struct ba_record *pPendingBA, *pAdmittedBA;
328  struct tx_ts_record *pTS = NULL;
329  u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
330  u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
331  union ba_param_set *pBaParamSet = NULL;
332  u16 ReasonCode;
333 
334  if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
335  RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BARSP(%d / "
336  "%d)\n", (int)skb->len,
337  (int)(sizeof(struct rtllib_hdr_3addr) + 9));
338  return -1;
339  }
340  rsp = (struct rtllib_hdr_3addr *)skb->data;
341  tag = (u8 *)rsp;
342  dst = (u8 *)(&rsp->addr2[0]);
343  tag += sizeof(struct rtllib_hdr_3addr);
344  pDialogToken = tag + 2;
345  pStatusCode = (u16 *)(tag + 3);
346  pBaParamSet = (union ba_param_set *)(tag + 5);
347  pBaTimeoutVal = (u16 *)(tag + 7);
348 
349  RT_TRACE(COMP_DBG, "====>rx ADDBARSP from : %pM\n", dst);
350  if (ieee->current_network.qos_data.active == 0 ||
351  ieee->pHTInfo->bCurrentHTSupport == false ||
352  ieee->pHTInfo->bCurrentAMPDUEnable == false) {
353  RTLLIB_DEBUG(RTLLIB_DL_ERR, "reject to ADDBA_RSP as some capab"
354  "ility is not ready(%d, %d, %d)\n",
355  ieee->current_network.qos_data.active,
356  ieee->pHTInfo->bCurrentHTSupport,
357  ieee->pHTInfo->bCurrentAMPDUEnable);
358  ReasonCode = DELBA_REASON_UNKNOWN_BA;
359  goto OnADDBARsp_Reject;
360  }
361 
362 
363  if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
364  (u8)(pBaParamSet->field.TID), TX_DIR, false)) {
365  RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __func__);
366  ReasonCode = DELBA_REASON_UNKNOWN_BA;
367  goto OnADDBARsp_Reject;
368  }
369 
370  pTS->bAddBaReqInProgress = false;
371  pPendingBA = &pTS->TxPendingBARecord;
372  pAdmittedBA = &pTS->TxAdmittedBARecord;
373 
374 
375  if ((pAdmittedBA->bValid == true)) {
376  RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp."
377  " Drop because already admit it!\n");
378  return -1;
379  } else if ((pPendingBA->bValid == false) ||
380  (*pDialogToken != pPendingBA->DialogToken)) {
381  RTLLIB_DEBUG(RTLLIB_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. "
382  "BA invalid, DELBA!\n");
383  ReasonCode = DELBA_REASON_UNKNOWN_BA;
384  goto OnADDBARsp_Reject;
385  } else {
386  RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA "
387  "is admitted! Status code:%X\n", *pStatusCode);
388  DeActivateBAEntry(ieee, pPendingBA);
389  }
390 
391 
392  if (*pStatusCode == ADDBA_STATUS_SUCCESS) {
393  if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
394  pTS->bAddBaReqDelayed = true;
395  DeActivateBAEntry(ieee, pAdmittedBA);
396  ReasonCode = DELBA_REASON_END_BA;
397  goto OnADDBARsp_Reject;
398  }
399 
400 
401  pAdmittedBA->DialogToken = *pDialogToken;
402  pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
403  pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
404  pAdmittedBA->BaParamSet = *pBaParamSet;
405  DeActivateBAEntry(ieee, pAdmittedBA);
406  ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
407  } else {
408  pTS->bAddBaReqDelayed = true;
409  pTS->bDisable_AddBa = true;
410  ReasonCode = DELBA_REASON_END_BA;
411  goto OnADDBARsp_Reject;
412  }
413 
414  return 0;
415 
416 OnADDBARsp_Reject:
417  {
418  struct ba_record BA;
419  BA.BaParamSet = *pBaParamSet;
420  rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
421  return 0;
422  }
423 }
424 
425 int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
426 {
427  struct rtllib_hdr_3addr *delba = NULL;
428  union delba_param_set *pDelBaParamSet = NULL;
429  u16 *pReasonCode = NULL;
430  u8 *dst = NULL;
431 
432  if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) {
433  RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in DELBA(%d /"
434  " %d)\n", (int)skb->len,
435  (int)(sizeof(struct rtllib_hdr_3addr) + 6));
436  return -1;
437  }
438 
439  if (ieee->current_network.qos_data.active == 0 ||
440  ieee->pHTInfo->bCurrentHTSupport == false) {
441  RTLLIB_DEBUG(RTLLIB_DL_ERR, "received DELBA while QOS or HT "
442  "is not supported(%d, %d)\n",
443  ieee->current_network. qos_data.active,
444  ieee->pHTInfo->bCurrentHTSupport);
445  return -1;
446  }
447 
449  delba = (struct rtllib_hdr_3addr *)skb->data;
450  dst = (u8 *)(&delba->addr2[0]);
451  delba += sizeof(struct rtllib_hdr_3addr);
452  pDelBaParamSet = (union delba_param_set *)(delba+2);
453  pReasonCode = (u16 *)(delba+4);
454 
455  if (pDelBaParamSet->field.Initiator == 1) {
456  struct rx_ts_record *pRxTs;
457 
458  if (!GetTs(ieee, (struct ts_common_info **)&pRxTs, dst,
459  (u8)pDelBaParamSet->field.TID, RX_DIR, false)) {
460  RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS for RXTS in "
461  "%s().dst: %pM TID:%d\n", __func__, dst,
462  (u8)pDelBaParamSet->field.TID);
463  return -1;
464  }
465 
466  RxTsDeleteBA(ieee, pRxTs);
467  } else {
468  struct tx_ts_record *pTxTs;
469 
470  if (!GetTs(ieee, (struct ts_common_info **)&pTxTs, dst,
471  (u8)pDelBaParamSet->field.TID, TX_DIR, false)) {
472  RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS for TXTS in "
473  "%s()\n", __func__);
474  return -1;
475  }
476 
477  pTxTs->bUsingBa = false;
478  pTxTs->bAddBaReqInProgress = false;
479  pTxTs->bAddBaReqDelayed = false;
480  del_timer_sync(&pTxTs->TsAddBaTimer);
481  TxTsDeleteBA(ieee, pTxTs);
482  }
483  return 0;
484 }
485 
486 void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
487  u8 Policy, u8 bOverwritePending)
488 {
489  struct ba_record *pBA = &pTS->TxPendingBARecord;
490 
491  if (pBA->bValid == true && bOverwritePending == false)
492  return;
493 
494  DeActivateBAEntry(ieee, pBA);
495 
496  pBA->DialogToken++;
497  pBA->BaParamSet.field.AMSDU_Support = 0;
498  pBA->BaParamSet.field.BAPolicy = Policy;
499  pBA->BaParamSet.field.TID =
500  pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;
501  pBA->BaParamSet.field.BufferSize = 32;
502  pBA->BaTimeoutValue = 0;
503  pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096;
504 
505  ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
506 
507  rtllib_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
508 }
509 
510 void TsInitDelBA(struct rtllib_device *ieee,
511  struct ts_common_info *pTsCommonInfo,
512  enum tr_select TxRxSelect)
513 {
514  if (TxRxSelect == TX_DIR) {
515  struct tx_ts_record *pTxTs =
516  (struct tx_ts_record *)pTsCommonInfo;
517 
518  if (TxTsDeleteBA(ieee, pTxTs))
519  rtllib_send_DELBA(ieee, pTsCommonInfo->Addr,
520  (pTxTs->TxAdmittedBARecord.bValid) ?
521  (&pTxTs->TxAdmittedBARecord) :
522  (&pTxTs->TxPendingBARecord),
523  TxRxSelect, DELBA_REASON_END_BA);
524  } else if (TxRxSelect == RX_DIR) {
525  struct rx_ts_record *pRxTs =
526  (struct rx_ts_record *)pTsCommonInfo;
527  if (RxTsDeleteBA(ieee, pRxTs))
528  rtllib_send_DELBA(ieee, pTsCommonInfo->Addr,
529  &pRxTs->RxAdmittedBARecord,
530  TxRxSelect, DELBA_REASON_END_BA);
531  }
532 }
533 
534 void BaSetupTimeOut(unsigned long data)
535 {
536  struct tx_ts_record *pTxTs = (struct tx_ts_record *)data;
537 
538  pTxTs->bAddBaReqInProgress = false;
539  pTxTs->bAddBaReqDelayed = true;
540  pTxTs->TxPendingBARecord.bValid = false;
541 }
542 
543 void TxBaInactTimeout(unsigned long data)
544 {
545  struct tx_ts_record *pTxTs = (struct tx_ts_record *)data;
546  struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device,
547  TxTsRecord[pTxTs->num]);
548  TxTsDeleteBA(ieee, pTxTs);
549  rtllib_send_DELBA(ieee, pTxTs->TsCommonInfo.Addr,
550  &pTxTs->TxAdmittedBARecord, TX_DIR,
552 }
553 
554 void RxBaInactTimeout(unsigned long data)
555 {
556  struct rx_ts_record *pRxTs = (struct rx_ts_record *)data;
557  struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device,
558  RxTsRecord[pRxTs->num]);
559 
560  RxTsDeleteBA(ieee, pRxTs);
561  rtllib_send_DELBA(ieee, pRxTs->TsCommonInfo.Addr,
562  &pRxTs->RxAdmittedBARecord, RX_DIR,
564  return ;
565 }