mirror of
https://github.com/YikeStone/MT7601u.git
synced 2025-08-02 10:54:08 +05:30
2339 lines
62 KiB
C
2339 lines
62 KiB
C
#ifdef DOT11_N_SUPPORT
|
|
|
|
#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(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
|
|
|
|
|
|
BA_ORI_ENTRY *BATableAllocOriEntry(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT USHORT *Idx);
|
|
|
|
BA_REC_ENTRY *BATableAllocRecEntry(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT USHORT *Idx);
|
|
|
|
VOID BAOriSessionSetupTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3);
|
|
|
|
VOID BARecSessionIdleTimeout(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID 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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MAC_TABLE_ENTRY *pEntryPeer,
|
|
OUT UCHAR *pWinSize)
|
|
{
|
|
UCHAR MaxSize;
|
|
UCHAR MaxPeerRxSize;
|
|
|
|
|
|
if (CLIENT_STATUS_TEST_FLAG(pEntryPeer, fCLIENT_STATUS_RALINK_CHIPSET))
|
|
MaxPeerRxSize = (1 << (pEntryPeer->MaxRAmpduFactor + 3)); /* (2^(13 + exp)) / 2048 bytes */
|
|
else
|
|
MaxPeerRxSize = (((1 << (pEntryPeer->MaxRAmpduFactor + 3)) * 10) / 16) -1;
|
|
|
|
#ifdef RT65xx
|
|
if (IS_RT65XX(pAd))
|
|
MaxSize = 31;
|
|
else
|
|
#endif /* RT65xx */
|
|
#ifdef MT7601
|
|
if (IS_MT7601(pAd))
|
|
MaxSize = 21;
|
|
else
|
|
#endif /* MT7601 */
|
|
if (pAd->MACVersion >= RALINK_2883_VERSION)
|
|
{
|
|
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) /* 2880e */
|
|
{
|
|
if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
|
|
MaxSize = 7; /* for non-open mode */
|
|
else
|
|
MaxSize = 13;
|
|
}
|
|
else
|
|
MaxSize = 7;
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("ba>WinSize=%d, MaxSize=%d, MaxPeerRxSize=%d\n",
|
|
*pWinSize, MaxSize, MaxPeerRxSize));
|
|
|
|
MaxSize = min(MaxPeerRxSize, 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(IN PRTMP_ADAPTER pAd,
|
|
IN struct reordering_mpdu *mpdu)
|
|
{
|
|
PNDIS_PACKET pPacket;
|
|
|
|
pPacket = mpdu->pPacket;
|
|
|
|
if (mpdu->bAMSDU)
|
|
{
|
|
/*ASSERT(0);*/
|
|
BA_Reorder_AMSDU_Annnounce(pAd, pPacket, mpdu->OpMode);
|
|
}
|
|
else
|
|
{
|
|
|
|
/* pass this 802.3 packet to upper layer or forward this packet to WM directly */
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
#ifdef P2P_SUPPORT
|
|
if (IS_OPMODE_AP(mpdu))
|
|
{
|
|
AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
|
|
}
|
|
else
|
|
{
|
|
ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
|
|
}
|
|
#else
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
|
|
#endif /* P2P_SUPPORT */
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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(PRTMP_ADAPTER pAd)
|
|
{
|
|
BA_TABLE *Tab;
|
|
PBA_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(PRTMP_ADAPTER pAd, int num)
|
|
{
|
|
int i;
|
|
PUCHAR mem;
|
|
struct reordering_mpdu *mpdu_blk;
|
|
struct reordering_list *freelist;
|
|
|
|
/* allocate spinlock */
|
|
NdisAllocateSpinLock(pAd, &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", (UINT32)(num*sizeof(struct reordering_mpdu))));
|
|
|
|
/* allocate number of mpdu_blk memory */
|
|
os_alloc_mem(pAd, (PUCHAR *)&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(PRTMP_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(PRTMP_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 USHORT ba_indicate_reordering_mpdus_in_order(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PBA_REC_ENTRY pBAEntry,
|
|
IN USHORT StartSeq)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk;
|
|
USHORT 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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PBA_REC_ENTRY pBAEntry,
|
|
IN USHORT 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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
PBA_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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PBA_REC_ENTRY pBAEntry,
|
|
IN ULONG Now32)
|
|
|
|
{
|
|
USHORT Sequence;
|
|
|
|
if ((pBAEntry == NULL) || (pBAEntry->list.qlen <= 0))
|
|
return;
|
|
|
|
/* 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)
|
|
)
|
|
{
|
|
/*
|
|
DBGPRINT(RT_DEBUG_OFF, ("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
|
|
(int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT,
|
|
pBAEntry->LastIndSeq));
|
|
*/
|
|
|
|
/* 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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MAC_TABLE_ENTRY *pEntry,
|
|
IN UCHAR TID,
|
|
IN USHORT TimeOut,
|
|
IN ULONG DelayTime,
|
|
IN BOOLEAN isForced)
|
|
|
|
{
|
|
/*MLME_ADDBA_REQ_STRUCT AddbaReq;*/
|
|
BA_ORI_ENTRY *pBAEntry = NULL;
|
|
USHORT Idx;
|
|
BOOLEAN Cancelled;
|
|
|
|
ASSERT(TID < NUM_OF_TID);
|
|
if (TID >= NUM_OF_TID)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Wrong TID %d!\n", TID));
|
|
return;
|
|
}
|
|
|
|
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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MAC_TABLE_ENTRY *pEntry,
|
|
IN PFRAME_ADDBA_RSP pFrame)
|
|
{
|
|
BA_ORI_ENTRY *pBAEntry = NULL;
|
|
BOOLEAN Cancelled;
|
|
UCHAR TID;
|
|
USHORT Idx;
|
|
PUCHAR pOutBuffer2 = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen;
|
|
FRAME_BAR FrameBar;
|
|
UCHAR MaxPeerBufSize;
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
UCHAR apidx;
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
TID = pFrame->BaParm.TID;
|
|
Idx = pEntry->BAOriWcidArray[TID];
|
|
pBAEntry =&pAd->BATable.BAOriEntry[Idx];
|
|
|
|
MaxPeerBufSize = 0;
|
|
|
|
/* Start fill in parameters.*/
|
|
if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
|
|
{
|
|
MaxPeerBufSize = (UCHAR)pFrame->BaParm.BufSize;
|
|
|
|
if (MaxPeerBufSize > 0)
|
|
MaxPeerBufSize -= 1;
|
|
else
|
|
MaxPeerBufSize = 0;
|
|
pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, MaxPeerBufSize);
|
|
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",
|
|
__FUNCTION__, 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;
|
|
}
|
|
|
|
#ifdef P2P_SUPPORT
|
|
BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->MacTab.Content[pBAEntry->Wcid].HdrAddr2);
|
|
#else
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
#ifdef APCLI_SUPPORT
|
|
if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pBAEntry->Wcid]))
|
|
{
|
|
apidx = pAd->MacTab.Content[pBAEntry->Wcid].MatchAPCLITabIdx;
|
|
BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress);
|
|
}
|
|
else
|
|
#endif /* APCLI_SUPPORT */
|
|
{
|
|
apidx = pAd->MacTab.Content[pBAEntry->Wcid].apidx;
|
|
BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid);
|
|
}
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
#endif /* P2P_SUPPORT */
|
|
|
|
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(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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MAC_TABLE_ENTRY *pEntry,
|
|
IN PFRAME_ADDBA_REQ pFrame)
|
|
{
|
|
BA_REC_ENTRY *pBAEntry = NULL;
|
|
BOOLEAN Status = TRUE;
|
|
BOOLEAN Cancelled;
|
|
USHORT Idx;
|
|
UCHAR TID;
|
|
UCHAR BAWinSize;
|
|
/*UINT32 Value;*/
|
|
/*UINT offset;*/
|
|
|
|
|
|
ASSERT(pEntry);
|
|
|
|
/* find TID*/
|
|
TID = pFrame->BaParm.TID;
|
|
|
|
BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
|
|
|
|
/* Intel patch*/
|
|
if (BAWinSize == 0)
|
|
{
|
|
BAWinSize = 64;
|
|
}
|
|
|
|
/* get software BA rec array index, Idx*/
|
|
Idx = pEntry->BARecWcidArray[TID];
|
|
|
|
|
|
if (Idx == 0)
|
|
{
|
|
/* allocate new array entry for the new session*/
|
|
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", __FUNCTION__, 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);
|
|
}
|
|
|
|
|
|
BA_REC_ENTRY *BATableAllocRecEntry(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT USHORT *Idx)
|
|
{
|
|
int i;
|
|
BA_REC_ENTRY *pBAEntry = NULL;
|
|
|
|
|
|
NdisAcquireSpinLock(&pAd->BATabLock);
|
|
|
|
if (pAd->BATable.numAsRecipient >= (MAX_LEN_OF_BA_REC_TABLE - 1))
|
|
{
|
|
DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n",
|
|
pAd->BATable.numAsRecipient, (MAX_LEN_OF_BA_REC_TABLE - 1)));
|
|
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;
|
|
}
|
|
|
|
BA_ORI_ENTRY *BATableAllocOriEntry(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT USHORT *Idx)
|
|
{
|
|
int i;
|
|
BA_ORI_ENTRY *pBAEntry = NULL;
|
|
|
|
NdisAcquireSpinLock(&pAd->BATabLock);
|
|
|
|
if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE - 1))
|
|
{
|
|
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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN ULONG Idx)
|
|
{
|
|
BA_ORI_ENTRY *pBAEntry = NULL;
|
|
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;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: Wcid = %d, TID = %d\n", __FUNCTION__, pBAEntry->Wcid, pBAEntry->TID));
|
|
|
|
|
|
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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN ULONG Idx)
|
|
{
|
|
BA_REC_ENTRY *pBAEntry = NULL;
|
|
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(
|
|
IN OUT PRTMP_ADAPTER pAd,
|
|
IN UCHAR Wcid,
|
|
IN UCHAR TID,
|
|
IN BOOLEAN bPassive,
|
|
IN BOOLEAN bForceSend)
|
|
{
|
|
ULONG Idx = 0;
|
|
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*/
|
|
MLME_DELBA_REQ_STRUCT DelbaReq;
|
|
MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/
|
|
os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM));
|
|
if (Elem != NULL)
|
|
{
|
|
NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
|
|
NdisZeroMemory(Elem, sizeof(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);*/
|
|
os_free_mem(NULL, Elem);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__));
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, 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))
|
|
{
|
|
MLME_DELBA_REQ_STRUCT DelbaReq;
|
|
MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/
|
|
os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM));
|
|
if (Elem != NULL)
|
|
{
|
|
NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
|
|
NdisZeroMemory(Elem, sizeof(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);*/
|
|
os_free_mem(NULL, Elem);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
}
|
|
RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
|
|
BATableFreeOriEntry(pAd, Idx);
|
|
|
|
if (bPassive)
|
|
{
|
|
/*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);*/
|
|
}
|
|
}
|
|
|
|
VOID BARecSessionTearDown(
|
|
IN OUT PRTMP_ADAPTER pAd,
|
|
IN UCHAR Wcid,
|
|
IN UCHAR TID,
|
|
IN BOOLEAN bPassive)
|
|
{
|
|
ULONG Idx = 0;
|
|
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", __FUNCTION__, 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))
|
|
{
|
|
MLME_DELBA_REQ_STRUCT DelbaReq;
|
|
BOOLEAN Cancelled;
|
|
/*ULONG offset; */
|
|
/*UINT32 VALUE;*/
|
|
|
|
RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
|
|
|
|
|
|
/* 1. Send DELBA Action Frame*/
|
|
if (bPassive == FALSE)
|
|
{
|
|
MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/
|
|
os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM));
|
|
if (Elem != NULL)
|
|
{
|
|
NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
|
|
NdisZeroMemory(Elem, sizeof(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);*/
|
|
os_free_mem(NULL, Elem);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
|
|
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(
|
|
IN OUT PRTMP_ADAPTER pAd,
|
|
IN UCHAR 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(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
|
|
MAC_TABLE_ENTRY *pEntry;
|
|
PRTMP_ADAPTER pAd;
|
|
|
|
if (pBAEntry == NULL)
|
|
return;
|
|
|
|
pAd = pBAEntry->pAdapter;
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
/* Do nothing if monitor mode is on*/
|
|
if (MONITOR_ON(pAd))
|
|
return;
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
#ifdef RALINK_ATE
|
|
/* Nothing to do in ATE mode. */
|
|
if (ATE_ON(pAd))
|
|
return;
|
|
#endif /* RALINK_ATE */
|
|
|
|
pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
|
|
|
|
if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
|
|
{
|
|
MLME_ADDBA_REQ_STRUCT AddbaReq;
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
#ifdef P2P_SUPPORT
|
|
if ((pAd->OpMode == OPMODE_STA) && IS_ENTRY_CLIENT(pEntry) && IS_P2P_ENTRY_NONE(pEntry))
|
|
#else
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
#endif /* P2P_SUPPORT */
|
|
{
|
|
if (INFRA_ON(pAd) &&
|
|
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) &&
|
|
(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)))
|
|
{
|
|
/* In scan progress and have no chance to send out, just re-schedule to another time period */
|
|
RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
|
|
return;
|
|
}
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
|
|
COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
|
|
AddbaReq.Wcid = (UCHAR)(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(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq, 0);
|
|
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(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
|
|
BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
|
|
PRTMP_ADAPTER pAd;
|
|
ULONG 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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
|
|
{
|
|
/* 7.4.4.1*/
|
|
/*ULONG Idx;*/
|
|
UCHAR Status = 1;
|
|
UCHAR pAddr[6];
|
|
FRAME_ADDBA_RSP ADDframe;
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
PFRAME_ADDBA_REQ pAddreqFrame = NULL;
|
|
/*UCHAR BufSize;*/
|
|
ULONG FrameLen;
|
|
PULONG ptemp;
|
|
PMAC_TABLE_ENTRY pMacEntry;
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
INT apidx;
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, 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 = (PULONG)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 = (PFRAME_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 (IS_ENTRY_CLIENT(&pAd->MacTab.Content[Elem->Wcid]))
|
|
ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
|
|
|
|
pAddreqFrame = (PFRAME_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(FRAME_ADDBA_RSP));
|
|
/* 2-1. Prepare ADDBA Response frame.*/
|
|
#ifdef P2P_SUPPORT
|
|
if (pMacEntry)
|
|
{
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
if (ADHOC_ON(pAd)
|
|
#ifdef QOS_DLS_SUPPORT
|
|
|| (IS_ENTRY_DLS(&pAd->MacTab.Content[Elem->Wcid]))
|
|
#endif /* QOS_DLS_SUPPORT */
|
|
#ifdef DOT11Z_TDLS_SUPPORT
|
|
|| (IS_ENTRY_TDLS(&pAd->MacTab.Content[Elem->Wcid]))
|
|
#endif /* DOT11Z_TDLS_SUPPORT */
|
|
)
|
|
{
|
|
ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
|
|
}
|
|
else
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
{
|
|
ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pMacEntry->HdrAddr2, pMacEntry->HdrAddr3);
|
|
}
|
|
}
|
|
#else
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
#ifdef APCLI_SUPPORT
|
|
if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Elem->Wcid]))
|
|
{
|
|
apidx = pAd->MacTab.Content[Elem->Wcid].MatchAPCLITabIdx;
|
|
ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAddr);
|
|
}
|
|
else
|
|
#endif /* APCLI_SUPPORT */
|
|
{
|
|
apidx = pAd->MacTab.Content[Elem->Wcid].apidx;
|
|
ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
|
|
}
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
if (ADHOC_ON(pAd)
|
|
#ifdef QOS_DLS_SUPPORT
|
|
|| (IS_ENTRY_DLS(&pAd->MacTab.Content[Elem->Wcid]))
|
|
#endif /* QOS_DLS_SUPPORT */
|
|
#ifdef DOT11Z_TDLS_SUPPORT
|
|
|| (IS_ENTRY_TDLS(&pAd->MacTab.Content[Elem->Wcid]))
|
|
#endif /* DOT11Z_TDLS_SUPPORT */
|
|
)
|
|
ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
|
|
else
|
|
ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
#endif /* P2P_SUPPORT */
|
|
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(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
|
|
if (ADDframe.BaParm.BufSize == 0)
|
|
{
|
|
ADDframe.BaParm.BufSize = 64;
|
|
}
|
|
ADDframe.TimeOutValue = 0; /* pAddreqFrame->TimeOutValue; */
|
|
|
|
#ifdef UNALIGNMENT_SUPPORT
|
|
{
|
|
BA_PARM tmpBaParm;
|
|
|
|
NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&ADDframe.BaParm), sizeof(BA_PARM));
|
|
*(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm));
|
|
NdisMoveMemory((PUCHAR)(&ADDframe.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM));
|
|
}
|
|
#else
|
|
*(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
|
|
#endif /* UNALIGNMENT_SUPPORT */
|
|
|
|
ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
|
|
ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
|
|
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(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", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID,
|
|
ADDframe.BaParm.BufSize));
|
|
}
|
|
|
|
|
|
VOID PeerAddBARspAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
|
|
{
|
|
/*UCHAR Idx, i;*/
|
|
/*PUCHAR pOutBuffer = NULL;*/
|
|
PFRAME_ADDBA_RSP pFrame = NULL;
|
|
/*PBA_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", __FUNCTION__, Elem->Wcid));
|
|
|
|
/*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);*/
|
|
|
|
if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
|
|
{
|
|
pFrame = (PFRAME_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)
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
|| ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
)
|
|
{
|
|
pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID PeerDelBAAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
|
|
{
|
|
/*UCHAR Idx;*/
|
|
/*PUCHAR pOutBuffer = NULL;*/
|
|
PFRAME_DELBA_REQ pDelFrame = NULL;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__));
|
|
/*DELBA Request from unknown peer, ignore this.*/
|
|
if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
|
|
{
|
|
pDelFrame = (PFRAME_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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN ULONG Wcid,
|
|
IN ULONG MsgLen,
|
|
IN PFRAME_BA_REQ pMsg)
|
|
{
|
|
PFRAME_BA_REQ pFrame = pMsg;
|
|
/*PRTMP_REORDERBUF pBuffer;*/
|
|
/*PRTMP_REORDERBUF pDmaBuf;*/
|
|
PBA_REC_ENTRY pBAEntry;
|
|
/*BOOLEAN Result;*/
|
|
ULONG Idx;
|
|
/*UCHAR NumRxPkt;*/
|
|
UCHAR TID;/*, i;*/
|
|
|
|
TID = (UCHAR)pFrame->BARControl.TID;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID));
|
|
/*hex_dump("BAR", (PCHAR) 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) /* 1600B */
|
|
{
|
|
DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
|
|
return FALSE;
|
|
}
|
|
else if (MsgLen != sizeof(FRAME_BA_REQ))
|
|
{
|
|
DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
|
|
return FALSE;
|
|
}
|
|
else if (MsgLen != sizeof(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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR Wcid,
|
|
IN UCHAR Psmp)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
FRAME_PSMP_ACTION Frame;
|
|
ULONG FrameLen;
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
UCHAR apidx;
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef P2P_SUPPORT
|
|
PMAC_TABLE_ENTRY pEntry;
|
|
#endif /* P2P_SUPPORT */
|
|
|
|
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;
|
|
}
|
|
|
|
#ifdef P2P_SUPPORT
|
|
if (VALID_WCID(Wcid))
|
|
{
|
|
pEntry = &pAd->MacTab.Content[Wcid];
|
|
|
|
if (pEntry)
|
|
ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pEntry->HdrAddr2, pEntry->HdrAddr3);
|
|
}
|
|
#else
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
#ifdef APCLI_SUPPORT
|
|
if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Wcid]))
|
|
{
|
|
apidx = pAd->MacTab.Content[Wcid].MatchAPCLITabIdx;
|
|
ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
|
|
}
|
|
else
|
|
#endif /* APCLI_SUPPORT */
|
|
{
|
|
apidx = pAd->MacTab.Content[Wcid].apidx;
|
|
ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
|
|
}
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
#endif /* P2P_SUPPORT */
|
|
|
|
Frame.Category = CATEGORY_HT;
|
|
Frame.Action = SMPS_ACTION;
|
|
switch (Psmp)
|
|
{
|
|
case MMPS_ENABLE:
|
|
Frame.Psmp = 0;
|
|
break;
|
|
case MMPS_DYNAMIC:
|
|
Frame.Psmp = 3;
|
|
break;
|
|
case MMPS_STATIC:
|
|
Frame.Psmp = 1;
|
|
break;
|
|
}
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(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
|
|
|
|
typedef struct GNU_PACKED _BEACON_REQUEST {
|
|
UCHAR RegulatoryClass;
|
|
UCHAR ChannelNumber;
|
|
USHORT RandomInterval;
|
|
USHORT MeasurementDuration;
|
|
UCHAR MeasurementMode;
|
|
UCHAR BSSID[MAC_ADDR_LEN];
|
|
UCHAR ReportingCondition;
|
|
UCHAR Threshold;
|
|
UCHAR SSIDIE[2]; /* 2 byte*/
|
|
} BEACON_REQUEST;
|
|
|
|
typedef struct GNU_PACKED _MEASUREMENT_REQ
|
|
{
|
|
UCHAR ID;
|
|
UCHAR Length;
|
|
UCHAR Token;
|
|
UCHAR RequestMode;
|
|
UCHAR Type;
|
|
} MEASUREMENT_REQ;
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
VOID SendBeaconRequest(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR Wcid)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
FRAME_RM_REQ_ACTION Frame;
|
|
ULONG FrameLen;
|
|
BEACON_REQUEST BeaconReq;
|
|
MEASUREMENT_REQ MeasureReg;
|
|
UCHAR apidx;
|
|
|
|
if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Wcid]))
|
|
return;
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
|
|
if (NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR,("Radio - SendBeaconRequest() allocate memory failed \n"));
|
|
return;
|
|
}
|
|
apidx = pAd->MacTab.Content[Wcid].apidx;
|
|
ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
|
|
|
|
Frame.Category = CATEGORY_RM;
|
|
Frame.Action = RADIO_MEASUREMENT_REQUEST_ACTION;
|
|
Frame.Token = 1;
|
|
Frame.Repetition = 0; /* executed once*/
|
|
|
|
BeaconReq.RegulatoryClass = 32; /* ?????*/
|
|
BeaconReq.ChannelNumber = 255; /* all channels*/
|
|
BeaconReq.RandomInterval = 0;
|
|
BeaconReq.MeasurementDuration = 10; /* 10 TU*/
|
|
BeaconReq.MeasurementMode = 1; /* Active mode */
|
|
COPY_MAC_ADDR(BeaconReq.BSSID, BROADCAST_ADDR);
|
|
BeaconReq.ReportingCondition = 254; /* report not necesssary*/
|
|
BeaconReq.Threshold = 0; /* minimum RCPI*/
|
|
BeaconReq.SSIDIE[0] = 0;
|
|
BeaconReq.SSIDIE[1] = 0; /* wildcard SSID zero length */
|
|
|
|
|
|
MeasureReg.ID = IE_MEASUREMENT_REQUEST;
|
|
MeasureReg.Token = 0;
|
|
MeasureReg.RequestMode = 0;
|
|
MeasureReg.Type = 5; /* Beacon Request*/
|
|
MeasureReg.Length = sizeof(MEASUREMENT_REQ)+sizeof(BEACON_REQUEST)-2;
|
|
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(FRAME_RM_REQ_ACTION), &Frame,
|
|
sizeof(MEASUREMENT_REQ), &MeasureReg,
|
|
sizeof(BEACON_REQUEST), &BeaconReq,
|
|
END_OF_ARGS);
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
DBGPRINT(RT_DEBUG_TRACE,("Radio - SendBeaconRequest\n"));
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
|
|
void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN RX_BLK *pRxBlk,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
PNDIS_PACKET pRxPkt;
|
|
UCHAR Header802_3[LENGTH_802_3];
|
|
|
|
/*
|
|
1. get 802.3 Header
|
|
2. remove LLC
|
|
a. pointer pRxBlk->pData to payload
|
|
b. modify pRxBlk->DataSize
|
|
*/
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
#ifdef P2P_SUPPORT
|
|
if (IS_PKT_OPMODE_AP(pRxBlk))
|
|
{
|
|
RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
|
|
}
|
|
else
|
|
{
|
|
RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
|
|
}
|
|
#else
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
|
|
#endif /* P2P_SUPPORT */
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
ASSERT(pRxBlk->pRxPacket);
|
|
|
|
pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
|
|
|
|
RTMP_OS_PKT_INIT(pRxBlk->pRxPacket,
|
|
get_netdev_from_bssid(pAd, FromWhichBSSID),
|
|
pRxBlk->pData, pRxBlk->DataSize);
|
|
|
|
|
|
/* copy 802.3 header, if necessary*/
|
|
if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
|
|
{
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
/* maybe insert VLAN tag to the received packet */
|
|
UCHAR VLAN_Size = 0;
|
|
UCHAR *data_p;
|
|
USHORT VLAN_VID = 0, VLAN_Priority = 0;
|
|
|
|
/* VLAN related */
|
|
MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
|
|
|
|
#ifdef WDS_VLAN_SUPPORT
|
|
if (VLAN_VID == 0) /* maybe WDS packet */
|
|
WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
|
|
#endif /* WDS_VLAN_SUPPORT */
|
|
|
|
if (VLAN_VID != 0)
|
|
VLAN_Size = LENGTH_802_1Q;
|
|
|
|
data_p = OS_PKT_HEAD_BUF_EXTEND(pRxPkt, LENGTH_802_3+VLAN_Size);
|
|
RT_VLAN_8023_HEADER_COPY(pAd, VLAN_VID, VLAN_Priority,
|
|
Header802_3, LENGTH_802_3,
|
|
data_p, FromWhichBSSID, TPID);
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
#ifdef P2P_SUPPORT
|
|
if (IS_PKT_OPMODE_AP(pRxBlk))
|
|
{
|
|
/* maybe insert VLAN tag to the received packet */
|
|
UCHAR VLAN_Size = 0;
|
|
UCHAR *data_p;
|
|
USHORT VLAN_VID = 0, VLAN_Priority = 0;
|
|
UCHAR WhichBSSID = FromWhichBSSID;
|
|
|
|
if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_P2P_GO)
|
|
WhichBSSID = FromWhichBSSID - MIN_NET_DEVICE_FOR_P2P_GO;
|
|
|
|
/* VLAN related */
|
|
MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, WhichBSSID);
|
|
|
|
#ifdef WDS_VLAN_SUPPORT
|
|
if (VLAN_VID == 0) /* maybe WDS packet */
|
|
WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
|
|
#endif /* WDS_VLAN_SUPPORT */
|
|
|
|
if (VLAN_VID != 0)
|
|
VLAN_Size = LENGTH_802_1Q;
|
|
|
|
data_p = OS_PKT_HEAD_BUF_EXTEND(pRxPkt, LENGTH_802_3+VLAN_Size);
|
|
RT_VLAN_8023_HEADER_COPY(pAd, VLAN_VID, VLAN_Priority,
|
|
Header802_3, LENGTH_802_3,
|
|
data_p, FromWhichBSSID, TPID);
|
|
}
|
|
else
|
|
{
|
|
#ifdef LINUX
|
|
UCHAR *data_p;
|
|
data_p = OS_PKT_HEAD_BUF_EXTEND(pRxPkt, LENGTH_802_3);
|
|
NdisMoveMemory(data_p, Header802_3, LENGTH_802_3);
|
|
#endif
|
|
}
|
|
#else
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
#ifdef LINUX
|
|
UCHAR *data_p;
|
|
data_p = OS_PKT_HEAD_BUF_EXTEND(pRxPkt, LENGTH_802_3);
|
|
NdisMoveMemory(data_p, Header802_3, LENGTH_802_3);
|
|
#endif
|
|
}
|
|
#endif /* P2P_SUPPORT */
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
}
|
|
}
|
|
|
|
|
|
#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);
|
|
|
|
#define INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(_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_Hdr_Trns(_pAd, _pRxBlk, _fromWhichBSSID); \
|
|
} \
|
|
} while (0);
|
|
|
|
static VOID ba_enqueue_reordering_packet(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PBA_REC_ENTRY pBAEntry,
|
|
IN RX_BLK *pRxBlk,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk;
|
|
UINT16 Sequence = (UINT16) 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->OpMode = pRxBlk->OpMode;
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef HDR_TRANS_SUPPORT
|
|
static VOID ba_enqueue_reordering_packet_hdr_trns(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PBA_REC_ENTRY pBAEntry,
|
|
IN RX_BLK *pRxBlk,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
struct reordering_mpdu *mpdu_blk;
|
|
UINT16 Sequence = (UINT16) 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->OpMode = pRxBlk->OpMode;
|
|
|
|
mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
|
|
|
|
convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
|
|
|
|
|
|
RTMP_OS_PKT_INIT(pRxBlk->pRxPacket,
|
|
get_netdev_from_bssid(pAd, FromWhichBSSID),
|
|
pRxBlk->pTransData, pRxBlk->TransDataSize);
|
|
|
|
|
|
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_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID);
|
|
}
|
|
}
|
|
#endif /* HDR_TRANS_SUPPORT */
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
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(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN RX_BLK *pRxBlk,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
USHORT Idx;
|
|
PBA_REC_ENTRY pBAEntry = NULL;
|
|
UINT16 Sequence = pRxBlk->pHeader->Sequence;
|
|
ULONG Now32;
|
|
UCHAR Wcid = pRxBlk->pRxWI->RxWIWirelessCliID;
|
|
UCHAR TID = pRxBlk->pRxWI->RxWITID;
|
|
|
|
|
|
if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
|
|
{
|
|
static int err_size;
|
|
|
|
err_size++;
|
|
if (err_size > 20) {
|
|
DBGPRINT(RT_DEBUG_TRACE, ("AMPDU DataSize = %d\n", pRxBlk->DataSize));
|
|
hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24);
|
|
hex_dump("Payload", pRxBlk->pData, 64);
|
|
err_size = 0;
|
|
}
|
|
|
|
/* 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))
|
|
{
|
|
USHORT 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef HDR_TRANS_SUPPORT
|
|
VOID Indicate_AMPDU_Packet_Hdr_Trns(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN RX_BLK *pRxBlk,
|
|
IN UCHAR FromWhichBSSID)
|
|
{
|
|
USHORT Idx;
|
|
PBA_REC_ENTRY pBAEntry = NULL;
|
|
UINT16 Sequence = pRxBlk->pHeader->Sequence;
|
|
ULONG Now32;
|
|
UCHAR Wcid = pRxBlk->pRxWI->RxWIWirelessCliID;
|
|
UCHAR TID = pRxBlk->pRxWI->RxWITID;
|
|
|
|
|
|
if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->TransDataSize > 1514))
|
|
{
|
|
static int err_size;
|
|
|
|
err_size++;
|
|
if (err_size > 20) {
|
|
DBGPRINT(RT_DEBUG_TRACE, ("AMPDU DataSize = %d\n", pRxBlk->DataSize));
|
|
hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24);
|
|
hex_dump("Payload", pRxBlk->pData, 64);
|
|
err_size = 0;
|
|
}
|
|
|
|
/* 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_HDR_TRNS(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_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID);
|
|
return;
|
|
}
|
|
|
|
/* I. Check if in order.*/
|
|
if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
|
|
{
|
|
USHORT LastIndSeq;
|
|
|
|
pBAEntry->LastIndSeq = Sequence;
|
|
INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(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_hdr_trns(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
|
|
}
|
|
|
|
/* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer*/
|
|
else
|
|
{
|
|
LONG WinStartSeq, TmpSeq;
|
|
|
|
|
|
printk("999999999\n");
|
|
|
|
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_hdr_trns(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
|
|
|
|
TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
|
|
if (TmpSeq != RESET_RCV_SEQ)
|
|
{
|
|
pBAEntry->LastIndSeq = TmpSeq;
|
|
}
|
|
}
|
|
}
|
|
#endif /* HDR_TRANS_SUPPORT */
|
|
|
|
|
|
VOID BaReOrderingBufferMaintain(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
ULONG Now32;
|
|
UCHAR Wcid;
|
|
USHORT Idx;
|
|
UCHAR TID;
|
|
PBA_REC_ENTRY pBAEntry = NULL;
|
|
PMAC_TABLE_ENTRY pEntry = NULL;
|
|
|
|
/* update last rx time*/
|
|
NdisGetSystemUpTime(&Now32);
|
|
|
|
for (Wcid = 1; Wcid < MAX_LEN_OF_MAC_TABLE; Wcid++)
|
|
{
|
|
pEntry = &pAd->MacTab.Content[Wcid];
|
|
if (IS_ENTRY_NONE(pEntry))
|
|
continue;
|
|
|
|
for (TID= 0; TID < NUM_OF_TID; TID++)
|
|
{
|
|
Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
|
|
pBAEntry = &pAd->BATable.BARecEntry[Idx];
|
|
ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
|
|
}
|
|
}
|
|
}
|
|
#endif /* DOT11_N_SUPPORT */
|
|
|