⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ba_action.c

📁 Linux下的RT系列无线网卡驱动,可以直接在x86平台上编译
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ************************************************************************* * Ralink Tech Inc. * 4F, No. 2 Technology 5th Rd. * Science-based Industrial Park * Hsin-chu, 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 MAX_TID_NUM		(15)#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 * HZ)/1000)	// system ticks -- 100 ms#define MAX_REORDERING_PACKET_TIMEOUT	((3000 * 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 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);	}	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(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->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;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 ((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+(REORDERING_PACKET_TIMEOUT)))		&& (pBAEntry->list.qlen > 0)	   )	{//		printk("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;		}		// printk("%x\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;	if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE)  &&  (isForced == FALSE))		return;	if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))	{//		printk("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 = 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;	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, ((UCHAR)pFrame->BaParm.BufSize));		pBAEntry->TimeOutValue = pFrame->TimeOutValue;		pBAEntry->ORI_BA_Status = Originator_Done;		// reset sequence number 		pBAEntry->Sequence = BA_ORI_INIT_SEQ;		// Set Bitmap flag.		pEntry->TXBAbitmap |= (1<<TID);		RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);		pBAEntry->ORIBATimer.TimerValue = 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 CONFIG_STA_SUPPORT		BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);#endif // CONFIG_STA_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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -