1 /******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
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
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
13 * The full GNU General Public License is included in this distribution in the
14 * file called LICENSE.
16 * Contact Information:
17 * wlanfae <wlanfae@realtek.com>
18 ******************************************************************************/
20 #include "rtl819x_BA.h"
23 static void ActivateBAEntry(struct rtllib_device
*ieee
, struct ba_record
*pBA
,
28 mod_timer(&pBA
->Timer
, jiffies
+ MSECS(Time
));
31 static void DeActivateBAEntry(struct rtllib_device
*ieee
, struct ba_record
*pBA
)
34 del_timer_sync(&pBA
->Timer
);
37 static u8
TxTsDeleteBA(struct rtllib_device
*ieee
, struct tx_ts_record
*pTxTs
)
39 struct ba_record
*pAdmittedBa
= &pTxTs
->TxAdmittedBARecord
;
40 struct ba_record
*pPendingBa
= &pTxTs
->TxPendingBARecord
;
41 u8 bSendDELBA
= false;
43 if (pPendingBa
->bValid
) {
44 DeActivateBAEntry(ieee
, pPendingBa
);
48 if (pAdmittedBa
->bValid
) {
49 DeActivateBAEntry(ieee
, pAdmittedBa
);
55 static u8
RxTsDeleteBA(struct rtllib_device
*ieee
, struct rx_ts_record
*pRxTs
)
57 struct ba_record
*pBa
= &pRxTs
->RxAdmittedBARecord
;
58 u8 bSendDELBA
= false;
61 DeActivateBAEntry(ieee
, pBa
);
68 void ResetBaEntry(struct ba_record
*pBA
)
71 pBA
->BaParamSet
.shortData
= 0;
72 pBA
->BaTimeoutValue
= 0;
74 pBA
->BaStartSeqCtrl
.ShortData
= 0;
76 static struct sk_buff
*rtllib_ADDBA(struct rtllib_device
*ieee
, u8
*Dst
,
77 struct ba_record
*pBA
,
78 u16 StatusCode
, u8 type
)
80 struct sk_buff
*skb
= NULL
;
81 struct rtllib_hdr_3addr
*BAReq
= NULL
;
84 u16 len
= ieee
->tx_headroom
+ 9;
86 RTLLIB_DEBUG(RTLLIB_DL_TRACE
| RTLLIB_DL_BA
, "========>%s(), frame(%d)"
87 " sentd to: %pM, ieee->dev:%p\n", __func__
,
88 type
, Dst
, ieee
->dev
);
90 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "pBA is NULL\n");
93 skb
= dev_alloc_skb(len
+ sizeof(struct rtllib_hdr_3addr
));
95 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't alloc skb for ADDBA_REQ\n");
99 memset(skb
->data
, 0, sizeof(struct rtllib_hdr_3addr
));
101 skb_reserve(skb
, ieee
->tx_headroom
);
103 BAReq
= (struct rtllib_hdr_3addr
*)skb_put(skb
,
104 sizeof(struct rtllib_hdr_3addr
));
106 memcpy(BAReq
->addr1
, Dst
, ETH_ALEN
);
107 memcpy(BAReq
->addr2
, ieee
->dev
->dev_addr
, ETH_ALEN
);
109 memcpy(BAReq
->addr3
, ieee
->current_network
.bssid
, ETH_ALEN
);
110 BAReq
->frame_ctl
= cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT
);
112 tag
= (u8
*)skb_put(skb
, 9);
115 *tag
++= pBA
->DialogToken
;
117 if (ACT_ADDBARSP
== type
) {
118 RT_TRACE(COMP_DBG
, "====>to send ADDBARSP\n");
119 tmp
= cpu_to_le16(StatusCode
);
120 memcpy(tag
, (u8
*)&tmp
, 2);
123 tmp
= cpu_to_le16(pBA
->BaParamSet
.shortData
);
124 memcpy(tag
, (u8
*)&tmp
, 2);
126 tmp
= cpu_to_le16(pBA
->BaTimeoutValue
);
127 memcpy(tag
, (u8
*)&tmp
, 2);
130 if (ACT_ADDBAREQ
== type
) {
131 memcpy(tag
, (u8
*)&(pBA
->BaStartSeqCtrl
), 2);
135 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA
|RTLLIB_DL_BA
, skb
->data
, skb
->len
);
139 static struct sk_buff
*rtllib_DELBA(struct rtllib_device
*ieee
, u8
*dst
,
140 struct ba_record
*pBA
,
141 enum tr_select TxRxSelect
, u16 ReasonCode
)
143 union delba_param_set DelbaParamSet
;
144 struct sk_buff
*skb
= NULL
;
145 struct rtllib_hdr_3addr
*Delba
= NULL
;
148 u16 len
= 6 + ieee
->tx_headroom
;
151 RTLLIB_DEBUG(RTLLIB_DL_TRACE
| RTLLIB_DL_BA
,
152 "========>%s(), Reason"
153 "Code(%d) sentd to: %pM\n", __func__
,
156 memset(&DelbaParamSet
, 0, 2);
158 DelbaParamSet
.field
.Initiator
= (TxRxSelect
== TX_DIR
) ? 1 : 0;
159 DelbaParamSet
.field
.TID
= pBA
->BaParamSet
.field
.TID
;
161 skb
= dev_alloc_skb(len
+ sizeof(struct rtllib_hdr_3addr
));
163 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't alloc skb for ADDBA_REQ\n");
167 skb_reserve(skb
, ieee
->tx_headroom
);
169 Delba
= (struct rtllib_hdr_3addr
*) skb_put(skb
,
170 sizeof(struct rtllib_hdr_3addr
));
172 memcpy(Delba
->addr1
, dst
, ETH_ALEN
);
173 memcpy(Delba
->addr2
, ieee
->dev
->dev_addr
, ETH_ALEN
);
174 memcpy(Delba
->addr3
, ieee
->current_network
.bssid
, ETH_ALEN
);
175 Delba
->frame_ctl
= cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT
);
177 tag
= (u8
*)skb_put(skb
, 6);
182 tmp
= cpu_to_le16(DelbaParamSet
.shortData
);
183 memcpy(tag
, (u8
*)&tmp
, 2);
185 tmp
= cpu_to_le16(ReasonCode
);
186 memcpy(tag
, (u8
*)&tmp
, 2);
189 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA
|RTLLIB_DL_BA
, skb
->data
, skb
->len
);
191 RTLLIB_DEBUG(RTLLIB_DL_TRACE
| RTLLIB_DL_BA
, "<=====%s()\n",
196 static void rtllib_send_ADDBAReq(struct rtllib_device
*ieee
, u8
*dst
,
197 struct ba_record
*pBA
)
199 struct sk_buff
*skb
= NULL
;
200 skb
= rtllib_ADDBA(ieee
, dst
, pBA
, 0, ACT_ADDBAREQ
);
203 RT_TRACE(COMP_DBG
, "====>to send ADDBAREQ!!!!!\n");
204 softmac_mgmt_xmit(skb
, ieee
);
206 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "alloc skb error in function"
207 " %s()\n", __func__
);
212 static void rtllib_send_ADDBARsp(struct rtllib_device
*ieee
, u8
*dst
,
213 struct ba_record
*pBA
, u16 StatusCode
)
215 struct sk_buff
*skb
= NULL
;
216 skb
= rtllib_ADDBA(ieee
, dst
, pBA
, StatusCode
, ACT_ADDBARSP
);
218 softmac_mgmt_xmit(skb
, ieee
);
220 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "alloc skb error in function"
221 " %s()\n", __func__
);
225 static void rtllib_send_DELBA(struct rtllib_device
*ieee
, u8
*dst
,
226 struct ba_record
*pBA
, enum tr_select TxRxSelect
,
229 struct sk_buff
*skb
= NULL
;
230 skb
= rtllib_DELBA(ieee
, dst
, pBA
, TxRxSelect
, ReasonCode
);
232 softmac_mgmt_xmit(skb
, ieee
);
234 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "alloc skb error in func"
235 "tion %s()\n", __func__
);
239 int rtllib_rx_ADDBAReq(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
241 struct rtllib_hdr_3addr
*req
= NULL
;
243 u8
*dst
= NULL
, *pDialogToken
= NULL
, *tag
= NULL
;
244 struct ba_record
*pBA
= NULL
;
245 union ba_param_set
*pBaParamSet
= NULL
;
246 u16
*pBaTimeoutVal
= NULL
;
247 union sequence_control
*pBaStartSeqCtrl
= NULL
;
248 struct rx_ts_record
*pTS
= NULL
;
250 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 9) {
251 RTLLIB_DEBUG(RTLLIB_DL_ERR
, " Invalid skb len in BAREQ(%d / "
252 "%d)\n", (int)skb
->len
,
253 (int)(sizeof(struct rtllib_hdr_3addr
) + 9));
257 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA
|RTLLIB_DL_BA
, skb
->data
, skb
->len
);
259 req
= (struct rtllib_hdr_3addr
*) skb
->data
;
261 dst
= (u8
*)(&req
->addr2
[0]);
262 tag
+= sizeof(struct rtllib_hdr_3addr
);
263 pDialogToken
= tag
+ 2;
264 pBaParamSet
= (union ba_param_set
*)(tag
+ 3);
265 pBaTimeoutVal
= (u16
*)(tag
+ 5);
266 pBaStartSeqCtrl
= (union sequence_control
*)(req
+ 7);
268 RT_TRACE(COMP_DBG
, "====>rx ADDBAREQ from : %pM\n", dst
);
269 if (ieee
->current_network
.qos_data
.active
== 0 ||
270 (ieee
->pHTInfo
->bCurrentHTSupport
== false) ||
271 (ieee
->pHTInfo
->IOTAction
& HT_IOT_ACT_REJECT_ADDBA_REQ
)) {
272 rc
= ADDBA_STATUS_REFUSED
;
273 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "Failed to reply on ADDBA_REQ as "
274 "some capability is not ready(%d, %d)\n",
275 ieee
->current_network
.qos_data
.active
,
276 ieee
->pHTInfo
->bCurrentHTSupport
);
277 goto OnADDBAReq_Fail
;
279 if (!GetTs(ieee
, (struct ts_common_info
**)(&pTS
), dst
,
280 (u8
)(pBaParamSet
->field
.TID
), RX_DIR
, true)) {
281 rc
= ADDBA_STATUS_REFUSED
;
282 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't get TS in %s()\n", __func__
);
283 goto OnADDBAReq_Fail
;
285 pBA
= &pTS
->RxAdmittedBARecord
;
287 if (pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
) {
288 rc
= ADDBA_STATUS_INVALID_PARAM
;
289 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "BA Policy is not correct in "
291 goto OnADDBAReq_Fail
;
294 rtllib_FlushRxTsPendingPkts(ieee
, pTS
);
296 DeActivateBAEntry(ieee
, pBA
);
297 pBA
->DialogToken
= *pDialogToken
;
298 pBA
->BaParamSet
= *pBaParamSet
;
299 pBA
->BaTimeoutValue
= *pBaTimeoutVal
;
300 pBA
->BaStartSeqCtrl
= *pBaStartSeqCtrl
;
302 if (ieee
->GetHalfNmodeSupportByAPsHandler(ieee
->dev
) ||
303 (ieee
->pHTInfo
->IOTAction
& HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT
))
304 pBA
->BaParamSet
.field
.BufferSize
= 1;
306 pBA
->BaParamSet
.field
.BufferSize
= 32;
308 ActivateBAEntry(ieee
, pBA
, 0);
309 rtllib_send_ADDBARsp(ieee
, dst
, pBA
, ADDBA_STATUS_SUCCESS
);
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
);
325 int rtllib_rx_ADDBARsp(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
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
;
335 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 9) {
336 RTLLIB_DEBUG(RTLLIB_DL_ERR
, " Invalid skb len in BARSP(%d / "
337 "%d)\n", (int)skb
->len
,
338 (int)(sizeof(struct rtllib_hdr_3addr
) + 9));
341 rsp
= (struct rtllib_hdr_3addr
*)skb
->data
;
343 dst
= (u8
*)(&rsp
->addr2
[0]);
344 tag
+= sizeof(struct rtllib_hdr_3addr
);
345 pDialogToken
= tag
+ 2;
346 pStatusCode
= (u16
*)(tag
+ 3);
347 pBaParamSet
= (union ba_param_set
*)(tag
+ 5);
348 pBaTimeoutVal
= (u16
*)(tag
+ 7);
350 RT_TRACE(COMP_DBG
, "====>rx ADDBARSP from : %pM\n", dst
);
351 if (ieee
->current_network
.qos_data
.active
== 0 ||
352 ieee
->pHTInfo
->bCurrentHTSupport
== false ||
353 ieee
->pHTInfo
->bCurrentAMPDUEnable
== false) {
354 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "reject to ADDBA_RSP as some capab"
355 "ility is not ready(%d, %d, %d)\n",
356 ieee
->current_network
.qos_data
.active
,
357 ieee
->pHTInfo
->bCurrentHTSupport
,
358 ieee
->pHTInfo
->bCurrentAMPDUEnable
);
359 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
360 goto OnADDBARsp_Reject
;
364 if (!GetTs(ieee
, (struct ts_common_info
**)(&pTS
), dst
,
365 (u8
)(pBaParamSet
->field
.TID
), TX_DIR
, false)) {
366 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't get TS in %s()\n", __func__
);
367 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
368 goto OnADDBARsp_Reject
;
371 pTS
->bAddBaReqInProgress
= false;
372 pPendingBA
= &pTS
->TxPendingBARecord
;
373 pAdmittedBA
= &pTS
->TxAdmittedBARecord
;
376 if ((pAdmittedBA
->bValid
== true)) {
377 RTLLIB_DEBUG(RTLLIB_DL_BA
, "OnADDBARsp(): Recv ADDBA Rsp."
378 " Drop because already admit it!\n");
380 } else if ((pPendingBA
->bValid
== false) ||
381 (*pDialogToken
!= pPendingBA
->DialogToken
)) {
382 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "OnADDBARsp(): Recv ADDBA Rsp. "
383 "BA invalid, DELBA!\n");
384 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
385 goto OnADDBARsp_Reject
;
387 RTLLIB_DEBUG(RTLLIB_DL_BA
, "OnADDBARsp(): Recv ADDBA Rsp. BA "
388 "is admitted! Status code:%X\n", *pStatusCode
);
389 DeActivateBAEntry(ieee
, pPendingBA
);
393 if (*pStatusCode
== ADDBA_STATUS_SUCCESS
) {
394 if (pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
) {
395 pTS
->bAddBaReqDelayed
= true;
396 DeActivateBAEntry(ieee
, pAdmittedBA
);
397 ReasonCode
= DELBA_REASON_END_BA
;
398 goto OnADDBARsp_Reject
;
402 pAdmittedBA
->DialogToken
= *pDialogToken
;
403 pAdmittedBA
->BaTimeoutValue
= *pBaTimeoutVal
;
404 pAdmittedBA
->BaStartSeqCtrl
= pPendingBA
->BaStartSeqCtrl
;
405 pAdmittedBA
->BaParamSet
= *pBaParamSet
;
406 DeActivateBAEntry(ieee
, pAdmittedBA
);
407 ActivateBAEntry(ieee
, pAdmittedBA
, *pBaTimeoutVal
);
409 pTS
->bAddBaReqDelayed
= true;
410 pTS
->bDisable_AddBa
= true;
411 ReasonCode
= DELBA_REASON_END_BA
;
412 goto OnADDBARsp_Reject
;
420 BA
.BaParamSet
= *pBaParamSet
;
421 rtllib_send_DELBA(ieee
, dst
, &BA
, TX_DIR
, ReasonCode
);
426 int rtllib_rx_DELBA(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
428 struct rtllib_hdr_3addr
*delba
= NULL
;
429 union delba_param_set
*pDelBaParamSet
= NULL
;
430 u16
*pReasonCode
= NULL
;
433 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 6) {
434 RTLLIB_DEBUG(RTLLIB_DL_ERR
, " Invalid skb len in DELBA(%d /"
435 " %d)\n", (int)skb
->len
,
436 (int)(sizeof(struct rtllib_hdr_3addr
) + 6));
440 if (ieee
->current_network
.qos_data
.active
== 0 ||
441 ieee
->pHTInfo
->bCurrentHTSupport
== false) {
442 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "received DELBA while QOS or HT "
443 "is not supported(%d, %d)\n",
444 ieee
->current_network
. qos_data
.active
,
445 ieee
->pHTInfo
->bCurrentHTSupport
);
449 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA
|RTLLIB_DL_BA
, skb
->data
, skb
->len
);
450 delba
= (struct rtllib_hdr_3addr
*)skb
->data
;
451 dst
= (u8
*)(&delba
->addr2
[0]);
452 delba
+= sizeof(struct rtllib_hdr_3addr
);
453 pDelBaParamSet
= (union delba_param_set
*)(delba
+2);
454 pReasonCode
= (u16
*)(delba
+4);
456 if (pDelBaParamSet
->field
.Initiator
== 1) {
457 struct rx_ts_record
*pRxTs
;
459 if (!GetTs(ieee
, (struct ts_common_info
**)&pRxTs
, dst
,
460 (u8
)pDelBaParamSet
->field
.TID
, RX_DIR
, false)) {
461 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't get TS for RXTS in "
462 "%s().dst: %pM TID:%d\n", __func__
, dst
,
463 (u8
)pDelBaParamSet
->field
.TID
);
467 RxTsDeleteBA(ieee
, pRxTs
);
469 struct tx_ts_record
*pTxTs
;
471 if (!GetTs(ieee
, (struct ts_common_info
**)&pTxTs
, dst
,
472 (u8
)pDelBaParamSet
->field
.TID
, TX_DIR
, false)) {
473 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't get TS for TXTS in "
478 pTxTs
->bUsingBa
= false;
479 pTxTs
->bAddBaReqInProgress
= false;
480 pTxTs
->bAddBaReqDelayed
= false;
481 del_timer_sync(&pTxTs
->TsAddBaTimer
);
482 TxTsDeleteBA(ieee
, pTxTs
);
487 void TsInitAddBA(struct rtllib_device
*ieee
, struct tx_ts_record
*pTS
,
488 u8 Policy
, u8 bOverwritePending
)
490 struct ba_record
*pBA
= &pTS
->TxPendingBARecord
;
492 if (pBA
->bValid
== true && bOverwritePending
== false)
495 DeActivateBAEntry(ieee
, pBA
);
498 pBA
->BaParamSet
.field
.AMSDU_Support
= 0;
499 pBA
->BaParamSet
.field
.BAPolicy
= Policy
;
500 pBA
->BaParamSet
.field
.TID
=
501 pTS
->TsCommonInfo
.TSpec
.f
.TSInfo
.field
.ucTSID
;
502 pBA
->BaParamSet
.field
.BufferSize
= 32;
503 pBA
->BaTimeoutValue
= 0;
504 pBA
->BaStartSeqCtrl
.field
.SeqNum
= (pTS
->TxCurSeq
+ 3) % 4096;
506 ActivateBAEntry(ieee
, pBA
, BA_SETUP_TIMEOUT
);
508 rtllib_send_ADDBAReq(ieee
, pTS
->TsCommonInfo
.Addr
, pBA
);
511 void TsInitDelBA(struct rtllib_device
*ieee
,
512 struct ts_common_info
*pTsCommonInfo
,
513 enum tr_select TxRxSelect
)
515 if (TxRxSelect
== TX_DIR
) {
516 struct tx_ts_record
*pTxTs
=
517 (struct tx_ts_record
*)pTsCommonInfo
;
519 if (TxTsDeleteBA(ieee
, pTxTs
))
520 rtllib_send_DELBA(ieee
, pTsCommonInfo
->Addr
,
521 (pTxTs
->TxAdmittedBARecord
.bValid
) ?
522 (&pTxTs
->TxAdmittedBARecord
) :
523 (&pTxTs
->TxPendingBARecord
),
524 TxRxSelect
, DELBA_REASON_END_BA
);
525 } else if (TxRxSelect
== RX_DIR
) {
526 struct rx_ts_record
*pRxTs
=
527 (struct rx_ts_record
*)pTsCommonInfo
;
528 if (RxTsDeleteBA(ieee
, pRxTs
))
529 rtllib_send_DELBA(ieee
, pTsCommonInfo
->Addr
,
530 &pRxTs
->RxAdmittedBARecord
,
531 TxRxSelect
, DELBA_REASON_END_BA
);
535 void BaSetupTimeOut(unsigned long data
)
537 struct tx_ts_record
*pTxTs
= (struct tx_ts_record
*)data
;
539 pTxTs
->bAddBaReqInProgress
= false;
540 pTxTs
->bAddBaReqDelayed
= true;
541 pTxTs
->TxPendingBARecord
.bValid
= false;
544 void TxBaInactTimeout(unsigned long data
)
546 struct tx_ts_record
*pTxTs
= (struct tx_ts_record
*)data
;
547 struct rtllib_device
*ieee
= container_of(pTxTs
, struct rtllib_device
,
548 TxTsRecord
[pTxTs
->num
]);
549 TxTsDeleteBA(ieee
, pTxTs
);
550 rtllib_send_DELBA(ieee
, pTxTs
->TsCommonInfo
.Addr
,
551 &pTxTs
->TxAdmittedBARecord
, TX_DIR
,
552 DELBA_REASON_TIMEOUT
);
555 void RxBaInactTimeout(unsigned long data
)
557 struct rx_ts_record
*pRxTs
= (struct rx_ts_record
*)data
;
558 struct rtllib_device
*ieee
= container_of(pRxTs
, struct rtllib_device
,
559 RxTsRecord
[pRxTs
->num
]);
561 RxTsDeleteBA(ieee
, pRxTs
);
562 rtllib_send_DELBA(ieee
, pRxTs
->TsCommonInfo
.Addr
,
563 &pRxTs
->RxAdmittedBARecord
, RX_DIR
,
564 DELBA_REASON_TIMEOUT
);