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 "rtllib.h" 20#include "rtl819x_BA.h" 21 22static 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 30static void DeActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA) 31{ 32 pBA->bValid = false; 33 del_timer_sync(&pBA->Timer); 34} 35 36static 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 54static 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 67void 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} 75static 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); 109 BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); 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 134 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); 135 return skb; 136} 137 138static 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()) 150 RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, 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); 174 Delba->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); 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 188 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); 189 if (net_ratelimit()) 190 RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "<=====%s()\n", 191 __func__); 192 return skb; 193} 194 195static 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 211static 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 224static 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 238int 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 256 RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); 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)) { 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; 277 } 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; 283 } 284 pBA = &pTS->RxAdmittedBARecord; 285 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 " 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 312OnADDBAReq_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 324int 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 416OnADDBARsp_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 425int 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 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); 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 486void 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 510void 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 534void 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 543void 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, 551 DELBA_REASON_TIMEOUT); 552} 553 554void 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, 563 DELBA_REASON_TIMEOUT); 564 return ; 565} 566