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