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"
22 static void ActivateBAEntry(struct rtllib_device
*ieee
, struct ba_record
*pBA
,
27 mod_timer(&pBA
->Timer
, jiffies
+ MSECS(Time
));
30 static void DeActivateBAEntry(struct rtllib_device
*ieee
, struct ba_record
*pBA
)
33 del_timer_sync(&pBA
->Timer
);
36 static u8
TxTsDeleteBA(struct rtllib_device
*ieee
, struct tx_ts_record
*pTxTs
)
38 struct ba_record
*pAdmittedBa
= &pTxTs
->TxAdmittedBARecord
;
39 struct ba_record
*pPendingBa
= &pTxTs
->TxPendingBARecord
;
40 u8 bSendDELBA
= false;
42 if (pPendingBa
->bValid
) {
43 DeActivateBAEntry(ieee
, pPendingBa
);
47 if (pAdmittedBa
->bValid
) {
48 DeActivateBAEntry(ieee
, pAdmittedBa
);
54 static u8
RxTsDeleteBA(struct rtllib_device
*ieee
, struct rx_ts_record
*pRxTs
)
56 struct ba_record
*pBa
= &pRxTs
->RxAdmittedBARecord
;
57 u8 bSendDELBA
= false;
60 DeActivateBAEntry(ieee
, pBa
);
67 void ResetBaEntry(struct ba_record
*pBA
)
70 pBA
->BaParamSet
.shortData
= 0;
71 pBA
->BaTimeoutValue
= 0;
73 pBA
->BaStartSeqCtrl
.ShortData
= 0;
75 static struct sk_buff
*rtllib_ADDBA(struct rtllib_device
*ieee
, u8
*Dst
,
76 struct ba_record
*pBA
,
77 u16 StatusCode
, u8 type
)
79 struct sk_buff
*skb
= NULL
;
80 struct rtllib_hdr_3addr
*BAReq
= NULL
;
83 u16 len
= ieee
->tx_headroom
+ 9;
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
);
89 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "pBA is NULL\n");
92 skb
= dev_alloc_skb(len
+ sizeof(struct rtllib_hdr_3addr
));
94 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't alloc skb for ADDBA_REQ\n");
98 memset(skb
->data
, 0, sizeof(struct rtllib_hdr_3addr
));
100 skb_reserve(skb
, ieee
->tx_headroom
);
102 BAReq
= (struct rtllib_hdr_3addr
*)skb_put(skb
,
103 sizeof(struct rtllib_hdr_3addr
));
105 memcpy(BAReq
->addr1
, Dst
, ETH_ALEN
);
106 memcpy(BAReq
->addr2
, ieee
->dev
->dev_addr
, ETH_ALEN
);
108 memcpy(BAReq
->addr3
, ieee
->current_network
.bssid
, ETH_ALEN
);
109 BAReq
->frame_ctl
= cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT
);
111 tag
= (u8
*)skb_put(skb
, 9);
114 *tag
++= pBA
->DialogToken
;
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);
122 tmp
= cpu_to_le16(pBA
->BaParamSet
.shortData
);
123 memcpy(tag
, (u8
*)&tmp
, 2);
125 tmp
= cpu_to_le16(pBA
->BaTimeoutValue
);
126 memcpy(tag
, (u8
*)&tmp
, 2);
129 if (ACT_ADDBAREQ
== type
) {
130 memcpy(tag
, (u8
*)&(pBA
->BaStartSeqCtrl
), 2);
134 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA
|RTLLIB_DL_BA
, skb
->data
, skb
->len
);
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
)
142 union delba_param_set DelbaParamSet
;
143 struct sk_buff
*skb
= NULL
;
144 struct rtllib_hdr_3addr
*Delba
= NULL
;
147 u16 len
= 6 + ieee
->tx_headroom
;
150 RTLLIB_DEBUG(RTLLIB_DL_TRACE
| RTLLIB_DL_BA
,
151 "========>%s(), Reason"
152 "Code(%d) sentd to: %pM\n", __func__
,
155 memset(&DelbaParamSet
, 0, 2);
157 DelbaParamSet
.field
.Initiator
= (TxRxSelect
== TX_DIR
) ? 1 : 0;
158 DelbaParamSet
.field
.TID
= pBA
->BaParamSet
.field
.TID
;
160 skb
= dev_alloc_skb(len
+ sizeof(struct rtllib_hdr_3addr
));
162 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't alloc skb for ADDBA_REQ\n");
166 skb_reserve(skb
, ieee
->tx_headroom
);
168 Delba
= (struct rtllib_hdr_3addr
*) skb_put(skb
,
169 sizeof(struct rtllib_hdr_3addr
));
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
);
174 Delba
->frame_ctl
= cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT
);
176 tag
= (u8
*)skb_put(skb
, 6);
181 tmp
= cpu_to_le16(DelbaParamSet
.shortData
);
182 memcpy(tag
, (u8
*)&tmp
, 2);
184 tmp
= cpu_to_le16(ReasonCode
);
185 memcpy(tag
, (u8
*)&tmp
, 2);
188 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA
|RTLLIB_DL_BA
, skb
->data
, skb
->len
);
190 RTLLIB_DEBUG(RTLLIB_DL_TRACE
| RTLLIB_DL_BA
, "<=====%s()\n",
195 static void rtllib_send_ADDBAReq(struct rtllib_device
*ieee
, u8
*dst
,
196 struct ba_record
*pBA
)
198 struct sk_buff
*skb
= NULL
;
199 skb
= rtllib_ADDBA(ieee
, dst
, pBA
, 0, ACT_ADDBAREQ
);
202 RT_TRACE(COMP_DBG
, "====>to send ADDBAREQ!!!!!\n");
203 softmac_mgmt_xmit(skb
, ieee
);
205 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "alloc skb error in function"
206 " %s()\n", __func__
);
211 static void rtllib_send_ADDBARsp(struct rtllib_device
*ieee
, u8
*dst
,
212 struct ba_record
*pBA
, u16 StatusCode
)
214 struct sk_buff
*skb
= NULL
;
215 skb
= rtllib_ADDBA(ieee
, dst
, pBA
, StatusCode
, ACT_ADDBARSP
);
217 softmac_mgmt_xmit(skb
, ieee
);
219 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "alloc skb error in function"
220 " %s()\n", __func__
);
224 static void rtllib_send_DELBA(struct rtllib_device
*ieee
, u8
*dst
,
225 struct ba_record
*pBA
, enum tr_select TxRxSelect
,
228 struct sk_buff
*skb
= NULL
;
229 skb
= rtllib_DELBA(ieee
, dst
, pBA
, TxRxSelect
, ReasonCode
);
231 softmac_mgmt_xmit(skb
, ieee
);
233 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "alloc skb error in func"
234 "tion %s()\n", __func__
);
238 int rtllib_rx_ADDBAReq(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
240 struct rtllib_hdr_3addr
*req
= NULL
;
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
;
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));
256 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA
|RTLLIB_DL_BA
, skb
->data
, skb
->len
);
258 req
= (struct rtllib_hdr_3addr
*) skb
->data
;
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);
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
)) {
271 rc
= ADDBA_STATUS_REFUSED
;
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
;
278 if (!GetTs(ieee
, (struct ts_common_info
**)(&pTS
), dst
,
279 (u8
)(pBaParamSet
->field
.TID
), RX_DIR
, true)) {
280 rc
= ADDBA_STATUS_REFUSED
;
281 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "can't get TS in %s()\n", __func__
);
282 goto OnADDBAReq_Fail
;
284 pBA
= &pTS
->RxAdmittedBARecord
;
286 if (pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
) {
287 rc
= ADDBA_STATUS_INVALID_PARAM
;
288 RTLLIB_DEBUG(RTLLIB_DL_ERR
, "BA Policy is not correct in "
290 goto OnADDBAReq_Fail
;
293 rtllib_FlushRxTsPendingPkts(ieee
, pTS
);
295 DeActivateBAEntry(ieee
, pBA
);
296 pBA
->DialogToken
= *pDialogToken
;
297 pBA
->BaParamSet
= *pBaParamSet
;
298 pBA
->BaTimeoutValue
= *pBaTimeoutVal
;
299 pBA
->BaStartSeqCtrl
= *pBaStartSeqCtrl
;
301 if (ieee
->GetHalfNmodeSupportByAPsHandler(ieee
->dev
) ||
302 (ieee
->pHTInfo
->IOTAction
& HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT
))
303 pBA
->BaParamSet
.field
.BufferSize
= 1;
305 pBA
->BaParamSet
.field
.BufferSize
= 32;
307 ActivateBAEntry(ieee
, pBA
, 0);
308 rtllib_send_ADDBARsp(ieee
, dst
, pBA
, ADDBA_STATUS_SUCCESS
);
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
);
324 int rtllib_rx_ADDBARsp(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
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
;
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));
340 rsp
= (struct rtllib_hdr_3addr
*)skb
->data
;
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);
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
;
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
;
370 pTS
->bAddBaReqInProgress
= false;
371 pPendingBA
= &pTS
->TxPendingBARecord
;
372 pAdmittedBA
= &pTS
->TxAdmittedBARecord
;
375 if ((pAdmittedBA
->bValid
== true)) {
376 RTLLIB_DEBUG(RTLLIB_DL_BA
, "OnADDBARsp(): Recv ADDBA Rsp."
377 " Drop because already admit it!\n");
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
;
386 RTLLIB_DEBUG(RTLLIB_DL_BA
, "OnADDBARsp(): Recv ADDBA Rsp. BA "
387 "is admitted! Status code:%X\n", *pStatusCode
);
388 DeActivateBAEntry(ieee
, pPendingBA
);
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
;
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
);
408 pTS
->bAddBaReqDelayed
= true;
409 pTS
->bDisable_AddBa
= true;
410 ReasonCode
= DELBA_REASON_END_BA
;
411 goto OnADDBARsp_Reject
;
419 BA
.BaParamSet
= *pBaParamSet
;
420 rtllib_send_DELBA(ieee
, dst
, &BA
, TX_DIR
, ReasonCode
);
425 int rtllib_rx_DELBA(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
427 struct rtllib_hdr_3addr
*delba
= NULL
;
428 union delba_param_set
*pDelBaParamSet
= NULL
;
429 u16
*pReasonCode
= NULL
;
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));
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
);
448 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA
|RTLLIB_DL_BA
, skb
->data
, skb
->len
);
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);
455 if (pDelBaParamSet
->field
.Initiator
== 1) {
456 struct rx_ts_record
*pRxTs
;
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
);
466 RxTsDeleteBA(ieee
, pRxTs
);
468 struct tx_ts_record
*pTxTs
;
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 "
477 pTxTs
->bUsingBa
= false;
478 pTxTs
->bAddBaReqInProgress
= false;
479 pTxTs
->bAddBaReqDelayed
= false;
480 del_timer_sync(&pTxTs
->TsAddBaTimer
);
481 TxTsDeleteBA(ieee
, pTxTs
);
486 void TsInitAddBA(struct rtllib_device
*ieee
, struct tx_ts_record
*pTS
,
487 u8 Policy
, u8 bOverwritePending
)
489 struct ba_record
*pBA
= &pTS
->TxPendingBARecord
;
491 if (pBA
->bValid
== true && bOverwritePending
== false)
494 DeActivateBAEntry(ieee
, pBA
);
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;
505 ActivateBAEntry(ieee
, pBA
, BA_SETUP_TIMEOUT
);
507 rtllib_send_ADDBAReq(ieee
, pTS
->TsCommonInfo
.Addr
, pBA
);
510 void TsInitDelBA(struct rtllib_device
*ieee
,
511 struct ts_common_info
*pTsCommonInfo
,
512 enum tr_select TxRxSelect
)
514 if (TxRxSelect
== TX_DIR
) {
515 struct tx_ts_record
*pTxTs
=
516 (struct tx_ts_record
*)pTsCommonInfo
;
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
);
534 void BaSetupTimeOut(unsigned long data
)
536 struct tx_ts_record
*pTxTs
= (struct tx_ts_record
*)data
;
538 pTxTs
->bAddBaReqInProgress
= false;
539 pTxTs
->bAddBaReqDelayed
= true;
540 pTxTs
->TxPendingBARecord
.bValid
= false;
543 void TxBaInactTimeout(unsigned long data
)
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
,
551 DELBA_REASON_TIMEOUT
);
554 void RxBaInactTimeout(unsigned long data
)
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
]);
560 RxTsDeleteBA(ieee
, pRxTs
);
561 rtllib_send_DELBA(ieee
, pRxTs
->TsCommonInfo
.Addr
,
562 &pRxTs
->RxAdmittedBARecord
, RX_DIR
,
563 DELBA_REASON_TIMEOUT
);