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