~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/staging/rt2860/common/ba_action.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
42
 
static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd,
43
 
                             struct reordering_mpdu *mpdu_blk);
44
 
 
45
 
struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx);
46
 
 
47
 
struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx);
48
 
 
49
 
void BAOriSessionSetupTimeout(void *SystemSpecific1,
50
 
                              void *FunctionContext,
51
 
                              void *SystemSpecific2,
52
 
                              void *SystemSpecific3);
53
 
 
54
 
void BARecSessionIdleTimeout(void *SystemSpecific1,
55
 
                             void *FunctionContext,
56
 
                             void *SystemSpecific2,
57
 
                             void *SystemSpecific3);
58
 
 
59
 
BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
60
 
BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
61
 
 
62
 
#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk)     \
63
 
                        Announce_Reordering_Packet(_pAd, _mpdu_blk);
64
 
 
65
 
void 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
 
 
101
 
void 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
 
 */
124
 
BOOLEAN 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
 
 */
151
 
static 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
 
 */
162
 
static 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
 
 
179
 
static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct
180
 
                                                                 reordering_list
181
 
                                                                 *list)
182
 
{
183
 
        return (ba_dequeue(list));
184
 
}
185
 
 
186
 
static 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
 
 */
198
 
void 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
 
 */
233
 
BOOLEAN 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
 
 
281
 
static 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
 
 
296
 
static 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
 
 
307
 
static 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
 
 
338
 
static 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
 
 
362
 
static 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 */
385
 
void 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
 
 */
444
 
void 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
 
 
510
 
void 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
 
 
575
 
BOOLEAN 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
 
 
664
 
struct 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
 
 
689
 
done:
690
 
        NdisReleaseSpinLock(&pAd->BATabLock);
691
 
        return pBAEntry;
692
 
}
693
 
 
694
 
struct 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
 
 
717
 
done:
718
 
        NdisReleaseSpinLock(&pAd->BATabLock);
719
 
        return pBAEntry;
720
 
}
721
 
 
722
 
void 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
 
 
756
 
void 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
 
 
781
 
void 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
 
 
871
 
void 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
 
 
960
 
void 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
 
 */
984
 
void 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
 
 */
1046
 
void 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
 
 
1074
 
void 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
 
 
1177
 
void 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
 
 
1220
 
void 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
 
 
1247
 
BOOLEAN 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
 
/*
1311
 
Description : Send PSMP Action frame If PSMP mode switches.
1312
 
*/
1313
 
void 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
 
 
1367
 
struct 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
 
 
1379
 
struct PACKED rt_measurement_req {
1380
 
        u8 ID;
1381
 
        u8 Length;
1382
 
        u8 Token;
1383
 
        u8 RequestMode;
1384
 
        u8 Type;
1385
 
};
1386
 
 
1387
 
void 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
 
 
1440
 
static 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
 
 
1519
 
void 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
 
}