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