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