mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-14 06:35:12 +00:00
06aea994cf
This removes superfluous exclamation marks from strings and comments, and also three spelling typos. Signed-off-by: Sebastian Dalfuß <sd@sedf.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1649 lines
46 KiB
C
1649 lines
46 KiB
C
/*
|
|
*************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 5F., No.36, Taiyuan St., Jhubei City,
|
|
* Hsinchu County 302,
|
|
* Taiwan, R.O.C.
|
|
*
|
|
* (c) Copyright 2002-2007, Ralink Technology, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
*************************************************************************
|
|
*/
|
|
|
|
#include "../rt_config.h"
|
|
|
|
#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 // inital sequence number of BA session */
|
|
|
|
#define ORI_SESSION_MAX_RETRY 8
|
|
#define ORI_BA_SESSION_TIMEOUT (2000) /* ms */
|
|
#define REC_BA_SESSION_IDLE_TIMEOUT (1000) /* ms */
|
|
|
|
#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */
|
|
#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms */
|
|
|
|
#define RESET_RCV_SEQ (0xFFFF)
|
|
|
|
static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd,
|
|
struct reordering_mpdu *mpdu_blk);
|
|
|
|
struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx);
|
|
|
|
struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx);
|
|
|
|
void BAOriSessionSetupTimeout(void *SystemSpecific1,
|
|
void *FunctionContext,
|
|
void *SystemSpecific2,
|
|
void *SystemSpecific3);
|
|
|
|
void BARecSessionIdleTimeout(void *SystemSpecific1,
|
|
void *FunctionContext,
|
|
void *SystemSpecific2,
|
|
void *SystemSpecific3);
|
|
|
|
BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
|
|
BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
|
|
|
|
#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
|
|
Announce_Reordering_Packet(_pAd, _mpdu_blk);
|
|
|
|
void BA_MaxWinSizeReasign(struct rt_rtmp_adapter *pAd,
|
|
struct rt_mac_table_entry *pEntryPeer, u8 * pWinSize)
|
|
{
|
|
u8 MaxSize;
|
|
|
|
if (pAd->MACVersion >= RALINK_2883_VERSION) /* 3*3 */
|
|
{
|
|
if (pAd->MACVersion >= RALINK_3070_VERSION) {
|
|
if (pEntryPeer->WepStatus !=
|
|
Ndis802_11EncryptionDisabled)
|
|
MaxSize = 7; /* for non-open mode */
|
|
else
|
|
MaxSize = 13;
|
|
} else
|
|
MaxSize = 31;
|
|
} else if (pAd->MACVersion >= RALINK_2880E_VERSION) /* 2880 e */
|
|
{
|
|
if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
|
|
MaxSize = 7; /* for non-open mode */
|
|
else
|
|
MaxSize = 13;
|
|
} else
|
|
MaxSize = 7;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
|
|
*pWinSize, MaxSize));
|
|
|
|
if ((*pWinSize) > MaxSize) {
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("ba> reassign max win size from %d to %d\n",
|
|
*pWinSize, MaxSize));
|
|
|
|
*pWinSize = MaxSize;
|
|
}
|
|
}
|
|
|
|
void Announce_Reordering_Packet(struct rt_rtmp_adapter *pAd,
|
|
IN struct reordering_mpdu *mpdu)
|
|
{
|
|
void *pPacket;
|
|
|
|
pPacket = mpdu->pPacket;
|
|
|
|
if (mpdu->bAMSDU) {
|
|
ASSERT(0);
|
|
BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
|
|
} else {
|
|
/* */
|
|
/* pass this 802.3 packet to upper layer or forward this packet to WM directly */
|
|
/* */
|
|
|
|
ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket,
|
|
RTMP_GET_PACKET_IF(pPacket));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Insert a reordering mpdu into sorted linked list by sequence no.
|
|
*/
|
|
BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list,
|
|
struct reordering_mpdu *mpdu)
|
|
{
|
|
|
|
struct reordering_mpdu **ppScan = &list->next;
|
|
|
|
while (*ppScan != NULL) {
|
|
if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) {
|
|
ppScan = &(*ppScan)->next;
|
|
} else if ((*ppScan)->Sequence == mpdu->Sequence) {
|
|
/* give up this duplicated frame */
|
|
return (FALSE);
|
|
} else {
|
|
/* find position */
|
|
break;
|
|
}
|
|
}
|
|
|
|
mpdu->next = *ppScan;
|
|
*ppScan = mpdu;
|
|
list->qlen++;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* caller lock critical section if necessary
|
|
*/
|
|
static inline void ba_enqueue(struct reordering_list *list,
|
|
struct reordering_mpdu *mpdu_blk)
|
|
{
|
|
list->qlen++;
|
|
mpdu_blk->next = list->next;
|
|
list->next = mpdu_blk;
|
|
}
|
|
|
|
/*
|
|
* caller lock critical section if necessary
|
|
*/
|
|
static inline struct reordering_mpdu *ba_dequeue(struct reordering_list *list)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk = NULL;
|
|
|
|
ASSERT(list);
|
|
|
|
if (list->qlen) {
|
|
list->qlen--;
|
|
mpdu_blk = list->next;
|
|
if (mpdu_blk) {
|
|
list->next = mpdu_blk->next;
|
|
mpdu_blk->next = NULL;
|
|
}
|
|
}
|
|
return mpdu_blk;
|
|
}
|
|
|
|
static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct
|
|
reordering_list
|
|
*list)
|
|
{
|
|
return (ba_dequeue(list));
|
|
}
|
|
|
|
static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct
|
|
reordering_list
|
|
*list)
|
|
{
|
|
ASSERT(list);
|
|
|
|
return (list->next);
|
|
}
|
|
|
|
/*
|
|
* free all resource for reordering mechanism
|
|
*/
|
|
void ba_reordering_resource_release(struct rt_rtmp_adapter *pAd)
|
|
{
|
|
struct rt_ba_table *Tab;
|
|
struct rt_ba_rec_entry *pBAEntry;
|
|
struct reordering_mpdu *mpdu_blk;
|
|
int i;
|
|
|
|
Tab = &pAd->BATable;
|
|
|
|
/* I. release all pending reordering packet */
|
|
NdisAcquireSpinLock(&pAd->BATabLock);
|
|
for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
|
|
pBAEntry = &Tab->BARecEntry[i];
|
|
if (pBAEntry->REC_BA_Status != Recipient_NONE) {
|
|
while ((mpdu_blk =
|
|
ba_reordering_mpdu_dequeue(&pBAEntry->list))) {
|
|
ASSERT(mpdu_blk->pPacket);
|
|
RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket,
|
|
NDIS_STATUS_FAILURE);
|
|
ba_mpdu_blk_free(pAd, mpdu_blk);
|
|
}
|
|
}
|
|
}
|
|
NdisReleaseSpinLock(&pAd->BATabLock);
|
|
|
|
ASSERT(pBAEntry->list.qlen == 0);
|
|
/* II. free memory of reordering mpdu table */
|
|
NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
|
|
os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
|
|
NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
|
|
}
|
|
|
|
/*
|
|
* Allocate all resource for reordering mechanism
|
|
*/
|
|
BOOLEAN ba_reordering_resource_init(struct rt_rtmp_adapter *pAd, int num)
|
|
{
|
|
int i;
|
|
u8 *mem;
|
|
struct reordering_mpdu *mpdu_blk;
|
|
struct reordering_list *freelist;
|
|
|
|
/* allocate spinlock */
|
|
NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
|
|
|
|
/* initialize freelist */
|
|
freelist = &pAd->mpdu_blk_pool.freelist;
|
|
freelist->next = NULL;
|
|
freelist->qlen = 0;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("Allocate %d memory for BA reordering\n",
|
|
(u32)(num * sizeof(struct reordering_mpdu))));
|
|
|
|
/* allocate number of mpdu_blk memory */
|
|
os_alloc_mem(pAd, (u8 **) & mem,
|
|
(num * sizeof(struct reordering_mpdu)));
|
|
|
|
pAd->mpdu_blk_pool.mem = mem;
|
|
|
|
if (mem == NULL) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("Can't Allocate Memory for BA Reordering\n"));
|
|
return (FALSE);
|
|
}
|
|
|
|
/* build mpdu_blk free list */
|
|
for (i = 0; i < num; i++) {
|
|
/* get mpdu_blk */
|
|
mpdu_blk = (struct reordering_mpdu *)mem;
|
|
/* initial mpdu_blk */
|
|
NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
|
|
/* next mpdu_blk */
|
|
mem += sizeof(struct reordering_mpdu);
|
|
/* insert mpdu_blk into freelist */
|
|
ba_enqueue(freelist, mpdu_blk);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*static int blk_count=0; // sample take off, no use */
|
|
|
|
static struct reordering_mpdu *ba_mpdu_blk_alloc(struct rt_rtmp_adapter *pAd)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk;
|
|
|
|
NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
|
|
mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
|
|
if (mpdu_blk) {
|
|
/* blk_count++; */
|
|
/* reset mpdu_blk */
|
|
NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
|
|
}
|
|
NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
|
|
return mpdu_blk;
|
|
}
|
|
|
|
static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd,
|
|
struct reordering_mpdu *mpdu_blk)
|
|
{
|
|
ASSERT(mpdu_blk);
|
|
|
|
NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
|
|
/* blk_count--; */
|
|
ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
|
|
NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
|
|
}
|
|
|
|
static u16 ba_indicate_reordering_mpdus_in_order(struct rt_rtmp_adapter *pAd,
|
|
struct rt_ba_rec_entry *pBAEntry,
|
|
u16 StartSeq)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk;
|
|
u16 LastIndSeq = RESET_RCV_SEQ;
|
|
|
|
NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
|
|
|
|
while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) {
|
|
/* find in-order frame */
|
|
if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) {
|
|
break;
|
|
}
|
|
/* dequeue in-order frame from reodering list */
|
|
mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
|
|
/* pass this frame up */
|
|
ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
|
|
/* move to next sequence */
|
|
StartSeq = mpdu_blk->Sequence;
|
|
LastIndSeq = StartSeq;
|
|
/* free mpdu_blk */
|
|
ba_mpdu_blk_free(pAd, mpdu_blk);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
|
|
|
|
/* update last indicated sequence */
|
|
return LastIndSeq;
|
|
}
|
|
|
|
static void ba_indicate_reordering_mpdus_le_seq(struct rt_rtmp_adapter *pAd,
|
|
struct rt_ba_rec_entry *pBAEntry,
|
|
u16 Sequence)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk;
|
|
|
|
NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
|
|
while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) {
|
|
/* find in-order frame */
|
|
if ((mpdu_blk->Sequence == Sequence)
|
|
|| SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) {
|
|
/* dequeue in-order frame from reodering list */
|
|
mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
|
|
/* pass this frame up */
|
|
ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
|
|
/* free mpdu_blk */
|
|
ba_mpdu_blk_free(pAd, mpdu_blk);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
|
|
}
|
|
|
|
static void ba_refresh_reordering_mpdus(struct rt_rtmp_adapter *pAd,
|
|
struct rt_ba_rec_entry *pBAEntry)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk;
|
|
|
|
NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
|
|
|
|
/* dequeue in-order frame from reodering list */
|
|
while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) {
|
|
/* pass this frame up */
|
|
ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
|
|
|
|
pBAEntry->LastIndSeq = mpdu_blk->Sequence;
|
|
ba_mpdu_blk_free(pAd, mpdu_blk);
|
|
|
|
/* update last indicated sequence */
|
|
}
|
|
ASSERT(pBAEntry->list.qlen == 0);
|
|
pBAEntry->LastIndSeq = RESET_RCV_SEQ;
|
|
NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
|
|
}
|
|
|
|
/*static */
|
|
void ba_flush_reordering_timeout_mpdus(struct rt_rtmp_adapter *pAd,
|
|
struct rt_ba_rec_entry *pBAEntry,
|
|
unsigned long Now32)
|
|
{
|
|
u16 Sequence;
|
|
|
|
/* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && */
|
|
/* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| */
|
|
/* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && */
|
|
/* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) */
|
|
if (RTMP_TIME_AFTER
|
|
((unsigned long)Now32,
|
|
(unsigned long)(pBAEntry->LastIndSeqAtTimer +
|
|
(MAX_REORDERING_PACKET_TIMEOUT / 6)))
|
|
&& (pBAEntry->list.qlen > 1)
|
|
) {
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ",
|
|
pBAEntry->list.qlen, Now32,
|
|
(pBAEntry->LastIndSeqAtTimer),
|
|
(int)((long)Now32 -
|
|
(long)(pBAEntry->LastIndSeqAtTimer)),
|
|
MAX_REORDERING_PACKET_TIMEOUT, pBAEntry->LastIndSeq));
|
|
ba_refresh_reordering_mpdus(pAd, pBAEntry);
|
|
pBAEntry->LastIndSeqAtTimer = Now32;
|
|
} else
|
|
if (RTMP_TIME_AFTER
|
|
((unsigned long)Now32,
|
|
(unsigned long)(pBAEntry->LastIndSeqAtTimer +
|
|
(REORDERING_PACKET_TIMEOUT)))
|
|
&& (pBAEntry->list.qlen > 0)
|
|
) {
|
|
/* */
|
|
/* force LastIndSeq to shift to LastIndSeq+1 */
|
|
/* */
|
|
Sequence = (pBAEntry->LastIndSeq + 1) & MAXSEQ;
|
|
ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
|
|
pBAEntry->LastIndSeqAtTimer = Now32;
|
|
pBAEntry->LastIndSeq = Sequence;
|
|
/* */
|
|
/* indicate in-order mpdus */
|
|
/* */
|
|
Sequence =
|
|
ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry,
|
|
Sequence);
|
|
if (Sequence != RESET_RCV_SEQ) {
|
|
pBAEntry->LastIndSeq = Sequence;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_OFF,
|
|
("%x, flush one!\n", pBAEntry->LastIndSeq));
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* generate ADDBA request to
|
|
* set up BA agreement
|
|
*/
|
|
void BAOriSessionSetUp(struct rt_rtmp_adapter *pAd,
|
|
struct rt_mac_table_entry *pEntry,
|
|
u8 TID,
|
|
u16 TimeOut,
|
|
unsigned long DelayTime, IN BOOLEAN isForced)
|
|
{
|
|
/*struct rt_mlme_addba_req AddbaReq; */
|
|
struct rt_ba_ori_entry *pBAEntry = NULL;
|
|
u16 Idx;
|
|
BOOLEAN Cancelled;
|
|
|
|
if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE)
|
|
&& (isForced == FALSE))
|
|
return;
|
|
|
|
/* if this entry is limited to use legacy tx mode, it doesn't generate BA. */
|
|
if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
|
|
return;
|
|
|
|
if ((pEntry->BADeclineBitmap & (1 << TID)) && (isForced == FALSE)) {
|
|
/* try again after 3 secs */
|
|
DelayTime = 3000;
|
|
/* DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n")); */
|
|
/* return; */
|
|
}
|
|
|
|
Idx = pEntry->BAOriWcidArray[TID];
|
|
if (Idx == 0) {
|
|
/* allocate a BA session */
|
|
pBAEntry = BATableAllocOriEntry(pAd, &Idx);
|
|
if (pBAEntry == NULL) {
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
|
|
return;
|
|
}
|
|
} else {
|
|
pBAEntry = &pAd->BATable.BAOriEntry[Idx];
|
|
}
|
|
|
|
if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) {
|
|
return;
|
|
}
|
|
|
|
pEntry->BAOriWcidArray[TID] = Idx;
|
|
|
|
/* Initialize BA session */
|
|
pBAEntry->ORI_BA_Status = Originator_WaitRes;
|
|
pBAEntry->Wcid = pEntry->Aid;
|
|
pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
|
|
pBAEntry->Sequence = BA_ORI_INIT_SEQ;
|
|
pBAEntry->Token = 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0 */
|
|
pBAEntry->TID = TID;
|
|
pBAEntry->TimeOutValue = TimeOut;
|
|
pBAEntry->pAdapter = pAd;
|
|
|
|
if (!(pEntry->TXBAbitmap & (1 << TID))) {
|
|
RTMPInitTimer(pAd, &pBAEntry->ORIBATimer,
|
|
GET_TIMER_FUNCTION(BAOriSessionSetupTimeout),
|
|
pBAEntry, FALSE);
|
|
} else
|
|
RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
|
|
|
|
/* set timer to send ADDBA request */
|
|
RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
|
|
}
|
|
|
|
void BAOriSessionAdd(struct rt_rtmp_adapter *pAd,
|
|
struct rt_mac_table_entry *pEntry, struct rt_frame_addba_rsp * pFrame)
|
|
{
|
|
struct rt_ba_ori_entry *pBAEntry = NULL;
|
|
BOOLEAN Cancelled;
|
|
u8 TID;
|
|
u16 Idx;
|
|
u8 *pOutBuffer2 = NULL;
|
|
int NStatus;
|
|
unsigned long FrameLen;
|
|
struct rt_frame_bar FrameBar;
|
|
|
|
TID = pFrame->BaParm.TID;
|
|
Idx = pEntry->BAOriWcidArray[TID];
|
|
pBAEntry = &pAd->BATable.BAOriEntry[Idx];
|
|
|
|
/* Start fill in parameters. */
|
|
if ((Idx != 0) && (pBAEntry->TID == TID)
|
|
&& (pBAEntry->ORI_BA_Status == Originator_WaitRes)) {
|
|
pBAEntry->BAWinSize =
|
|
min(pBAEntry->BAWinSize, ((u8)pFrame->BaParm.BufSize));
|
|
BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
|
|
|
|
pBAEntry->TimeOutValue = pFrame->TimeOutValue;
|
|
pBAEntry->ORI_BA_Status = Originator_Done;
|
|
pAd->BATable.numDoneOriginator++;
|
|
|
|
/* reset sequence number */
|
|
pBAEntry->Sequence = BA_ORI_INIT_SEQ;
|
|
/* Set Bitmap flag. */
|
|
pEntry->TXBAbitmap |= (1 << TID);
|
|
RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
|
|
|
|
pBAEntry->ORIBATimer.TimerValue = 0; /*pFrame->TimeOutValue; */
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n",
|
|
__func__, pEntry->TXBAbitmap, pBAEntry->BAWinSize,
|
|
pBAEntry->ORIBATimer.TimerValue));
|
|
|
|
/* SEND BAR ; */
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory */
|
|
if (NStatus != NDIS_STATUS_SUCCESS) {
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("BA - BAOriSessionAdd() allocate memory failed \n"));
|
|
return;
|
|
}
|
|
|
|
BarHeaderInit(pAd, &FrameBar,
|
|
pAd->MacTab.Content[pBAEntry->Wcid].Addr,
|
|
pAd->CurrentAddress);
|
|
|
|
FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function. */
|
|
FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; /* make sure sequence not clear in DEL funciton. */
|
|
FrameBar.BarControl.TID = pBAEntry->TID; /* make sure sequence not clear in DEL funciton. */
|
|
MakeOutgoingFrame(pOutBuffer2, &FrameLen,
|
|
sizeof(struct rt_frame_bar), &FrameBar, END_OF_ARGS);
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer2);
|
|
|
|
if (pBAEntry->ORIBATimer.TimerValue)
|
|
RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); /* in mSec */
|
|
}
|
|
}
|
|
|
|
BOOLEAN BARecSessionAdd(struct rt_rtmp_adapter *pAd,
|
|
struct rt_mac_table_entry *pEntry, struct rt_frame_addba_req * pFrame)
|
|
{
|
|
struct rt_ba_rec_entry *pBAEntry = NULL;
|
|
BOOLEAN Status = TRUE;
|
|
BOOLEAN Cancelled;
|
|
u16 Idx;
|
|
u8 TID;
|
|
u8 BAWinSize;
|
|
/*u32 Value; */
|
|
/*u32 offset; */
|
|
|
|
ASSERT(pEntry);
|
|
|
|
/* find TID */
|
|
TID = pFrame->BaParm.TID;
|
|
|
|
BAWinSize =
|
|
min(((u8)pFrame->BaParm.BufSize),
|
|
(u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
|
|
|
|
/* Intel patch */
|
|
if (BAWinSize == 0) {
|
|
BAWinSize = 64;
|
|
}
|
|
|
|
Idx = pEntry->BARecWcidArray[TID];
|
|
|
|
if (Idx == 0) {
|
|
pBAEntry = BATableAllocRecEntry(pAd, &Idx);
|
|
} else {
|
|
pBAEntry = &pAd->BATable.BARecEntry[Idx];
|
|
/* flush all pending reordering mpdus */
|
|
ba_refresh_reordering_mpdus(pAd, pBAEntry);
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__,
|
|
pAd->BATable.numAsRecipient, Idx, pFrame->BaParm.BufSize,
|
|
BAWinSize));
|
|
|
|
/* Start fill in parameters. */
|
|
if (pBAEntry != NULL) {
|
|
ASSERT(pBAEntry->list.qlen == 0);
|
|
|
|
pBAEntry->REC_BA_Status = Recipient_HandleRes;
|
|
pBAEntry->BAWinSize = BAWinSize;
|
|
pBAEntry->Wcid = pEntry->Aid;
|
|
pBAEntry->TID = TID;
|
|
pBAEntry->TimeOutValue = pFrame->TimeOutValue;
|
|
pBAEntry->REC_BA_Status = Recipient_Accept;
|
|
/* initial sequence number */
|
|
pBAEntry->LastIndSeq = RESET_RCV_SEQ; /*pFrame->BaStartSeq.field.StartSeq; */
|
|
|
|
DBGPRINT(RT_DEBUG_OFF,
|
|
("Start Seq = %08x\n",
|
|
pFrame->BaStartSeq.field.StartSeq));
|
|
|
|
if (pEntry->RXBAbitmap & (1 << TID)) {
|
|
RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
|
|
} else {
|
|
RTMPInitTimer(pAd, &pBAEntry->RECBATimer,
|
|
GET_TIMER_FUNCTION
|
|
(BARecSessionIdleTimeout), pBAEntry,
|
|
TRUE);
|
|
}
|
|
|
|
/* Set Bitmap flag. */
|
|
pEntry->RXBAbitmap |= (1 << TID);
|
|
pEntry->BARecWcidArray[TID] = Idx;
|
|
|
|
pEntry->BADeclineBitmap &= ~(1 << TID);
|
|
|
|
/* Set BA session mask in WCID table. */
|
|
RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
|
|
pEntry->Aid, pEntry->RXBAbitmap,
|
|
pEntry->BARecWcidArray[TID]));
|
|
} else {
|
|
Status = FALSE;
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
|
|
PRINT_MAC(pEntry->Addr), TID));
|
|
}
|
|
return (Status);
|
|
}
|
|
|
|
struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx)
|
|
{
|
|
int i;
|
|
struct rt_ba_rec_entry *pBAEntry = NULL;
|
|
|
|
NdisAcquireSpinLock(&pAd->BATabLock);
|
|
|
|
if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) {
|
|
DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n",
|
|
pAd->BATable.numAsRecipient,
|
|
MAX_BARECI_SESSION));
|
|
goto done;
|
|
}
|
|
/* reserve idx 0 to identify BAWcidArray[TID] as empty */
|
|
for (i = 1; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
|
|
pBAEntry = &pAd->BATable.BARecEntry[i];
|
|
if ((pBAEntry->REC_BA_Status == Recipient_NONE)) {
|
|
/* get one */
|
|
pAd->BATable.numAsRecipient++;
|
|
pBAEntry->REC_BA_Status = Recipient_USED;
|
|
*Idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
done:
|
|
NdisReleaseSpinLock(&pAd->BATabLock);
|
|
return pBAEntry;
|
|
}
|
|
|
|
struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx)
|
|
{
|
|
int i;
|
|
struct rt_ba_ori_entry *pBAEntry = NULL;
|
|
|
|
NdisAcquireSpinLock(&pAd->BATabLock);
|
|
|
|
if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) {
|
|
goto done;
|
|
}
|
|
/* reserve idx 0 to identify BAWcidArray[TID] as empty */
|
|
for (i = 1; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
|
|
pBAEntry = &pAd->BATable.BAOriEntry[i];
|
|
if ((pBAEntry->ORI_BA_Status == Originator_NONE)) {
|
|
/* get one */
|
|
pAd->BATable.numAsOriginator++;
|
|
pBAEntry->ORI_BA_Status = Originator_USED;
|
|
pBAEntry->pAdapter = pAd;
|
|
*Idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
done:
|
|
NdisReleaseSpinLock(&pAd->BATabLock);
|
|
return pBAEntry;
|
|
}
|
|
|
|
void BATableFreeOriEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx)
|
|
{
|
|
struct rt_ba_ori_entry *pBAEntry = NULL;
|
|
struct rt_mac_table_entry *pEntry;
|
|
|
|
if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
|
|
return;
|
|
|
|
pBAEntry = &pAd->BATable.BAOriEntry[Idx];
|
|
|
|
if (pBAEntry->ORI_BA_Status != Originator_NONE) {
|
|
pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
|
|
pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
|
|
|
|
NdisAcquireSpinLock(&pAd->BATabLock);
|
|
if (pBAEntry->ORI_BA_Status == Originator_Done) {
|
|
pAd->BATable.numDoneOriginator -= 1;
|
|
pEntry->TXBAbitmap &= (~(1 << (pBAEntry->TID)));
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("BATableFreeOriEntry numAsOriginator= %ld\n",
|
|
pAd->BATable.numAsRecipient));
|
|
/* Erase Bitmap flag. */
|
|
}
|
|
|
|
ASSERT(pAd->BATable.numAsOriginator != 0);
|
|
|
|
pAd->BATable.numAsOriginator -= 1;
|
|
|
|
pBAEntry->ORI_BA_Status = Originator_NONE;
|
|
pBAEntry->Token = 0;
|
|
NdisReleaseSpinLock(&pAd->BATabLock);
|
|
}
|
|
}
|
|
|
|
void BATableFreeRecEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx)
|
|
{
|
|
struct rt_ba_rec_entry *pBAEntry = NULL;
|
|
struct rt_mac_table_entry *pEntry;
|
|
|
|
if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
|
|
return;
|
|
|
|
pBAEntry = &pAd->BATable.BARecEntry[Idx];
|
|
|
|
if (pBAEntry->REC_BA_Status != Recipient_NONE) {
|
|
pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
|
|
pEntry->BARecWcidArray[pBAEntry->TID] = 0;
|
|
|
|
NdisAcquireSpinLock(&pAd->BATabLock);
|
|
|
|
ASSERT(pAd->BATable.numAsRecipient != 0);
|
|
|
|
pAd->BATable.numAsRecipient -= 1;
|
|
|
|
pBAEntry->REC_BA_Status = Recipient_NONE;
|
|
NdisReleaseSpinLock(&pAd->BATabLock);
|
|
}
|
|
}
|
|
|
|
void BAOriSessionTearDown(struct rt_rtmp_adapter *pAd,
|
|
u8 Wcid,
|
|
u8 TID,
|
|
IN BOOLEAN bPassive, IN BOOLEAN bForceSend)
|
|
{
|
|
unsigned long Idx = 0;
|
|
struct rt_ba_ori_entry *pBAEntry;
|
|
BOOLEAN Cancelled;
|
|
|
|
if (Wcid >= MAX_LEN_OF_MAC_TABLE) {
|
|
return;
|
|
}
|
|
/* */
|
|
/* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */
|
|
/* */
|
|
Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
|
|
if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) {
|
|
if (bForceSend == TRUE) {
|
|
/* force send specified TID DelBA */
|
|
struct rt_mlme_delba_req DelbaReq;
|
|
struct rt_mlme_queue_elem *Elem =
|
|
(struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem),
|
|
MEM_ALLOC_FLAG);
|
|
if (Elem != NULL) {
|
|
NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
|
|
NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem));
|
|
|
|
COPY_MAC_ADDR(DelbaReq.Addr,
|
|
pAd->MacTab.Content[Wcid].Addr);
|
|
DelbaReq.Wcid = Wcid;
|
|
DelbaReq.TID = TID;
|
|
DelbaReq.Initiator = ORIGINATOR;
|
|
Elem->MsgLen = sizeof(DelbaReq);
|
|
NdisMoveMemory(Elem->Msg, &DelbaReq,
|
|
sizeof(DelbaReq));
|
|
MlmeDELBAAction(pAd, Elem);
|
|
kfree(Elem);
|
|
} else {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s(bForceSend):alloc memory failed!\n",
|
|
__func__));
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
|
|
|
|
pBAEntry = &pAd->BATable.BAOriEntry[Idx];
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx,
|
|
Wcid, TID, pBAEntry->ORI_BA_Status));
|
|
/* */
|
|
/* Prepare DelBA action frame and send to the peer. */
|
|
/* */
|
|
if ((bPassive == FALSE) && (TID == pBAEntry->TID)
|
|
&& (pBAEntry->ORI_BA_Status == Originator_Done)) {
|
|
struct rt_mlme_delba_req DelbaReq;
|
|
struct rt_mlme_queue_elem *Elem =
|
|
(struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem),
|
|
MEM_ALLOC_FLAG);
|
|
if (Elem != NULL) {
|
|
NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
|
|
NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem));
|
|
|
|
COPY_MAC_ADDR(DelbaReq.Addr,
|
|
pAd->MacTab.Content[Wcid].Addr);
|
|
DelbaReq.Wcid = Wcid;
|
|
DelbaReq.TID = pBAEntry->TID;
|
|
DelbaReq.Initiator = ORIGINATOR;
|
|
Elem->MsgLen = sizeof(DelbaReq);
|
|
NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
|
|
MlmeDELBAAction(pAd, Elem);
|
|
kfree(Elem);
|
|
} else {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s():alloc memory failed!\n", __func__));
|
|
return;
|
|
}
|
|
}
|
|
RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
|
|
BATableFreeOriEntry(pAd, Idx);
|
|
|
|
if (bPassive) {
|
|
/*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); */
|
|
}
|
|
}
|
|
|
|
void BARecSessionTearDown(struct rt_rtmp_adapter *pAd,
|
|
u8 Wcid, u8 TID, IN BOOLEAN bPassive)
|
|
{
|
|
unsigned long Idx = 0;
|
|
struct rt_ba_rec_entry *pBAEntry;
|
|
|
|
if (Wcid >= MAX_LEN_OF_MAC_TABLE) {
|
|
return;
|
|
}
|
|
/* */
|
|
/* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */
|
|
/* */
|
|
Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
|
|
if (Idx == 0)
|
|
return;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
|
|
|
|
pBAEntry = &pAd->BATable.BARecEntry[Idx];
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx,
|
|
Wcid, TID, pBAEntry->REC_BA_Status));
|
|
/* */
|
|
/* Prepare DelBA action frame and send to the peer. */
|
|
/* */
|
|
if ((TID == pBAEntry->TID)
|
|
&& (pBAEntry->REC_BA_Status == Recipient_Accept)) {
|
|
struct rt_mlme_delba_req DelbaReq;
|
|
BOOLEAN Cancelled;
|
|
/*unsigned long offset; */
|
|
/*u32 VALUE; */
|
|
|
|
RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
|
|
|
|
/* */
|
|
/* 1. Send DELBA Action Frame */
|
|
/* */
|
|
if (bPassive == FALSE) {
|
|
struct rt_mlme_queue_elem *Elem =
|
|
(struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem),
|
|
MEM_ALLOC_FLAG);
|
|
if (Elem != NULL) {
|
|
NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
|
|
NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem));
|
|
|
|
COPY_MAC_ADDR(DelbaReq.Addr,
|
|
pAd->MacTab.Content[Wcid].Addr);
|
|
DelbaReq.Wcid = Wcid;
|
|
DelbaReq.TID = TID;
|
|
DelbaReq.Initiator = RECIPIENT;
|
|
Elem->MsgLen = sizeof(DelbaReq);
|
|
NdisMoveMemory(Elem->Msg, &DelbaReq,
|
|
sizeof(DelbaReq));
|
|
MlmeDELBAAction(pAd, Elem);
|
|
kfree(Elem);
|
|
} else {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("%s():alloc memory failed!\n",
|
|
__func__));
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* */
|
|
/* 2. Free resource of BA session */
|
|
/* */
|
|
/* flush all pending reordering mpdus */
|
|
ba_refresh_reordering_mpdus(pAd, pBAEntry);
|
|
|
|
NdisAcquireSpinLock(&pAd->BATabLock);
|
|
|
|
/* Erase Bitmap flag. */
|
|
pBAEntry->LastIndSeq = RESET_RCV_SEQ;
|
|
pBAEntry->BAWinSize = 0;
|
|
/* Erase Bitmap flag at software mactable */
|
|
pAd->MacTab.Content[Wcid].RXBAbitmap &=
|
|
(~(1 << (pBAEntry->TID)));
|
|
pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
|
|
|
|
RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
|
|
|
|
NdisReleaseSpinLock(&pAd->BATabLock);
|
|
|
|
}
|
|
|
|
BATableFreeRecEntry(pAd, Idx);
|
|
}
|
|
|
|
void BASessionTearDownALL(struct rt_rtmp_adapter *pAd, u8 Wcid)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < NUM_OF_TID; i++) {
|
|
BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
|
|
BARecSessionTearDown(pAd, Wcid, i, FALSE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Retry sending ADDBA Reqest.
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
Parametrs:
|
|
p8023Header: if this is already 802.3 format, p8023Header is NULL
|
|
|
|
Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
|
|
FALSE , then continue indicaterx at this moment.
|
|
==========================================================================
|
|
*/
|
|
void BAOriSessionSetupTimeout(void *SystemSpecific1,
|
|
void *FunctionContext,
|
|
void *SystemSpecific2,
|
|
void *SystemSpecific3)
|
|
{
|
|
struct rt_ba_ori_entry *pBAEntry = (struct rt_ba_ori_entry *)FunctionContext;
|
|
struct rt_mac_table_entry *pEntry;
|
|
struct rt_rtmp_adapter *pAd;
|
|
|
|
if (pBAEntry == NULL)
|
|
return;
|
|
|
|
pAd = pBAEntry->pAdapter;
|
|
|
|
{
|
|
/* Do nothing if monitor mode is on */
|
|
if (MONITOR_ON(pAd))
|
|
return;
|
|
}
|
|
|
|
pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
|
|
|
|
if ((pBAEntry->ORI_BA_Status == Originator_WaitRes)
|
|
&& (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) {
|
|
struct rt_mlme_addba_req AddbaReq;
|
|
|
|
NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
|
|
COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
|
|
AddbaReq.Wcid = (u8)(pEntry->Aid);
|
|
AddbaReq.TID = pBAEntry->TID;
|
|
AddbaReq.BaBufSize =
|
|
pAd->CommonCfg.BACapability.field.RxBAWinLimit;
|
|
AddbaReq.TimeOutValue = 0;
|
|
AddbaReq.Token = pBAEntry->Token;
|
|
MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE,
|
|
sizeof(struct rt_mlme_addba_req), (void *)& AddbaReq);
|
|
RTMP_MLME_HANDLER(pAd);
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("BA Ori Session Timeout(%d) : Send ADD BA again\n",
|
|
pBAEntry->Token));
|
|
|
|
pBAEntry->Token++;
|
|
RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
|
|
} else {
|
|
BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Retry sending ADDBA Reqest.
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
Parametrs:
|
|
p8023Header: if this is already 802.3 format, p8023Header is NULL
|
|
|
|
Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
|
|
FALSE , then continue indicaterx at this moment.
|
|
==========================================================================
|
|
*/
|
|
void BARecSessionIdleTimeout(void *SystemSpecific1,
|
|
void *FunctionContext,
|
|
void *SystemSpecific2, void *SystemSpecific3)
|
|
{
|
|
|
|
struct rt_ba_rec_entry *pBAEntry = (struct rt_ba_rec_entry *)FunctionContext;
|
|
struct rt_rtmp_adapter *pAd;
|
|
unsigned long Now32;
|
|
|
|
if (pBAEntry == NULL)
|
|
return;
|
|
|
|
if ((pBAEntry->REC_BA_Status == Recipient_Accept)) {
|
|
NdisGetSystemUpTime(&Now32);
|
|
|
|
if (RTMP_TIME_AFTER
|
|
((unsigned long)Now32,
|
|
(unsigned long)(pBAEntry->LastIndSeqAtTimer +
|
|
REC_BA_SESSION_IDLE_TIMEOUT))) {
|
|
pAd = pBAEntry->pAdapter;
|
|
/* flush all pending reordering mpdus */
|
|
ba_refresh_reordering_mpdus(pAd, pBAEntry);
|
|
DBGPRINT(RT_DEBUG_OFF,
|
|
("%ld: REC BA session Timeout\n", Now32));
|
|
}
|
|
}
|
|
}
|
|
|
|
void PeerAddBAReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
|
|
{
|
|
/* 7.4.4.1 */
|
|
/*unsigned long Idx; */
|
|
u8 Status = 1;
|
|
u8 pAddr[6];
|
|
struct rt_frame_addba_rsp ADDframe;
|
|
u8 *pOutBuffer = NULL;
|
|
int NStatus;
|
|
struct rt_frame_addba_req * pAddreqFrame = NULL;
|
|
/*u8 BufSize; */
|
|
unsigned long FrameLen;
|
|
unsigned long *ptemp;
|
|
struct rt_mac_table_entry *pMacEntry;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid));
|
|
|
|
/*hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); */
|
|
|
|
/*ADDBA Request from unknown peer, ignore this. */
|
|
if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
|
|
return;
|
|
|
|
pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
|
|
DBGPRINT(RT_DEBUG_TRACE, ("BA - PeerAddBAReqAction----> \n"));
|
|
ptemp = (unsigned long *)Elem->Msg;
|
|
/*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))); */
|
|
|
|
if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) {
|
|
|
|
if ((pAd->CommonCfg.bBADecline == FALSE)
|
|
&& IS_HT_STA(pMacEntry)) {
|
|
pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]);
|
|
DBGPRINT(RT_DEBUG_OFF,
|
|
("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid));
|
|
if (BARecSessionAdd
|
|
(pAd, &pAd->MacTab.Content[Elem->Wcid],
|
|
pAddreqFrame))
|
|
Status = 0;
|
|
else
|
|
Status = 38; /* more parameters have invalid values */
|
|
} else {
|
|
Status = 37; /* the request has been declined. */
|
|
}
|
|
}
|
|
|
|
if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
|
|
ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
|
|
|
|
pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]);
|
|
/* 2. Always send back ADDBA Response */
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */
|
|
if (NStatus != NDIS_STATUS_SUCCESS) {
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("ACTION - PeerBAAction() allocate memory failed \n"));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(&ADDframe, sizeof(struct rt_frame_addba_rsp));
|
|
|
|
/* 2-1. Prepare ADDBA Response frame. */
|
|
{
|
|
if (ADHOC_ON(pAd))
|
|
ActHeaderInit(pAd, &ADDframe.Hdr, pAddr,
|
|
pAd->CurrentAddress,
|
|
pAd->CommonCfg.Bssid);
|
|
else
|
|
ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid,
|
|
pAd->CurrentAddress, pAddr);
|
|
}
|
|
|
|
ADDframe.Category = CATEGORY_BA;
|
|
ADDframe.Action = ADDBA_RESP;
|
|
ADDframe.Token = pAddreqFrame->Token;
|
|
/* What is the Status code?? need to check. */
|
|
ADDframe.StatusCode = Status;
|
|
ADDframe.BaParm.BAPolicy = IMMED_BA;
|
|
ADDframe.BaParm.AMSDUSupported = 0;
|
|
ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
|
|
ADDframe.BaParm.BufSize =
|
|
min(((u8)pAddreqFrame->BaParm.BufSize),
|
|
(u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
|
|
if (ADDframe.BaParm.BufSize == 0) {
|
|
ADDframe.BaParm.BufSize = 64;
|
|
}
|
|
ADDframe.TimeOutValue = 0; /*pAddreqFrame->TimeOutValue; */
|
|
|
|
*(u16 *) (&ADDframe.BaParm) =
|
|
cpu2le16(*(u16 *) (&ADDframe.BaParm));
|
|
ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
|
|
ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
|
|
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(struct rt_frame_addba_rsp), &ADDframe, END_OF_ARGS);
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid,
|
|
ADDframe.BaParm.TID, ADDframe.BaParm.BufSize));
|
|
}
|
|
|
|
void PeerAddBARspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
|
|
{
|
|
/*u8 Idx, i; */
|
|
/*u8 * pOutBuffer = NULL; */
|
|
struct rt_frame_addba_rsp * pFrame = NULL;
|
|
/*struct rt_ba_ori_entry *pBAEntry; */
|
|
|
|
/*ADDBA Response from unknown peer, ignore this. */
|
|
if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
|
|
return;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid));
|
|
|
|
/*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); */
|
|
|
|
if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) {
|
|
pFrame = (struct rt_frame_addba_rsp *) (&Elem->Msg[0]);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("\t\t StatusCode = %d\n", pFrame->StatusCode));
|
|
switch (pFrame->StatusCode) {
|
|
case 0:
|
|
/* I want a BAsession with this peer as an originator. */
|
|
BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid],
|
|
pFrame);
|
|
break;
|
|
default:
|
|
/* check status == USED ??? */
|
|
BAOriSessionTearDown(pAd, Elem->Wcid,
|
|
pFrame->BaParm.TID, TRUE, FALSE);
|
|
break;
|
|
}
|
|
/* Rcv Decline StatusCode */
|
|
if ((pFrame->StatusCode == 37)
|
|
|| ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd)
|
|
&& (pFrame->StatusCode != 0))
|
|
) {
|
|
pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |=
|
|
1 << pFrame->BaParm.TID;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PeerDelBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
|
|
{
|
|
/*u8 Idx; */
|
|
/*u8 * pOutBuffer = NULL; */
|
|
struct rt_frame_delba_req * pDelFrame = NULL;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s ==>\n", __func__));
|
|
/*DELBA Request from unknown peer, ignore this. */
|
|
if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) {
|
|
pDelFrame = (struct rt_frame_delba_req *) (&Elem->Msg[0]);
|
|
if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) {
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("BA - PeerDelBAAction----> ORIGINATOR\n"));
|
|
BARecSessionTearDown(pAd, Elem->Wcid,
|
|
pDelFrame->DelbaParm.TID, TRUE);
|
|
} else {
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n",
|
|
pDelFrame->ReasonCode));
|
|
/*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); */
|
|
BAOriSessionTearDown(pAd, Elem->Wcid,
|
|
pDelFrame->DelbaParm.TID, TRUE,
|
|
FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOLEAN CntlEnqueueForRecv(struct rt_rtmp_adapter *pAd,
|
|
unsigned long Wcid,
|
|
unsigned long MsgLen, struct rt_frame_ba_req * pMsg)
|
|
{
|
|
struct rt_frame_ba_req * pFrame = pMsg;
|
|
/*PRTMP_REORDERBUF pBuffer; */
|
|
/*PRTMP_REORDERBUF pDmaBuf; */
|
|
struct rt_ba_rec_entry *pBAEntry;
|
|
/*BOOLEAN Result; */
|
|
unsigned long Idx;
|
|
/*u8 NumRxPkt; */
|
|
u8 TID; /*, i; */
|
|
|
|
TID = (u8)pFrame->BARControl.TID;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID));
|
|
/*hex_dump("BAR", (char *)pFrame, MsgLen); */
|
|
/* Do nothing if the driver is starting halt state. */
|
|
/* This might happen when timer already been fired before cancel timer with mlmehalt */
|
|
if (RTMP_TEST_FLAG
|
|
(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
|
|
return FALSE;
|
|
|
|
/* First check the size, it MUST not exceed the mlme queue size */
|
|
if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
|
|
DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
|
|
return FALSE;
|
|
} else if (MsgLen != sizeof(struct rt_frame_ba_req)) {
|
|
DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
|
|
return FALSE;
|
|
} else if (MsgLen != sizeof(struct rt_frame_ba_req)) {
|
|
DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
|
|
return FALSE;
|
|
}
|
|
|
|
if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) {
|
|
/* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. */
|
|
Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
|
|
pBAEntry = &pAd->BATable.BARecEntry[Idx];
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,
|
|
("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID,
|
|
pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq));
|
|
|
|
if (SEQ_SMALLER
|
|
(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq,
|
|
MAXSEQ)) {
|
|
/*DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); */
|
|
ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry,
|
|
pFrame->BAStartingSeq.field.
|
|
StartSeq);
|
|
pBAEntry->LastIndSeq =
|
|
(pFrame->BAStartingSeq.field.StartSeq ==
|
|
0) ? MAXSEQ : (pFrame->BAStartingSeq.field.StartSeq - 1);
|
|
}
|
|
/*ba_refresh_reordering_mpdus(pAd, pBAEntry); */
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
Description : Send PSMP Action frame If PSMP mode switches.
|
|
*/
|
|
void SendPSMPAction(struct rt_rtmp_adapter *pAd, u8 Wcid, u8 Psmp)
|
|
{
|
|
u8 *pOutBuffer = NULL;
|
|
int NStatus;
|
|
/*unsigned long Idx; */
|
|
struct rt_frame_psmp_action Frame;
|
|
unsigned long FrameLen;
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */
|
|
if (NStatus != NDIS_STATUS_SUCCESS) {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
("BA - MlmeADDBAAction() allocate memory failed \n"));
|
|
return;
|
|
}
|
|
|
|
ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid,
|
|
pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
|
|
|
|
Frame.Category = CATEGORY_HT;
|
|
Frame.Action = SMPS_ACTION;
|
|
switch (Psmp) {
|
|
case MMPS_ENABLE:
|
|
#ifdef RT30xx
|
|
if (IS_RT30xx(pAd)
|
|
&& (pAd->Antenna.field.RxPath > 1
|
|
|| pAd->Antenna.field.TxPath > 1)) {
|
|
RTMP_ASIC_MMPS_DISABLE(pAd);
|
|
}
|
|
#endif /* RT30xx // */
|
|
Frame.Psmp = 0;
|
|
break;
|
|
case MMPS_DYNAMIC:
|
|
Frame.Psmp = 3;
|
|
break;
|
|
case MMPS_STATIC:
|
|
#ifdef RT30xx
|
|
if (IS_RT30xx(pAd)
|
|
&& (pAd->Antenna.field.RxPath > 1
|
|
|| pAd->Antenna.field.TxPath > 1)) {
|
|
RTMP_ASIC_MMPS_ENABLE(pAd);
|
|
}
|
|
#endif /* RT30xx // */
|
|
Frame.Psmp = 1;
|
|
break;
|
|
}
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(struct rt_frame_psmp_action), &Frame, END_OF_ARGS);
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
DBGPRINT(RT_DEBUG_ERROR, ("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
|
|
}
|
|
|
|
#define RADIO_MEASUREMENT_REQUEST_ACTION 0
|
|
|
|
struct PACKED rt_beacon_request {
|
|
u8 RegulatoryClass;
|
|
u8 ChannelNumber;
|
|
u16 RandomInterval;
|
|
u16 MeasurementDuration;
|
|
u8 MeasurementMode;
|
|
u8 BSSID[MAC_ADDR_LEN];
|
|
u8 ReportingCondition;
|
|
u8 Threshold;
|
|
u8 SSIDIE[2]; /* 2 byte */
|
|
};
|
|
|
|
struct PACKED rt_measurement_req {
|
|
u8 ID;
|
|
u8 Length;
|
|
u8 Token;
|
|
u8 RequestMode;
|
|
u8 Type;
|
|
};
|
|
|
|
void convert_reordering_packet_to_preAMSDU_or_802_3_packet(struct rt_rtmp_adapter *pAd,
|
|
struct rt_rx_blk *pRxBlk,
|
|
u8
|
|
FromWhichBSSID)
|
|
{
|
|
void *pRxPkt;
|
|
u8 Header802_3[LENGTH_802_3];
|
|
|
|
/* 1. get 802.3 Header */
|
|
/* 2. remove LLC */
|
|
/* a. pointer pRxBlk->pData to payload */
|
|
/* b. modify pRxBlk->DataSize */
|
|
|
|
RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
|
|
|
|
ASSERT(pRxBlk->pRxPacket);
|
|
pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
|
|
|
|
SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID));
|
|
SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData);
|
|
SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize);
|
|
SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize);
|
|
|
|
/* */
|
|
/* copy 802.3 header, if necessary */
|
|
/* */
|
|
if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
|
|
{
|
|
#ifdef LINUX
|
|
NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3),
|
|
Header802_3, LENGTH_802_3);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
|
|
do \
|
|
{ \
|
|
if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
|
|
{ \
|
|
Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
|
|
} \
|
|
else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
|
|
{ \
|
|
Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
|
|
} \
|
|
else \
|
|
{ \
|
|
Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
|
|
} \
|
|
} while (0);
|
|
|
|
static void ba_enqueue_reordering_packet(struct rt_rtmp_adapter *pAd,
|
|
struct rt_ba_rec_entry *pBAEntry,
|
|
struct rt_rx_blk *pRxBlk,
|
|
u8 FromWhichBSSID)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk;
|
|
u16 Sequence = (u16)pRxBlk->pHeader->Sequence;
|
|
|
|
mpdu_blk = ba_mpdu_blk_alloc(pAd);
|
|
if ((mpdu_blk != NULL) && (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) {
|
|
/* Write RxD buffer address & allocated buffer length */
|
|
NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
|
|
|
|
mpdu_blk->Sequence = Sequence;
|
|
|
|
mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
|
|
|
|
convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd,
|
|
pRxBlk,
|
|
FromWhichBSSID);
|
|
|
|
STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
|
|
|
|
/* */
|
|
/* it is necessary for reordering packet to record */
|
|
/* which BSS it come from */
|
|
/* */
|
|
RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
|
|
|
|
mpdu_blk->pPacket = pRxBlk->pRxPacket;
|
|
|
|
if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk)
|
|
== FALSE) {
|
|
/* had been already within reordering list */
|
|
/* don't indicate */
|
|
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
|
|
NDIS_STATUS_SUCCESS);
|
|
ba_mpdu_blk_free(pAd, mpdu_blk);
|
|
}
|
|
|
|
ASSERT((0 <= pBAEntry->list.qlen)
|
|
&& (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
|
|
NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
|
|
} else {
|
|
DBGPRINT(RT_DEBUG_ERROR,
|
|
(" (%d) Can't allocate reordering mpdu blk\n",
|
|
pBAEntry->list.qlen));
|
|
|
|
/*
|
|
* flush all pending reordering mpdus
|
|
* and receving mpdu to upper layer
|
|
* make tcp/ip to take care reordering mechanism
|
|
*/
|
|
/*ba_refresh_reordering_mpdus(pAd, pBAEntry); */
|
|
ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
|
|
|
|
pBAEntry->LastIndSeq = Sequence;
|
|
INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
|
|
}
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Indicate this packet to upper layer or put it into reordering buffer
|
|
|
|
Parametrs:
|
|
pRxBlk : carry necessary packet info 802.11 format
|
|
FromWhichBSSID : the packet received from which BSS
|
|
|
|
Return :
|
|
none
|
|
|
|
Note :
|
|
the packet queued into reordering buffer need to cover to 802.3 format
|
|
or pre_AMSDU format
|
|
==========================================================================
|
|
*/
|
|
|
|
void Indicate_AMPDU_Packet(struct rt_rtmp_adapter *pAd,
|
|
struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
|
|
{
|
|
u16 Idx;
|
|
struct rt_ba_rec_entry *pBAEntry = NULL;
|
|
u16 Sequence = pRxBlk->pHeader->Sequence;
|
|
unsigned long Now32;
|
|
u8 Wcid = pRxBlk->pRxWI->WirelessCliID;
|
|
u8 TID = pRxBlk->pRxWI->TID;
|
|
|
|
if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)
|
|
&& (pRxBlk->DataSize > MAX_RX_PKT_LEN)) {
|
|
/* release packet */
|
|
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
|
|
NDIS_STATUS_FAILURE);
|
|
return;
|
|
}
|
|
|
|
if (Wcid < MAX_LEN_OF_MAC_TABLE) {
|
|
Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
|
|
if (Idx == 0) {
|
|
/* Rec BA Session had been torn down */
|
|
INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
|
|
return;
|
|
}
|
|
pBAEntry = &pAd->BATable.BARecEntry[Idx];
|
|
} else {
|
|
/* impossible ! */
|
|
ASSERT(0);
|
|
/* release packet */
|
|
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
|
|
NDIS_STATUS_FAILURE);
|
|
return;
|
|
}
|
|
|
|
ASSERT(pBAEntry);
|
|
|
|
/* update last rx time */
|
|
NdisGetSystemUpTime(&Now32);
|
|
|
|
pBAEntry->rcvSeq = Sequence;
|
|
|
|
ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
|
|
pBAEntry->LastIndSeqAtTimer = Now32;
|
|
|
|
/* */
|
|
/* Reset Last Indicate Sequence */
|
|
/* */
|
|
if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) {
|
|
ASSERT((pBAEntry->list.qlen == 0)
|
|
&& (pBAEntry->list.next == NULL));
|
|
|
|
/* reset rcv sequence of BA session */
|
|
pBAEntry->LastIndSeq = Sequence;
|
|
pBAEntry->LastIndSeqAtTimer = Now32;
|
|
INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
|
|
return;
|
|
}
|
|
|
|
/* */
|
|
/* I. Check if in order. */
|
|
/* */
|
|
if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) {
|
|
u16 LastIndSeq;
|
|
|
|
pBAEntry->LastIndSeq = Sequence;
|
|
INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
|
|
LastIndSeq =
|
|
ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry,
|
|
pBAEntry->LastIndSeq);
|
|
if (LastIndSeq != RESET_RCV_SEQ) {
|
|
pBAEntry->LastIndSeq = LastIndSeq;
|
|
}
|
|
pBAEntry->LastIndSeqAtTimer = Now32;
|
|
}
|
|
/* */
|
|
/* II. Drop Duplicated Packet */
|
|
/* */
|
|
else if (Sequence == pBAEntry->LastIndSeq) {
|
|
|
|
/* drop and release packet */
|
|
pBAEntry->nDropPacket++;
|
|
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
|
|
NDIS_STATUS_FAILURE);
|
|
}
|
|
/* */
|
|
/* III. Drop Old Received Packet */
|
|
/* */
|
|
else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) {
|
|
|
|
/* drop and release packet */
|
|
pBAEntry->nDropPacket++;
|
|
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
|
|
NDIS_STATUS_FAILURE);
|
|
}
|
|
/* */
|
|
/* IV. Receive Sequence within Window Size */
|
|
/* */
|
|
else if (SEQ_SMALLER
|
|
(Sequence,
|
|
(((pBAEntry->LastIndSeq + pBAEntry->BAWinSize + 1)) & MAXSEQ),
|
|
MAXSEQ)) {
|
|
ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk,
|
|
FromWhichBSSID);
|
|
}
|
|
/* */
|
|
/* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer */
|
|
/* */
|
|
else {
|
|
long WinStartSeq, TmpSeq;
|
|
|
|
TmpSeq = Sequence - (pBAEntry->BAWinSize) - 1;
|
|
if (TmpSeq < 0) {
|
|
TmpSeq = (MAXSEQ + 1) + TmpSeq;
|
|
}
|
|
WinStartSeq = (TmpSeq + 1) & MAXSEQ;
|
|
ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
|
|
pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */
|
|
|
|
pBAEntry->LastIndSeqAtTimer = Now32;
|
|
|
|
ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk,
|
|
FromWhichBSSID);
|
|
|
|
TmpSeq =
|
|
ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry,
|
|
pBAEntry->LastIndSeq);
|
|
if (TmpSeq != RESET_RCV_SEQ) {
|
|
pBAEntry->LastIndSeq = TmpSeq;
|
|
}
|
|
}
|
|
}
|