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