1/* 2 ************************************************************************* 3 * Ralink Tech Inc. 4 * 5F., No.36, Taiyuan St., Jhubei City, 5 * Hsinchu County 302, 6 * Taiwan, R.O.C. 7 * 8 * (c) Copyright 2002-2007, Ralink Technology, Inc. 9 * 10 * This program is free software; you can redistribute it and/or modify * 11 * it under the terms of the GNU General Public License as published by * 12 * the Free Software Foundation; either version 2 of the License, or * 13 * (at your option) any later version. * 14 * * 15 * This program is distributed in the hope that it will be useful, * 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 * GNU General Public License for more details. * 19 * * 20 * You should have received a copy of the GNU General Public License * 21 * along with this program; if not, write to the * 22 * Free Software Foundation, Inc., * 23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 24 * * 25 ************************************************************************* 26 */ 27 28#include "../rt_config.h" 29 30#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 // inital sequence number of BA session */ 31 32#define ORI_SESSION_MAX_RETRY 8 33#define ORI_BA_SESSION_TIMEOUT (2000) /* ms */ 34#define REC_BA_SESSION_IDLE_TIMEOUT (1000) /* ms */ 35 36#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */ 37#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms */ 38 39#define RESET_RCV_SEQ (0xFFFF) 40 41static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd, 42 struct reordering_mpdu *mpdu_blk); 43 44struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx); 45 46struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx); 47 48void BAOriSessionSetupTimeout(void *SystemSpecific1, 49 void *FunctionContext, 50 void *SystemSpecific2, 51 void *SystemSpecific3); 52 53void BARecSessionIdleTimeout(void *SystemSpecific1, 54 void *FunctionContext, 55 void *SystemSpecific2, 56 void *SystemSpecific3); 57 58BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout); 59BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); 60 61#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \ 62 Announce_Reordering_Packet(_pAd, _mpdu_blk); 63 64void BA_MaxWinSizeReasign(struct rt_rtmp_adapter *pAd, 65 struct rt_mac_table_entry *pEntryPeer, u8 * pWinSize) 66{ 67 u8 MaxSize; 68 69 if (pAd->MACVersion >= RALINK_2883_VERSION) /* 3*3 */ 70 { 71 if (pAd->MACVersion >= RALINK_3070_VERSION) { 72 if (pEntryPeer->WepStatus != 73 Ndis802_11EncryptionDisabled) 74 MaxSize = 7; /* for non-open mode */ 75 else 76 MaxSize = 13; 77 } else 78 MaxSize = 31; 79 } else if (pAd->MACVersion >= RALINK_2880E_VERSION) /* 2880 e */ 80 { 81 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled) 82 MaxSize = 7; /* for non-open mode */ 83 else 84 MaxSize = 13; 85 } else 86 MaxSize = 7; 87 88 DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n", 89 *pWinSize, MaxSize)); 90 91 if ((*pWinSize) > MaxSize) { 92 DBGPRINT(RT_DEBUG_TRACE, 93 ("ba> reassign max win size from %d to %d\n", 94 *pWinSize, MaxSize)); 95 96 *pWinSize = MaxSize; 97 } 98} 99 100void Announce_Reordering_Packet(struct rt_rtmp_adapter *pAd, 101 IN struct reordering_mpdu *mpdu) 102{ 103 void *pPacket; 104 105 pPacket = mpdu->pPacket; 106 107 if (mpdu->bAMSDU) { 108 ASSERT(0); 109 BA_Reorder_AMSDU_Annnounce(pAd, pPacket); 110 } else { 111 /* */ 112 /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ 113 /* */ 114 115 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, 116 RTMP_GET_PACKET_IF(pPacket)); 117 } 118} 119 120/* 121 * Insert a reordering mpdu into sorted linked list by sequence no. 122 */ 123BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, 124 struct reordering_mpdu *mpdu) 125{ 126 127 struct reordering_mpdu **ppScan = &list->next; 128 129 while (*ppScan != NULL) { 130 if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) { 131 ppScan = &(*ppScan)->next; 132 } else if ((*ppScan)->Sequence == mpdu->Sequence) { 133 /* give up this duplicated frame */ 134 return (FALSE); 135 } else { 136 /* find position */ 137 break; 138 } 139 } 140 141 mpdu->next = *ppScan; 142 *ppScan = mpdu; 143 list->qlen++; 144 return TRUE; 145} 146 147/* 148 * caller lock critical section if necessary 149 */ 150static inline void ba_enqueue(struct reordering_list *list, 151 struct reordering_mpdu *mpdu_blk) 152{ 153 list->qlen++; 154 mpdu_blk->next = list->next; 155 list->next = mpdu_blk; 156} 157 158/* 159 * caller lock critical section if necessary 160 */ 161static inline struct reordering_mpdu *ba_dequeue(struct reordering_list *list) 162{ 163 struct reordering_mpdu *mpdu_blk = NULL; 164 165 ASSERT(list); 166 167 if (list->qlen) { 168 list->qlen--; 169 mpdu_blk = list->next; 170 if (mpdu_blk) { 171 list->next = mpdu_blk->next; 172 mpdu_blk->next = NULL; 173 } 174 } 175 return mpdu_blk; 176} 177 178static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct 179 reordering_list 180 *list) 181{ 182 return (ba_dequeue(list)); 183} 184 185static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct 186 reordering_list 187 *list) 188{ 189 ASSERT(list); 190 191 return (list->next); 192} 193 194/* 195 * free all resource for reordering mechanism 196 */ 197void ba_reordering_resource_release(struct rt_rtmp_adapter *pAd) 198{ 199 struct rt_ba_table *Tab; 200 struct rt_ba_rec_entry *pBAEntry; 201 struct reordering_mpdu *mpdu_blk; 202 int i; 203 204 Tab = &pAd->BATable; 205 206 /* I. release all pending reordering packet */ 207 NdisAcquireSpinLock(&pAd->BATabLock); 208 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) { 209 pBAEntry = &Tab->BARecEntry[i]; 210 if (pBAEntry->REC_BA_Status != Recipient_NONE) { 211 while ((mpdu_blk = 212 ba_reordering_mpdu_dequeue(&pBAEntry->list))) { 213 ASSERT(mpdu_blk->pPacket); 214 RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, 215 NDIS_STATUS_FAILURE); 216 ba_mpdu_blk_free(pAd, mpdu_blk); 217 } 218 } 219 } 220 NdisReleaseSpinLock(&pAd->BATabLock); 221 222 ASSERT(pBAEntry->list.qlen == 0); 223 /* II. free memory of reordering mpdu table */ 224 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); 225 os_free_mem(pAd, pAd->mpdu_blk_pool.mem); 226 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); 227} 228 229/* 230 * Allocate all resource for reordering mechanism 231 */ 232BOOLEAN ba_reordering_resource_init(struct rt_rtmp_adapter *pAd, int num) 233{ 234 int i; 235 u8 *mem; 236 struct reordering_mpdu *mpdu_blk; 237 struct reordering_list *freelist; 238 239 /* allocate spinlock */ 240 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock); 241 242 /* initialize freelist */ 243 freelist = &pAd->mpdu_blk_pool.freelist; 244 freelist->next = NULL; 245 freelist->qlen = 0; 246 247 DBGPRINT(RT_DEBUG_TRACE, 248 ("Allocate %d memory for BA reordering\n", 249 (u32)(num * sizeof(struct reordering_mpdu)))); 250 251 /* allocate number of mpdu_blk memory */ 252 os_alloc_mem(pAd, (u8 **) & mem, 253 (num * sizeof(struct reordering_mpdu))); 254 255 pAd->mpdu_blk_pool.mem = mem; 256 257 if (mem == NULL) { 258 DBGPRINT(RT_DEBUG_ERROR, 259 ("Can't Allocate Memory for BA Reordering\n")); 260 return (FALSE); 261 } 262 263 /* build mpdu_blk free list */ 264 for (i = 0; i < num; i++) { 265 /* get mpdu_blk */ 266 mpdu_blk = (struct reordering_mpdu *)mem; 267 /* initial mpdu_blk */ 268 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); 269 /* next mpdu_blk */ 270 mem += sizeof(struct reordering_mpdu); 271 /* insert mpdu_blk into freelist */ 272 ba_enqueue(freelist, mpdu_blk); 273 } 274 275 return (TRUE); 276} 277 278/*static int blk_count=0; // sample take off, no use */ 279 280static struct reordering_mpdu *ba_mpdu_blk_alloc(struct rt_rtmp_adapter *pAd) 281{ 282 struct reordering_mpdu *mpdu_blk; 283 284 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); 285 mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist); 286 if (mpdu_blk) { 287/* blk_count++; */ 288 /* reset mpdu_blk */ 289 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); 290 } 291 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); 292 return mpdu_blk; 293} 294 295static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd, 296 struct reordering_mpdu *mpdu_blk) 297{ 298 ASSERT(mpdu_blk); 299 300 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); 301/* blk_count--; */ 302 ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk); 303 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); 304} 305 306static u16 ba_indicate_reordering_mpdus_in_order(struct rt_rtmp_adapter *pAd, 307 struct rt_ba_rec_entry *pBAEntry, 308 u16 StartSeq) 309{ 310 struct reordering_mpdu *mpdu_blk; 311 u16 LastIndSeq = RESET_RCV_SEQ; 312 313 NdisAcquireSpinLock(&pBAEntry->RxReRingLock); 314 315 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { 316 /* find in-order frame */ 317 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) { 318 break; 319 } 320 /* dequeue in-order frame from reodering list */ 321 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); 322 /* pass this frame up */ 323 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); 324 /* move to next sequence */ 325 StartSeq = mpdu_blk->Sequence; 326 LastIndSeq = StartSeq; 327 /* free mpdu_blk */ 328 ba_mpdu_blk_free(pAd, mpdu_blk); 329 } 330 331 NdisReleaseSpinLock(&pBAEntry->RxReRingLock); 332 333 /* update last indicated sequence */ 334 return LastIndSeq; 335} 336 337static void ba_indicate_reordering_mpdus_le_seq(struct rt_rtmp_adapter *pAd, 338 struct rt_ba_rec_entry *pBAEntry, 339 u16 Sequence) 340{ 341 struct reordering_mpdu *mpdu_blk; 342 343 NdisAcquireSpinLock(&pBAEntry->RxReRingLock); 344 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { 345 /* find in-order frame */ 346 if ((mpdu_blk->Sequence == Sequence) 347 || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) { 348 /* dequeue in-order frame from reodering list */ 349 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); 350 /* pass this frame up */ 351 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); 352 /* free mpdu_blk */ 353 ba_mpdu_blk_free(pAd, mpdu_blk); 354 } else { 355 break; 356 } 357 } 358 NdisReleaseSpinLock(&pBAEntry->RxReRingLock); 359} 360 361static void ba_refresh_reordering_mpdus(struct rt_rtmp_adapter *pAd, 362 struct rt_ba_rec_entry *pBAEntry) 363{ 364 struct reordering_mpdu *mpdu_blk; 365 366 NdisAcquireSpinLock(&pBAEntry->RxReRingLock); 367 368 /* dequeue in-order frame from reodering list */ 369 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) { 370 /* pass this frame up */ 371 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); 372 373 pBAEntry->LastIndSeq = mpdu_blk->Sequence; 374 ba_mpdu_blk_free(pAd, mpdu_blk); 375 376 /* update last indicated sequence */ 377 } 378 ASSERT(pBAEntry->list.qlen == 0); 379 pBAEntry->LastIndSeq = RESET_RCV_SEQ; 380 NdisReleaseSpinLock(&pBAEntry->RxReRingLock); 381} 382 383/*static */ 384void ba_flush_reordering_timeout_mpdus(struct rt_rtmp_adapter *pAd, 385 struct rt_ba_rec_entry *pBAEntry, 386 unsigned long Now32) 387{ 388 u16 Sequence; 389 390/* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && */ 391/* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| */ 392/* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && */ 393/* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) */ 394 if (RTMP_TIME_AFTER 395 ((unsigned long)Now32, 396 (unsigned long)(pBAEntry->LastIndSeqAtTimer + 397 (MAX_REORDERING_PACKET_TIMEOUT / 6))) 398 && (pBAEntry->list.qlen > 1) 399 ) { 400 DBGPRINT(RT_DEBUG_TRACE, 401 ("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", 402 pBAEntry->list.qlen, Now32, 403 (pBAEntry->LastIndSeqAtTimer), 404 (int)((long)Now32 - 405 (long)(pBAEntry->LastIndSeqAtTimer)), 406 MAX_REORDERING_PACKET_TIMEOUT, pBAEntry->LastIndSeq)); 407 ba_refresh_reordering_mpdus(pAd, pBAEntry); 408 pBAEntry->LastIndSeqAtTimer = Now32; 409 } else 410 if (RTMP_TIME_AFTER 411 ((unsigned long)Now32, 412 (unsigned long)(pBAEntry->LastIndSeqAtTimer + 413 (REORDERING_PACKET_TIMEOUT))) 414 && (pBAEntry->list.qlen > 0) 415 ) { 416 /* */ 417 /* force LastIndSeq to shift to LastIndSeq+1 */ 418 /* */ 419 Sequence = (pBAEntry->LastIndSeq + 1) & MAXSEQ; 420 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); 421 pBAEntry->LastIndSeqAtTimer = Now32; 422 pBAEntry->LastIndSeq = Sequence; 423 /* */ 424 /* indicate in-order mpdus */ 425 /* */ 426 Sequence = 427 ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, 428 Sequence); 429 if (Sequence != RESET_RCV_SEQ) { 430 pBAEntry->LastIndSeq = Sequence; 431 } 432 433 DBGPRINT(RT_DEBUG_OFF, 434 ("%x, flush one!\n", pBAEntry->LastIndSeq)); 435 436 } 437} 438 439/* 440 * generate ADDBA request to 441 * set up BA agreement 442 */ 443void BAOriSessionSetUp(struct rt_rtmp_adapter *pAd, 444 struct rt_mac_table_entry *pEntry, 445 u8 TID, 446 u16 TimeOut, 447 unsigned long DelayTime, IN BOOLEAN isForced) 448{ 449 /*struct rt_mlme_addba_req AddbaReq; */ 450 struct rt_ba_ori_entry *pBAEntry = NULL; 451 u16 Idx; 452 BOOLEAN Cancelled; 453 454 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) 455 && (isForced == FALSE)) 456 return; 457 458 /* if this entry is limited to use legacy tx mode, it doesn't generate BA. */ 459 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) 460 return; 461 462 if ((pEntry->BADeclineBitmap & (1 << TID)) && (isForced == FALSE)) { 463 /* try again after 3 secs */ 464 DelayTime = 3000; 465/* DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n")); */ 466/* return; */ 467 } 468 469 Idx = pEntry->BAOriWcidArray[TID]; 470 if (Idx == 0) { 471 /* allocate a BA session */ 472 pBAEntry = BATableAllocOriEntry(pAd, &Idx); 473 if (pBAEntry == NULL) { 474 DBGPRINT(RT_DEBUG_TRACE, 475 ("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); 476 return; 477 } 478 } else { 479 pBAEntry = &pAd->BATable.BAOriEntry[Idx]; 480 } 481 482 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) { 483 return; 484 } 485 486 pEntry->BAOriWcidArray[TID] = Idx; 487 488 /* Initialize BA session */ 489 pBAEntry->ORI_BA_Status = Originator_WaitRes; 490 pBAEntry->Wcid = pEntry->Aid; 491 pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; 492 pBAEntry->Sequence = BA_ORI_INIT_SEQ; 493 pBAEntry->Token = 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0 */ 494 pBAEntry->TID = TID; 495 pBAEntry->TimeOutValue = TimeOut; 496 pBAEntry->pAdapter = pAd; 497 498 if (!(pEntry->TXBAbitmap & (1 << TID))) { 499 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, 500 GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), 501 pBAEntry, FALSE); 502 } else 503 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); 504 505 /* set timer to send ADDBA request */ 506 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); 507} 508 509void BAOriSessionAdd(struct rt_rtmp_adapter *pAd, 510 struct rt_mac_table_entry *pEntry, struct rt_frame_addba_rsp * pFrame) 511{ 512 struct rt_ba_ori_entry *pBAEntry = NULL; 513 BOOLEAN Cancelled; 514 u8 TID; 515 u16 Idx; 516 u8 *pOutBuffer2 = NULL; 517 int NStatus; 518 unsigned long FrameLen; 519 struct rt_frame_bar FrameBar; 520 521 TID = pFrame->BaParm.TID; 522 Idx = pEntry->BAOriWcidArray[TID]; 523 pBAEntry = &pAd->BATable.BAOriEntry[Idx]; 524 525 /* Start fill in parameters. */ 526 if ((Idx != 0) && (pBAEntry->TID == TID) 527 && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) { 528 pBAEntry->BAWinSize = 529 min(pBAEntry->BAWinSize, ((u8)pFrame->BaParm.BufSize)); 530 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); 531 532 pBAEntry->TimeOutValue = pFrame->TimeOutValue; 533 pBAEntry->ORI_BA_Status = Originator_Done; 534 pAd->BATable.numDoneOriginator++; 535 536 /* reset sequence number */ 537 pBAEntry->Sequence = BA_ORI_INIT_SEQ; 538 /* Set Bitmap flag. */ 539 pEntry->TXBAbitmap |= (1 << TID); 540 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); 541 542 pBAEntry->ORIBATimer.TimerValue = 0; /*pFrame->TimeOutValue; */ 543 544 DBGPRINT(RT_DEBUG_TRACE, 545 ("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", 546 __func__, pEntry->TXBAbitmap, pBAEntry->BAWinSize, 547 pBAEntry->ORIBATimer.TimerValue)); 548 549 /* SEND BAR ; */ 550 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory */ 551 if (NStatus != NDIS_STATUS_SUCCESS) { 552 DBGPRINT(RT_DEBUG_TRACE, 553 ("BA - BAOriSessionAdd() allocate memory failed \n")); 554 return; 555 } 556 557 BarHeaderInit(pAd, &FrameBar, 558 pAd->MacTab.Content[pBAEntry->Wcid].Addr, 559 pAd->CurrentAddress); 560 561 FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function. */ 562 FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; /* make sure sequence not clear in DEL funciton. */ 563 FrameBar.BarControl.TID = pBAEntry->TID; /* make sure sequence not clear in DEL funciton. */ 564 MakeOutgoingFrame(pOutBuffer2, &FrameLen, 565 sizeof(struct rt_frame_bar), &FrameBar, END_OF_ARGS); 566 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); 567 MlmeFreeMemory(pAd, pOutBuffer2); 568 569 if (pBAEntry->ORIBATimer.TimerValue) 570 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); /* in mSec */ 571 } 572} 573 574BOOLEAN BARecSessionAdd(struct rt_rtmp_adapter *pAd, 575 struct rt_mac_table_entry *pEntry, struct rt_frame_addba_req * pFrame) 576{ 577 struct rt_ba_rec_entry *pBAEntry = NULL; 578 BOOLEAN Status = TRUE; 579 BOOLEAN Cancelled; 580 u16 Idx; 581 u8 TID; 582 u8 BAWinSize; 583 /*u32 Value; */ 584 /*u32 offset; */ 585 586 ASSERT(pEntry); 587 588 /* find TID */ 589 TID = pFrame->BaParm.TID; 590 591 BAWinSize = 592 min(((u8)pFrame->BaParm.BufSize), 593 (u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit); 594 595 /* Intel patch */ 596 if (BAWinSize == 0) { 597 BAWinSize = 64; 598 } 599 600 Idx = pEntry->BARecWcidArray[TID]; 601 602 if (Idx == 0) { 603 pBAEntry = BATableAllocRecEntry(pAd, &Idx); 604 } else { 605 pBAEntry = &pAd->BATable.BARecEntry[Idx]; 606 /* flush all pending reordering mpdus */ 607 ba_refresh_reordering_mpdus(pAd, pBAEntry); 608 } 609 610 DBGPRINT(RT_DEBUG_TRACE, 611 ("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__, 612 pAd->BATable.numAsRecipient, Idx, pFrame->BaParm.BufSize, 613 BAWinSize)); 614 615 /* Start fill in parameters. */ 616 if (pBAEntry != NULL) { 617 ASSERT(pBAEntry->list.qlen == 0); 618 619 pBAEntry->REC_BA_Status = Recipient_HandleRes; 620 pBAEntry->BAWinSize = BAWinSize; 621 pBAEntry->Wcid = pEntry->Aid; 622 pBAEntry->TID = TID; 623 pBAEntry->TimeOutValue = pFrame->TimeOutValue; 624 pBAEntry->REC_BA_Status = Recipient_Accept; 625 /* initial sequence number */ 626 pBAEntry->LastIndSeq = RESET_RCV_SEQ; /*pFrame->BaStartSeq.field.StartSeq; */ 627 628 DBGPRINT(RT_DEBUG_OFF, 629 ("Start Seq = %08x\n", 630 pFrame->BaStartSeq.field.StartSeq)); 631 632 if (pEntry->RXBAbitmap & (1 << TID)) { 633 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); 634 } else { 635 RTMPInitTimer(pAd, &pBAEntry->RECBATimer, 636 GET_TIMER_FUNCTION 637 (BARecSessionIdleTimeout), pBAEntry, 638 TRUE); 639 } 640 641 /* Set Bitmap flag. */ 642 pEntry->RXBAbitmap |= (1 << TID); 643 pEntry->BARecWcidArray[TID] = Idx; 644 645 pEntry->BADeclineBitmap &= ~(1 << TID); 646 647 /* Set BA session mask in WCID table. */ 648 RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID); 649 650 DBGPRINT(RT_DEBUG_TRACE, 651 ("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", 652 pEntry->Aid, pEntry->RXBAbitmap, 653 pEntry->BARecWcidArray[TID])); 654 } else { 655 Status = FALSE; 656 DBGPRINT(RT_DEBUG_TRACE, 657 ("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", 658 PRINT_MAC(pEntry->Addr), TID)); 659 } 660 return (Status); 661} 662 663struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx) 664{ 665 int i; 666 struct rt_ba_rec_entry *pBAEntry = NULL; 667 668 NdisAcquireSpinLock(&pAd->BATabLock); 669 670 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) { 671 DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n", 672 pAd->BATable.numAsRecipient, 673 MAX_BARECI_SESSION)); 674 goto done; 675 } 676 /* reserve idx 0 to identify BAWcidArray[TID] as empty */ 677 for (i = 1; i < MAX_LEN_OF_BA_REC_TABLE; i++) { 678 pBAEntry = &pAd->BATable.BARecEntry[i]; 679 if ((pBAEntry->REC_BA_Status == Recipient_NONE)) { 680 /* get one */ 681 pAd->BATable.numAsRecipient++; 682 pBAEntry->REC_BA_Status = Recipient_USED; 683 *Idx = i; 684 break; 685 } 686 } 687 688done: 689 NdisReleaseSpinLock(&pAd->BATabLock); 690 return pBAEntry; 691} 692 693struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx) 694{ 695 int i; 696 struct rt_ba_ori_entry *pBAEntry = NULL; 697 698 NdisAcquireSpinLock(&pAd->BATabLock); 699 700 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) { 701 goto done; 702 } 703 /* reserve idx 0 to identify BAWcidArray[TID] as empty */ 704 for (i = 1; i < MAX_LEN_OF_BA_ORI_TABLE; i++) { 705 pBAEntry = &pAd->BATable.BAOriEntry[i]; 706 if ((pBAEntry->ORI_BA_Status == Originator_NONE)) { 707 /* get one */ 708 pAd->BATable.numAsOriginator++; 709 pBAEntry->ORI_BA_Status = Originator_USED; 710 pBAEntry->pAdapter = pAd; 711 *Idx = i; 712 break; 713 } 714 } 715 716done: 717 NdisReleaseSpinLock(&pAd->BATabLock); 718 return pBAEntry; 719} 720 721void BATableFreeOriEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx) 722{ 723 struct rt_ba_ori_entry *pBAEntry = NULL; 724 struct rt_mac_table_entry *pEntry; 725 726 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) 727 return; 728 729 pBAEntry = &pAd->BATable.BAOriEntry[Idx]; 730 731 if (pBAEntry->ORI_BA_Status != Originator_NONE) { 732 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; 733 pEntry->BAOriWcidArray[pBAEntry->TID] = 0; 734 735 NdisAcquireSpinLock(&pAd->BATabLock); 736 if (pBAEntry->ORI_BA_Status == Originator_Done) { 737 pAd->BATable.numDoneOriginator -= 1; 738 pEntry->TXBAbitmap &= (~(1 << (pBAEntry->TID))); 739 DBGPRINT(RT_DEBUG_TRACE, 740 ("BATableFreeOriEntry numAsOriginator= %ld\n", 741 pAd->BATable.numAsRecipient)); 742 /* Erase Bitmap flag. */ 743 } 744 745 ASSERT(pAd->BATable.numAsOriginator != 0); 746 747 pAd->BATable.numAsOriginator -= 1; 748 749 pBAEntry->ORI_BA_Status = Originator_NONE; 750 pBAEntry->Token = 0; 751 NdisReleaseSpinLock(&pAd->BATabLock); 752 } 753} 754 755void BATableFreeRecEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx) 756{ 757 struct rt_ba_rec_entry *pBAEntry = NULL; 758 struct rt_mac_table_entry *pEntry; 759 760 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) 761 return; 762 763 pBAEntry = &pAd->BATable.BARecEntry[Idx]; 764 765 if (pBAEntry->REC_BA_Status != Recipient_NONE) { 766 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; 767 pEntry->BARecWcidArray[pBAEntry->TID] = 0; 768 769 NdisAcquireSpinLock(&pAd->BATabLock); 770 771 ASSERT(pAd->BATable.numAsRecipient != 0); 772 773 pAd->BATable.numAsRecipient -= 1; 774 775 pBAEntry->REC_BA_Status = Recipient_NONE; 776 NdisReleaseSpinLock(&pAd->BATabLock); 777 } 778} 779 780void BAOriSessionTearDown(struct rt_rtmp_adapter *pAd, 781 u8 Wcid, 782 u8 TID, 783 IN BOOLEAN bPassive, IN BOOLEAN bForceSend) 784{ 785 unsigned long Idx = 0; 786 struct rt_ba_ori_entry *pBAEntry; 787 BOOLEAN Cancelled; 788 789 if (Wcid >= MAX_LEN_OF_MAC_TABLE) { 790 return; 791 } 792 /* */ 793 /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */ 794 /* */ 795 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; 796 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) { 797 if (bForceSend == TRUE) { 798 /* force send specified TID DelBA */ 799 struct rt_mlme_delba_req DelbaReq; 800 struct rt_mlme_queue_elem *Elem = 801 (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), 802 MEM_ALLOC_FLAG); 803 if (Elem != NULL) { 804 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); 805 NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); 806 807 COPY_MAC_ADDR(DelbaReq.Addr, 808 pAd->MacTab.Content[Wcid].Addr); 809 DelbaReq.Wcid = Wcid; 810 DelbaReq.TID = TID; 811 DelbaReq.Initiator = ORIGINATOR; 812 Elem->MsgLen = sizeof(DelbaReq); 813 NdisMoveMemory(Elem->Msg, &DelbaReq, 814 sizeof(DelbaReq)); 815 MlmeDELBAAction(pAd, Elem); 816 kfree(Elem); 817 } else { 818 DBGPRINT(RT_DEBUG_ERROR, 819 ("%s(bForceSend):alloc memory failed!\n", 820 __func__)); 821 } 822 } 823 824 return; 825 } 826 827 DBGPRINT(RT_DEBUG_TRACE, 828 ("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID)); 829 830 pBAEntry = &pAd->BATable.BAOriEntry[Idx]; 831 DBGPRINT(RT_DEBUG_TRACE, 832 ("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, 833 Wcid, TID, pBAEntry->ORI_BA_Status)); 834 /* */ 835 /* Prepare DelBA action frame and send to the peer. */ 836 /* */ 837 if ((bPassive == FALSE) && (TID == pBAEntry->TID) 838 && (pBAEntry->ORI_BA_Status == Originator_Done)) { 839 struct rt_mlme_delba_req DelbaReq; 840 struct rt_mlme_queue_elem *Elem = 841 (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), 842 MEM_ALLOC_FLAG); 843 if (Elem != NULL) { 844 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); 845 NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); 846 847 COPY_MAC_ADDR(DelbaReq.Addr, 848 pAd->MacTab.Content[Wcid].Addr); 849 DelbaReq.Wcid = Wcid; 850 DelbaReq.TID = pBAEntry->TID; 851 DelbaReq.Initiator = ORIGINATOR; 852 Elem->MsgLen = sizeof(DelbaReq); 853 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); 854 MlmeDELBAAction(pAd, Elem); 855 kfree(Elem); 856 } else { 857 DBGPRINT(RT_DEBUG_ERROR, 858 ("%s():alloc memory failed!\n", __func__)); 859 return; 860 } 861 } 862 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); 863 BATableFreeOriEntry(pAd, Idx); 864 865 if (bPassive) { 866 /*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); */ 867 } 868} 869 870void BARecSessionTearDown(struct rt_rtmp_adapter *pAd, 871 u8 Wcid, u8 TID, IN BOOLEAN bPassive) 872{ 873 unsigned long Idx = 0; 874 struct rt_ba_rec_entry *pBAEntry; 875 876 if (Wcid >= MAX_LEN_OF_MAC_TABLE) { 877 return; 878 } 879 /* */ 880 /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */ 881 /* */ 882 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; 883 if (Idx == 0) 884 return; 885 886 DBGPRINT(RT_DEBUG_TRACE, 887 ("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID)); 888 889 pBAEntry = &pAd->BATable.BARecEntry[Idx]; 890 DBGPRINT(RT_DEBUG_TRACE, 891 ("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, 892 Wcid, TID, pBAEntry->REC_BA_Status)); 893 /* */ 894 /* Prepare DelBA action frame and send to the peer. */ 895 /* */ 896 if ((TID == pBAEntry->TID) 897 && (pBAEntry->REC_BA_Status == Recipient_Accept)) { 898 struct rt_mlme_delba_req DelbaReq; 899 BOOLEAN Cancelled; 900 /*unsigned long offset; */ 901 /*u32 VALUE; */ 902 903 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); 904 905 /* */ 906 /* 1. Send DELBA Action Frame */ 907 /* */ 908 if (bPassive == FALSE) { 909 struct rt_mlme_queue_elem *Elem = 910 (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem), 911 MEM_ALLOC_FLAG); 912 if (Elem != NULL) { 913 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); 914 NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem)); 915 916 COPY_MAC_ADDR(DelbaReq.Addr, 917 pAd->MacTab.Content[Wcid].Addr); 918 DelbaReq.Wcid = Wcid; 919 DelbaReq.TID = TID; 920 DelbaReq.Initiator = RECIPIENT; 921 Elem->MsgLen = sizeof(DelbaReq); 922 NdisMoveMemory(Elem->Msg, &DelbaReq, 923 sizeof(DelbaReq)); 924 MlmeDELBAAction(pAd, Elem); 925 kfree(Elem); 926 } else { 927 DBGPRINT(RT_DEBUG_ERROR, 928 ("%s():alloc memory failed!\n", 929 __func__)); 930 return; 931 } 932 } 933 934 /* */ 935 /* 2. Free resource of BA session */ 936 /* */ 937 /* flush all pending reordering mpdus */ 938 ba_refresh_reordering_mpdus(pAd, pBAEntry); 939 940 NdisAcquireSpinLock(&pAd->BATabLock); 941 942 /* Erase Bitmap flag. */ 943 pBAEntry->LastIndSeq = RESET_RCV_SEQ; 944 pBAEntry->BAWinSize = 0; 945 /* Erase Bitmap flag at software mactable */ 946 pAd->MacTab.Content[Wcid].RXBAbitmap &= 947 (~(1 << (pBAEntry->TID))); 948 pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0; 949 950 RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); 951 952 NdisReleaseSpinLock(&pAd->BATabLock); 953 954 } 955 956 BATableFreeRecEntry(pAd, Idx); 957} 958 959void BASessionTearDownALL(struct rt_rtmp_adapter *pAd, u8 Wcid) 960{ 961 int i; 962 963 for (i = 0; i < NUM_OF_TID; i++) { 964 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE); 965 BARecSessionTearDown(pAd, Wcid, i, FALSE); 966 } 967} 968 969/* 970 ========================================================================== 971 Description: 972 Retry sending ADDBA Reqest. 973 974 IRQL = DISPATCH_LEVEL 975 976 Parametrs: 977 p8023Header: if this is already 802.3 format, p8023Header is NULL 978 979 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. 980 FALSE , then continue indicaterx at this moment. 981 ========================================================================== 982 */ 983void BAOriSessionSetupTimeout(void *SystemSpecific1, 984 void *FunctionContext, 985 void *SystemSpecific2, 986 void *SystemSpecific3) 987{ 988 struct rt_ba_ori_entry *pBAEntry = (struct rt_ba_ori_entry *)FunctionContext; 989 struct rt_mac_table_entry *pEntry; 990 struct rt_rtmp_adapter *pAd; 991 992 if (pBAEntry == NULL) 993 return; 994 995 pAd = pBAEntry->pAdapter; 996 997 { 998 /* Do nothing if monitor mode is on */ 999 if (MONITOR_ON(pAd)) 1000 return; 1001 } 1002 1003 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; 1004 1005 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) 1006 && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) { 1007 struct rt_mlme_addba_req AddbaReq; 1008 1009 NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); 1010 COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); 1011 AddbaReq.Wcid = (u8)(pEntry->Aid); 1012 AddbaReq.TID = pBAEntry->TID; 1013 AddbaReq.BaBufSize = 1014 pAd->CommonCfg.BACapability.field.RxBAWinLimit; 1015 AddbaReq.TimeOutValue = 0; 1016 AddbaReq.Token = pBAEntry->Token; 1017 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, 1018 sizeof(struct rt_mlme_addba_req), (void *)& AddbaReq); 1019 RTMP_MLME_HANDLER(pAd); 1020 DBGPRINT(RT_DEBUG_TRACE, 1021 ("BA Ori Session Timeout(%d) : Send ADD BA again\n", 1022 pBAEntry->Token)); 1023 1024 pBAEntry->Token++; 1025 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); 1026 } else { 1027 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); 1028 } 1029} 1030 1031/* 1032 ========================================================================== 1033 Description: 1034 Retry sending ADDBA Reqest. 1035 1036 IRQL = DISPATCH_LEVEL 1037 1038 Parametrs: 1039 p8023Header: if this is already 802.3 format, p8023Header is NULL 1040 1041 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. 1042 FALSE , then continue indicaterx at this moment. 1043 ========================================================================== 1044 */ 1045void BARecSessionIdleTimeout(void *SystemSpecific1, 1046 void *FunctionContext, 1047 void *SystemSpecific2, void *SystemSpecific3) 1048{ 1049 1050 struct rt_ba_rec_entry *pBAEntry = (struct rt_ba_rec_entry *)FunctionContext; 1051 struct rt_rtmp_adapter *pAd; 1052 unsigned long Now32; 1053 1054 if (pBAEntry == NULL) 1055 return; 1056 1057 if ((pBAEntry->REC_BA_Status == Recipient_Accept)) { 1058 NdisGetSystemUpTime(&Now32); 1059 1060 if (RTMP_TIME_AFTER 1061 ((unsigned long)Now32, 1062 (unsigned long)(pBAEntry->LastIndSeqAtTimer + 1063 REC_BA_SESSION_IDLE_TIMEOUT))) { 1064 pAd = pBAEntry->pAdapter; 1065 /* flush all pending reordering mpdus */ 1066 ba_refresh_reordering_mpdus(pAd, pBAEntry); 1067 DBGPRINT(RT_DEBUG_OFF, 1068 ("%ld: REC BA session Timeout\n", Now32)); 1069 } 1070 } 1071} 1072 1073void PeerAddBAReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1074{ 1075 /* 7.4.4.1 */ 1076 /*unsigned long Idx; */ 1077 u8 Status = 1; 1078 u8 pAddr[6]; 1079 struct rt_frame_addba_rsp ADDframe; 1080 u8 *pOutBuffer = NULL; 1081 int NStatus; 1082 struct rt_frame_addba_req * pAddreqFrame = NULL; 1083 /*u8 BufSize; */ 1084 unsigned long FrameLen; 1085 unsigned long *ptemp; 1086 struct rt_mac_table_entry *pMacEntry; 1087 1088 DBGPRINT(RT_DEBUG_TRACE, 1089 ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid)); 1090 1091 /*hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); */ 1092 1093 /*ADDBA Request from unknown peer, ignore this. */ 1094 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) 1095 return; 1096 1097 pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; 1098 DBGPRINT(RT_DEBUG_TRACE, ("BA - PeerAddBAReqAction----> \n")); 1099 ptemp = (unsigned long *)Elem->Msg; 1100 /*DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8))); */ 1101 1102 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) { 1103 1104 if ((pAd->CommonCfg.bBADecline == FALSE) 1105 && IS_HT_STA(pMacEntry)) { 1106 pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]); 1107 DBGPRINT(RT_DEBUG_OFF, 1108 ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid)); 1109 if (BARecSessionAdd 1110 (pAd, &pAd->MacTab.Content[Elem->Wcid], 1111 pAddreqFrame)) 1112 Status = 0; 1113 else 1114 Status = 38; /* more parameters have invalid values */ 1115 } else { 1116 Status = 37; /* the request has been declined. */ 1117 } 1118 } 1119 1120 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) 1121 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); 1122 1123 pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]); 1124 /* 2. Always send back ADDBA Response */ 1125 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ 1126 if (NStatus != NDIS_STATUS_SUCCESS) { 1127 DBGPRINT(RT_DEBUG_TRACE, 1128 ("ACTION - PeerBAAction() allocate memory failed \n")); 1129 return; 1130 } 1131 1132 NdisZeroMemory(&ADDframe, sizeof(struct rt_frame_addba_rsp)); 1133 1134 /* 2-1. Prepare ADDBA Response frame. */ 1135 { 1136 if (ADHOC_ON(pAd)) 1137 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, 1138 pAd->CurrentAddress, 1139 pAd->CommonCfg.Bssid); 1140 else 1141 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, 1142 pAd->CurrentAddress, pAddr); 1143 } 1144 1145 ADDframe.Category = CATEGORY_BA; 1146 ADDframe.Action = ADDBA_RESP; 1147 ADDframe.Token = pAddreqFrame->Token; 1148 /* What is the Status code?? need to check. */ 1149 ADDframe.StatusCode = Status; 1150 ADDframe.BaParm.BAPolicy = IMMED_BA; 1151 ADDframe.BaParm.AMSDUSupported = 0; 1152 ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; 1153 ADDframe.BaParm.BufSize = 1154 min(((u8)pAddreqFrame->BaParm.BufSize), 1155 (u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit); 1156 if (ADDframe.BaParm.BufSize == 0) { 1157 ADDframe.BaParm.BufSize = 64; 1158 } 1159 ADDframe.TimeOutValue = 0; /*pAddreqFrame->TimeOutValue; */ 1160 1161 *(u16 *) (&ADDframe.BaParm) = 1162 cpu2le16(*(u16 *) (&ADDframe.BaParm)); 1163 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); 1164 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); 1165 1166 MakeOutgoingFrame(pOutBuffer, &FrameLen, 1167 sizeof(struct rt_frame_addba_rsp), &ADDframe, END_OF_ARGS); 1168 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); 1169 MlmeFreeMemory(pAd, pOutBuffer); 1170 1171 DBGPRINT(RT_DEBUG_TRACE, 1172 ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, 1173 ADDframe.BaParm.TID, ADDframe.BaParm.BufSize)); 1174} 1175 1176void PeerAddBARspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1177{ 1178 /*u8 Idx, i; */ 1179 /*u8 * pOutBuffer = NULL; */ 1180 struct rt_frame_addba_rsp * pFrame = NULL; 1181 /*struct rt_ba_ori_entry *pBAEntry; */ 1182 1183 /*ADDBA Response from unknown peer, ignore this. */ 1184 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) 1185 return; 1186 1187 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid)); 1188 1189 /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); */ 1190 1191 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) { 1192 pFrame = (struct rt_frame_addba_rsp *) (&Elem->Msg[0]); 1193 1194 DBGPRINT(RT_DEBUG_TRACE, 1195 ("\t\t StatusCode = %d\n", pFrame->StatusCode)); 1196 switch (pFrame->StatusCode) { 1197 case 0: 1198 /* I want a BAsession with this peer as an originator. */ 1199 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], 1200 pFrame); 1201 break; 1202 default: 1203 /* check status == USED ??? */ 1204 BAOriSessionTearDown(pAd, Elem->Wcid, 1205 pFrame->BaParm.TID, TRUE, FALSE); 1206 break; 1207 } 1208 /* Rcv Decline StatusCode */ 1209 if ((pFrame->StatusCode == 37) 1210 || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) 1211 && (pFrame->StatusCode != 0)) 1212 ) { 1213 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1214 1 << pFrame->BaParm.TID; 1215 } 1216 } 1217} 1218 1219void PeerDelBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem) 1220{ 1221 /*u8 Idx; */ 1222 /*u8 * pOutBuffer = NULL; */ 1223 struct rt_frame_delba_req * pDelFrame = NULL; 1224 1225 DBGPRINT(RT_DEBUG_TRACE, ("%s ==>\n", __func__)); 1226 /*DELBA Request from unknown peer, ignore this. */ 1227 if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) { 1228 pDelFrame = (struct rt_frame_delba_req *) (&Elem->Msg[0]); 1229 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) { 1230 DBGPRINT(RT_DEBUG_TRACE, 1231 ("BA - PeerDelBAAction----> ORIGINATOR\n")); 1232 BARecSessionTearDown(pAd, Elem->Wcid, 1233 pDelFrame->DelbaParm.TID, TRUE); 1234 } else { 1235 DBGPRINT(RT_DEBUG_TRACE, 1236 ("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", 1237 pDelFrame->ReasonCode)); 1238 /*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); */ 1239 BAOriSessionTearDown(pAd, Elem->Wcid, 1240 pDelFrame->DelbaParm.TID, TRUE, 1241 FALSE); 1242 } 1243 } 1244} 1245 1246BOOLEAN CntlEnqueueForRecv(struct rt_rtmp_adapter *pAd, 1247 unsigned long Wcid, 1248 unsigned long MsgLen, struct rt_frame_ba_req * pMsg) 1249{ 1250 struct rt_frame_ba_req * pFrame = pMsg; 1251 /*PRTMP_REORDERBUF pBuffer; */ 1252 /*PRTMP_REORDERBUF pDmaBuf; */ 1253 struct rt_ba_rec_entry *pBAEntry; 1254 /*BOOLEAN Result; */ 1255 unsigned long Idx; 1256 /*u8 NumRxPkt; */ 1257 u8 TID; /*, i; */ 1258 1259 TID = (u8)pFrame->BARControl.TID; 1260 1261 DBGPRINT(RT_DEBUG_TRACE, 1262 ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID)); 1263 /*hex_dump("BAR", (char *)pFrame, MsgLen); */ 1264 /* Do nothing if the driver is starting halt state. */ 1265 /* This might happen when timer already been fired before cancel timer with mlmehalt */ 1266 if (RTMP_TEST_FLAG 1267 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) 1268 return FALSE; 1269 1270 /* First check the size, it MUST not exceed the mlme queue size */ 1271 if (MsgLen > MGMT_DMA_BUFFER_SIZE) { 1272 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); 1273 return FALSE; 1274 } else if (MsgLen != sizeof(struct rt_frame_ba_req)) { 1275 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); 1276 return FALSE; 1277 } else if (MsgLen != sizeof(struct rt_frame_ba_req)) { 1278 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); 1279 return FALSE; 1280 } 1281 1282 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) { 1283 /* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. */ 1284 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; 1285 pBAEntry = &pAd->BATable.BARecEntry[Idx]; 1286 } else { 1287 return FALSE; 1288 } 1289 1290 DBGPRINT(RT_DEBUG_TRACE, 1291 ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, 1292 pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); 1293 1294 if (SEQ_SMALLER 1295 (pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, 1296 MAXSEQ)) { 1297 /*DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); */ 1298 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, 1299 pFrame->BAStartingSeq.field. 1300 StartSeq); 1301 pBAEntry->LastIndSeq = 1302 (pFrame->BAStartingSeq.field.StartSeq == 1303 0) ? MAXSEQ : (pFrame->BAStartingSeq.field.StartSeq - 1); 1304 } 1305 /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */ 1306 return TRUE; 1307} 1308 1309/* 1310Description : Send PSMP Action frame If PSMP mode switches. 1311*/ 1312void SendPSMPAction(struct rt_rtmp_adapter *pAd, u8 Wcid, u8 Psmp) 1313{ 1314 u8 *pOutBuffer = NULL; 1315 int NStatus; 1316 /*unsigned long Idx; */ 1317 struct rt_frame_psmp_action Frame; 1318 unsigned long FrameLen; 1319 1320 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ 1321 if (NStatus != NDIS_STATUS_SUCCESS) { 1322 DBGPRINT(RT_DEBUG_ERROR, 1323 ("BA - MlmeADDBAAction() allocate memory failed \n")); 1324 return; 1325 } 1326 1327 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, 1328 pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); 1329 1330 Frame.Category = CATEGORY_HT; 1331 Frame.Action = SMPS_ACTION; 1332 switch (Psmp) { 1333 case MMPS_ENABLE: 1334#ifdef RT30xx 1335 if (IS_RT30xx(pAd) 1336 && (pAd->Antenna.field.RxPath > 1 1337 || pAd->Antenna.field.TxPath > 1)) { 1338 RTMP_ASIC_MMPS_DISABLE(pAd); 1339 } 1340#endif /* RT30xx // */ 1341 Frame.Psmp = 0; 1342 break; 1343 case MMPS_DYNAMIC: 1344 Frame.Psmp = 3; 1345 break; 1346 case MMPS_STATIC: 1347#ifdef RT30xx 1348 if (IS_RT30xx(pAd) 1349 && (pAd->Antenna.field.RxPath > 1 1350 || pAd->Antenna.field.TxPath > 1)) { 1351 RTMP_ASIC_MMPS_ENABLE(pAd); 1352 } 1353#endif /* RT30xx // */ 1354 Frame.Psmp = 1; 1355 break; 1356 } 1357 MakeOutgoingFrame(pOutBuffer, &FrameLen, 1358 sizeof(struct rt_frame_psmp_action), &Frame, END_OF_ARGS); 1359 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); 1360 MlmeFreeMemory(pAd, pOutBuffer); 1361 DBGPRINT(RT_DEBUG_ERROR, ("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); 1362} 1363 1364#define RADIO_MEASUREMENT_REQUEST_ACTION 0 1365 1366struct PACKED rt_beacon_request { 1367 u8 RegulatoryClass; 1368 u8 ChannelNumber; 1369 u16 RandomInterval; 1370 u16 MeasurementDuration; 1371 u8 MeasurementMode; 1372 u8 BSSID[MAC_ADDR_LEN]; 1373 u8 ReportingCondition; 1374 u8 Threshold; 1375 u8 SSIDIE[2]; /* 2 byte */ 1376}; 1377 1378struct PACKED rt_measurement_req { 1379 u8 ID; 1380 u8 Length; 1381 u8 Token; 1382 u8 RequestMode; 1383 u8 Type; 1384}; 1385 1386void convert_reordering_packet_to_preAMSDU_or_802_3_packet(struct rt_rtmp_adapter *pAd, 1387 struct rt_rx_blk *pRxBlk, 1388 u8 1389 FromWhichBSSID) 1390{ 1391 void *pRxPkt; 1392 u8 Header802_3[LENGTH_802_3]; 1393 1394 /* 1. get 802.3 Header */ 1395 /* 2. remove LLC */ 1396 /* a. pointer pRxBlk->pData to payload */ 1397 /* b. modify pRxBlk->DataSize */ 1398 1399 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); 1400 1401 ASSERT(pRxBlk->pRxPacket); 1402 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); 1403 1404 SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID)); 1405 SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData); 1406 SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize); 1407 SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize); 1408 1409 /* */ 1410 /* copy 802.3 header, if necessary */ 1411 /* */ 1412 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) { 1413 { 1414 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), 1415 Header802_3, LENGTH_802_3); 1416 } 1417 } 1418} 1419 1420#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ 1421 do \ 1422 { \ 1423 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ 1424 { \ 1425 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ 1426 } \ 1427 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ 1428 { \ 1429 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ 1430 } \ 1431 else \ 1432 { \ 1433 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ 1434 } \ 1435 } while (0); 1436 1437static void ba_enqueue_reordering_packet(struct rt_rtmp_adapter *pAd, 1438 struct rt_ba_rec_entry *pBAEntry, 1439 struct rt_rx_blk *pRxBlk, 1440 u8 FromWhichBSSID) 1441{ 1442 struct reordering_mpdu *mpdu_blk; 1443 u16 Sequence = (u16)pRxBlk->pHeader->Sequence; 1444 1445 mpdu_blk = ba_mpdu_blk_alloc(pAd); 1446 if ((mpdu_blk != NULL) && (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) { 1447 /* Write RxD buffer address & allocated buffer length */ 1448 NdisAcquireSpinLock(&pBAEntry->RxReRingLock); 1449 1450 mpdu_blk->Sequence = Sequence; 1451 1452 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); 1453 1454 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, 1455 pRxBlk, 1456 FromWhichBSSID); 1457 1458 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); 1459 1460 /* */ 1461 /* it is necessary for reordering packet to record */ 1462 /* which BSS it come from */ 1463 /* */ 1464 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); 1465 1466 mpdu_blk->pPacket = pRxBlk->pRxPacket; 1467 1468 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) 1469 == FALSE) { 1470 /* had been already within reordering list */ 1471 /* don't indicate */ 1472 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, 1473 NDIS_STATUS_SUCCESS); 1474 ba_mpdu_blk_free(pAd, mpdu_blk); 1475 } 1476 1477 ASSERT((0 <= pBAEntry->list.qlen) 1478 && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); 1479 NdisReleaseSpinLock(&pBAEntry->RxReRingLock); 1480 } else { 1481 DBGPRINT(RT_DEBUG_ERROR, 1482 (" (%d) Can't allocate reordering mpdu blk\n", 1483 pBAEntry->list.qlen)); 1484 1485 /* 1486 * flush all pending reordering mpdus 1487 * and receving mpdu to upper layer 1488 * make tcp/ip to take care reordering mechanism 1489 */ 1490 /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */ 1491 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); 1492 1493 pBAEntry->LastIndSeq = Sequence; 1494 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); 1495 } 1496} 1497 1498/* 1499 ========================================================================== 1500 Description: 1501 Indicate this packet to upper layer or put it into reordering buffer 1502 1503 Parametrs: 1504 pRxBlk : carry necessary packet info 802.11 format 1505 FromWhichBSSID : the packet received from which BSS 1506 1507 Return : 1508 none 1509 1510 Note : 1511 the packet queued into reordering buffer need to cover to 802.3 format 1512 or pre_AMSDU format 1513 ========================================================================== 1514 */ 1515 1516void Indicate_AMPDU_Packet(struct rt_rtmp_adapter *pAd, 1517 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) 1518{ 1519 u16 Idx; 1520 struct rt_ba_rec_entry *pBAEntry = NULL; 1521 u16 Sequence = pRxBlk->pHeader->Sequence; 1522 unsigned long Now32; 1523 u8 Wcid = pRxBlk->pRxWI->WirelessCliID; 1524 u8 TID = pRxBlk->pRxWI->TID; 1525 1526 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) 1527 && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) { 1528 /* release packet */ 1529 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, 1530 NDIS_STATUS_FAILURE); 1531 return; 1532 } 1533 1534 if (Wcid < MAX_LEN_OF_MAC_TABLE) { 1535 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; 1536 if (Idx == 0) { 1537 /* Rec BA Session had been torn down */ 1538 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); 1539 return; 1540 } 1541 pBAEntry = &pAd->BATable.BARecEntry[Idx]; 1542 } else { 1543 /* impossible ! */ 1544 ASSERT(0); 1545 /* release packet */ 1546 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, 1547 NDIS_STATUS_FAILURE); 1548 return; 1549 } 1550 1551 ASSERT(pBAEntry); 1552 1553 /* update last rx time */ 1554 NdisGetSystemUpTime(&Now32); 1555 1556 pBAEntry->rcvSeq = Sequence; 1557 1558 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); 1559 pBAEntry->LastIndSeqAtTimer = Now32; 1560 1561 /* */ 1562 /* Reset Last Indicate Sequence */ 1563 /* */ 1564 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) { 1565 ASSERT((pBAEntry->list.qlen == 0) 1566 && (pBAEntry->list.next == NULL)); 1567 1568 /* reset rcv sequence of BA session */ 1569 pBAEntry->LastIndSeq = Sequence; 1570 pBAEntry->LastIndSeqAtTimer = Now32; 1571 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); 1572 return; 1573 } 1574 1575 /* */ 1576 /* I. Check if in order. */ 1577 /* */ 1578 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) { 1579 u16 LastIndSeq; 1580 1581 pBAEntry->LastIndSeq = Sequence; 1582 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); 1583 LastIndSeq = 1584 ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, 1585 pBAEntry->LastIndSeq); 1586 if (LastIndSeq != RESET_RCV_SEQ) { 1587 pBAEntry->LastIndSeq = LastIndSeq; 1588 } 1589 pBAEntry->LastIndSeqAtTimer = Now32; 1590 } 1591 /* */ 1592 /* II. Drop Duplicated Packet */ 1593 /* */ 1594 else if (Sequence == pBAEntry->LastIndSeq) { 1595 1596 /* drop and release packet */ 1597 pBAEntry->nDropPacket++; 1598 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, 1599 NDIS_STATUS_FAILURE); 1600 } 1601 /* */ 1602 /* III. Drop Old Received Packet */ 1603 /* */ 1604 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) { 1605 1606 /* drop and release packet */ 1607 pBAEntry->nDropPacket++; 1608 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, 1609 NDIS_STATUS_FAILURE); 1610 } 1611 /* */ 1612 /* IV. Receive Sequence within Window Size */ 1613 /* */ 1614 else if (SEQ_SMALLER 1615 (Sequence, 1616 (((pBAEntry->LastIndSeq + pBAEntry->BAWinSize + 1)) & MAXSEQ), 1617 MAXSEQ)) { 1618 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, 1619 FromWhichBSSID); 1620 } 1621 /* */ 1622 /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer */ 1623 /* */ 1624 else { 1625 long WinStartSeq, TmpSeq; 1626 1627 TmpSeq = Sequence - (pBAEntry->BAWinSize) - 1; 1628 if (TmpSeq < 0) { 1629 TmpSeq = (MAXSEQ + 1) + TmpSeq; 1630 } 1631 WinStartSeq = (TmpSeq + 1) & MAXSEQ; 1632 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); 1633 pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */ 1634 1635 pBAEntry->LastIndSeqAtTimer = Now32; 1636 1637 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, 1638 FromWhichBSSID); 1639 1640 TmpSeq = 1641 ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, 1642 pBAEntry->LastIndSeq); 1643 if (TmpSeq != RESET_RCV_SEQ) { 1644 pBAEntry->LastIndSeq = TmpSeq; 1645 } 1646 } 1647} 1648