BOOLEAN
CheckRxTsIndicateSeq(
	IN	PADAPTER		Adapter,
	IN	PRX_TS_RECORD	pTS,
	IN	u2Byte			NewSeqNum
	)
{
	PRT_HIGH_THROUGHPUT 	pHTInfo = Adapter->MgntInfo.pHTInfo;
	u1Byte					WinSize = pHTInfo->RxReorderWinSize;
	u2Byte					WinEnd = (pTS->RxIndicateSeq + WinSize -1)%4096;

	// Rx Reorder initialize condition.
	if(pTS->RxIndicateSeq == 0xffff)
		pTS->RxIndicateSeq = NewSeqNum;

	// Drop out the packet which SeqNum is smaller than WinStart
	if( SN_LESS(NewSeqNum, pTS->RxIndicateSeq ) )
	{
		RT_TRACE(COMP_RX_REORDER, DBG_WARNING, ("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum));
		return FALSE;
	}

	//
	//	SeqNum "MUST" in Window Size !!
	//
	if( !ISinWindow(NewSeqNum ,  pTS->RxIndicateSeq ) )
	{
		RT_TRACE(COMP_RX_REORDER, DBG_WARNING, ("CheckRxTsIndicateSeq(): out-off squence !! Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum));
		return FALSE;
	}
	
	//
	// Sliding window manipulation. Conditions includes:
	// 1. Incoming SeqNum is equal to WinStart =>Window shift 1
	// 2. Incoming SeqNum is larger than the WinEnd => Window shift N
	//
	if( SN_EQUAL(NewSeqNum, pTS->RxIndicateSeq) )
	{
		pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
	}
	else if(SN_LESS(WinEnd, NewSeqNum))
	{
		RT_TRACE(COMP_RX_REORDER, DBG_WARNING, ("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum));
		if(NewSeqNum >= (WinSize - 1))
			pTS->RxIndicateSeq = NewSeqNum + 1 -WinSize;
		else
			pTS->RxIndicateSeq = 4095 - (WinSize - (NewSeqNum +1)) + 1;
	}

	return TRUE;
}
Example #2
0
/********************************************************************************************************************
 *function:  I still not understand this function, so wait for further implementation
 *   input:  unsigned long	 data		//acturally we send struct tx_ts_record or struct rx_ts_record to these timer
 *  return:  NULL
 *  notice:
 ********************************************************************************************************************/
static void RxPktPendingTimeout(struct timer_list *t)
{
	struct rx_ts_record     *pRxTs = from_timer(pRxTs, t, rx_pkt_pending_timer);
	struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);

	PRX_REORDER_ENTRY	pReorderEntry = NULL;

	//u32 flags = 0;
	unsigned long flags = 0;
	u8 index = 0;
	bool bPktInBuf = false;

	spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
	IEEE80211_DEBUG(IEEE80211_DL_REORDER, "==================>%s()\n", __func__);
	if(pRxTs->rx_timeout_indicate_seq != 0xffff) {
		// Indicate the pending packets sequentially according to SeqNum until meet the gap.
		while(!list_empty(&pRxTs->rx_pending_pkt_list)) {
			pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->rx_pending_pkt_list.prev, RX_REORDER_ENTRY, List);
			if(index == 0)
				pRxTs->rx_indicate_seq = pReorderEntry->SeqNum;

			if( SN_LESS(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq) ||
				SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq)	) {
				list_del_init(&pReorderEntry->List);

				if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->rx_indicate_seq))
					pRxTs->rx_indicate_seq = (pRxTs->rx_indicate_seq + 1) % 4096;

				IEEE80211_DEBUG(IEEE80211_DL_REORDER, "RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum);
				ieee->stats_IndicateArray[index] = pReorderEntry->prxb;
				index++;

				list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
			} else {
				bPktInBuf = true;
				break;
			}
		}
	}

	if(index>0) {
		// Set rx_timeout_indicate_seq to 0xffff to indicate no pending packets in buffer now.
		pRxTs->rx_timeout_indicate_seq = 0xffff;

		// Indicate packets
		if(index > REORDER_WIN_SIZE) {
			IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n");
			spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
			return;
		}
		ieee80211_indicate_packets(ieee, ieee->stats_IndicateArray, index);
	}

	if(bPktInBuf && (pRxTs->rx_timeout_indicate_seq == 0xffff)) {
		pRxTs->rx_timeout_indicate_seq = pRxTs->rx_indicate_seq;
		mod_timer(&pRxTs->rx_pkt_pending_timer,
			  jiffies + msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime));
	}
	spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
}
BOOLEAN
InsertRxReorderList(
	IN	PADAPTER		Adapter,
	IN	PRT_RFD			pRfd,
	IN	PRX_TS_RECORD	pTS,
	IN	u2Byte			SeqNum
	)
{
	PMGNT_INFO			pMgntInfo = &Adapter->MgntInfo;
	PRX_REORDER_ENTRY 	pReorderEntry;
	PRT_LIST_ENTRY	pList = &pTS->RxPendingPktList;

	if(!RTIsListEmpty(&pMgntInfo->RxReorder_Unused_List))
	{
		pReorderEntry = (PRX_REORDER_ENTRY)RTRemoveHeadList(&pMgntInfo->RxReorder_Unused_List);

		// Make a reorder entry and insert into a the packet list.
		pReorderEntry->SeqNum = SeqNum;
		pReorderEntry->pRfd = pRfd;

		while(pList->Blink != &pTS->RxPendingPktList)
		{
			if( SN_LESS(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)pList->Blink)->SeqNum) )
			{
				// Not reach correct position yet!!
				pList = pList->Blink;
			}
			else if( SN_EQUAL(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)pList->Blink)->SeqNum) )
			{
				// Duplicate entry is found!! Do not insert current entry.
				RT_TRACE(COMP_RX_REORDER, DBG_WARNING, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum));

				RTInsertTailList(&pMgntInfo->RxReorder_Unused_List, &pReorderEntry->List);
				return FALSE;
			}
			else
			{
				break;
			}
		}

		pReorderEntry->List.Blink = pList->Blink;
		pReorderEntry->List.Blink->Flink = &pReorderEntry->List;
		pReorderEntry->List.Flink = pList;
		pList->Blink = &pReorderEntry->List;

		RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum));
		return TRUE;
	}
	else
	{
		// This part shall be modified!! We can just indicate all the packets in buffer and get reorder entries.
		RT_TRACE(COMP_RX_REORDER, DBG_WARNING, ("InsertRxReorderList(): There is no reorder entry!! Packet is dropped!!\n"));
		return FALSE;
	}
}
Example #4
0
void RxPktPendingTimeout(unsigned long data)
{
	PRX_TS_RECORD	pRxTs = (PRX_TS_RECORD)data;
	struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, RxTsRecord[pRxTs->num]);
	
	PRX_REORDER_ENTRY 	pReorderEntry = NULL;

	unsigned long flags = 0;
	struct rtllib_rxb *stats_IndicateArray[REORDER_WIN_SIZE];
	u8 index = 0;
	bool bPktInBuf = false;


	spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
	RTLLIB_DEBUG(RTLLIB_DL_REORDER,"==================>%s()\n",__FUNCTION__);
	if(pRxTs->RxTimeoutIndicateSeq != 0xffff)
	{
		while(!list_empty(&pRxTs->RxPendingPktList))
		{
			pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
			if(index == 0)
				pRxTs->RxIndicateSeq = pReorderEntry->SeqNum;

			if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) || 
				SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq)	)
			{
				list_del_init(&pReorderEntry->List);
			
				if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq))
					pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096;

				RTLLIB_DEBUG(RTLLIB_DL_REORDER,"RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum);
				stats_IndicateArray[index] = pReorderEntry->prxb;
				index++;
				
				list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
			}
			else
			{
				bPktInBuf = true;
				break;
			}
		}
	}

	if(index>0)
	{
		pRxTs->RxTimeoutIndicateSeq = 0xffff;
	
		if(index > REORDER_WIN_SIZE){
			RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
			spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
			return;
		}
		rtllib_indicate_packets(ieee, stats_IndicateArray, index);
		 bPktInBuf = false;

	}

	if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff))
	{
		pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
#if 0   
		if(timer_pending(&pTS->RxPktPendingTimer))
			del_timer_sync(&pTS->RxPktPendingTimer);
		pTS->RxPktPendingTimer.expires = jiffies + MSECS(pHTInfo->RxReorderPendingTime);
		add_timer(&pTS->RxPktPendingTimer);
#else
		mod_timer(&pRxTs->RxPktPendingTimer,  jiffies + MSECS(ieee->pHTInfo->RxReorderPendingTime));
#endif

#if 0		
		if(timer_pending(&pRxTs->RxPktPendingTimer))
			del_timer_sync(&pRxTs->RxPktPendingTimer);
		pRxTs->RxPktPendingTimer.expires = jiffies + ieee->pHTInfo->RxReorderPendingTime;
		add_timer(&pRxTs->RxPktPendingTimer);
#endif
	}
	spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
}
Example #5
0
void rtllib_tx_query_agg_cap(struct rtllib_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
{
	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
	PTX_TS_RECORD			pTxTs = NULL;
	struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr*)skb->data;

	if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
		return;
	if (!IsQoSDataFrame(skb->data))
		return;

	if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1))
		return;
	//check packet and mode later
#ifdef TO_DO_LIST
	if(pTcb->PacketLength >= 4096)
		return;
	// For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation.
	if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
		return; 
#endif

	if(pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION)
		return;
	
	if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
	{
		return; 
	}
	if(pHTInfo->bCurrentAMPDUEnable)
	{
		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true))
		{
			printk("===>can't get TS\n");
			return;
		}
		if (pTxTs->TxAdmittedBARecord.bValid == false)
		{
			//as some AP will refuse our action frame until key handshake has been finished. WB
			if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA)) {
				;//printk("############### ieee->wpa_ie_len=%d ieee->pairwise_key_type=%d\n", ieee->wpa_ie_len,ieee->pairwise_key_type);
			} else if (tcb_desc->bdhcp == 1){
				;//dhcp my be very slow for some ap like linksys610N/350N
			} else if (!pTxTs->bDisable_AddBa){
				TsStartAddBaProcess(ieee, pTxTs);
			}
			goto FORCED_AGG_SETTING;
		}
		else if (pTxTs->bUsingBa == false)
		{
			if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
				pTxTs->bUsingBa = true;
			else
				goto FORCED_AGG_SETTING;
		}
#ifndef _RTL8192_EXT_PATCH_
		if (ieee->iw_mode == IW_MODE_INFRA)
#endif
		{
			tcb_desc->bAMPDUEnable = true;
			tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
			tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
		}
	}
FORCED_AGG_SETTING:
	switch(pHTInfo->ForcedAMPDUMode )
	{
		case HT_AGG_AUTO:
			break;

		case HT_AGG_FORCE_ENABLE:
			tcb_desc->bAMPDUEnable = true;
			tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
			tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
			break;

		case HT_AGG_FORCE_DISABLE:
			tcb_desc->bAMPDUEnable = false;
			tcb_desc->ampdu_density = 0;
			tcb_desc->ampdu_factor = 0;
			break;

	}	
		return;
}
Example #6
0
void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
{
	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
	PTX_TS_RECORD			pTxTs = NULL;
	struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data;

	if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
		return;
	if (!IsQoSDataFrame(skb->data))
		return;

	if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1))
		return;
	//check packet and mode later
#ifdef TO_DO_LIST
	if(pTcb->PacketLength >= 4096)
		return;
	// For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation.
	if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
		return;
#endif
	if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
	{
		return;
	}
	if(pHTInfo->bCurrentAMPDUEnable)
	{
		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true))
		{
;
			return;
		}
		if (pTxTs->TxAdmittedBARecord.bValid == false)
		{
			TsStartAddBaProcess(ieee, pTxTs);
			goto FORCED_AGG_SETTING;
		}
		else if (pTxTs->bUsingBa == false)
		{
			if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
				pTxTs->bUsingBa = true;
			else
				goto FORCED_AGG_SETTING;
		}

		if (ieee->iw_mode == IW_MODE_INFRA)
		{
			tcb_desc->bAMPDUEnable = true;
			tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
			tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
		}
	}
FORCED_AGG_SETTING:
	switch(pHTInfo->ForcedAMPDUMode )
	{
		case HT_AGG_AUTO:
			break;

		case HT_AGG_FORCE_ENABLE:
			tcb_desc->bAMPDUEnable = true;
			tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
			tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
			break;

		case HT_AGG_FORCE_DISABLE:
			tcb_desc->bAMPDUEnable = false;
			tcb_desc->ampdu_density = 0;
			tcb_desc->ampdu_factor = 0;
			break;

	}
		return;
}
Example #7
0
static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
				    struct sk_buff *skb,
				    struct cb_desc *tcb_desc)
{
	struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
	struct tx_ts_record *pTxTs = NULL;
	struct rtllib_hdr_1addr *hdr = (struct rtllib_hdr_1addr *)skb->data;

	if (rtllib_act_scanning(ieee, false))
		return;

	if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
		return;
	if (!IsQoSDataFrame(skb->data))
		return;
	if (is_multicast_ether_addr(hdr->addr1))
		return;

	if (tcb_desc->bdhcp || ieee->CntAfterLink < 2)
		return;

	if (pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION)
		return;

	if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
		return;
	if (pHTInfo->bCurrentAMPDUEnable) {
		if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1,
		    skb->priority, TX_DIR, true)) {
			printk(KERN_INFO "%s: can't get TS\n", __func__);
			return;
		}
		if (pTxTs->TxAdmittedBARecord.bValid == false) {
			if (ieee->wpa_ie_len && (ieee->pairwise_key_type ==
			    KEY_TYPE_NA)) {
				;
			} else if (tcb_desc->bdhcp == 1) {
				;
			} else if (!pTxTs->bDisable_AddBa) {
				TsStartAddBaProcess(ieee, pTxTs);
			}
			goto FORCED_AGG_SETTING;
		} else if (pTxTs->bUsingBa == false) {
			if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum,
			   (pTxTs->TxCurSeq+1)%4096))
				pTxTs->bUsingBa = true;
			else
				goto FORCED_AGG_SETTING;
		}
		if (ieee->iw_mode == IW_MODE_INFRA) {
			tcb_desc->bAMPDUEnable = true;
			tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
			tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
		}
	}
FORCED_AGG_SETTING:
	switch (pHTInfo->ForcedAMPDUMode) {
	case HT_AGG_AUTO:
		break;

	case HT_AGG_FORCE_ENABLE:
		tcb_desc->bAMPDUEnable = true;
		tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
		tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
		break;

	case HT_AGG_FORCE_DISABLE:
		tcb_desc->bAMPDUEnable = false;
		tcb_desc->ampdu_density = 0;
		tcb_desc->ampdu_factor = 0;
		break;
	}
	return;
}
Example #8
0
void rtllib_tx_query_agg_cap(struct rtllib_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
{
	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
	PTX_TS_RECORD			pTxTs = NULL;
	struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr*)skb->data;

	if(tcb_desc->bBTTxPacket)
		return;
	
	if(rtllib_act_scanning(ieee,false))
		return;

	if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT){
		return;
	}
	if (!IsQoSDataFrame(skb->data)){
		return;
	}
	if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)){
		return;
	}
#ifdef TO_DO_LIST
	if(pTcb->PacketLength >= 4096)
		return;
	if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
		return; 
#endif

	if(tcb_desc->bdhcp || ieee->CntAfterLink<2){
		return;
	}
	
	if(pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION){
		return;
	}	

	if(!ieee->GetNmodeSupportBySecCfg(ieee->dev)){
		return; 
	}
	if(pHTInfo->bCurrentAMPDUEnable){
		if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)){
			printk("%s: can't get TS\n", __func__);
			return;
		}
		if (pTxTs->TxAdmittedBARecord.bValid == false){
			if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA)) {
				;
			} else if (tcb_desc->bdhcp == 1){
				;
			} else if (!pTxTs->bDisable_AddBa){
				TsStartAddBaProcess(ieee, pTxTs);
			}
			goto FORCED_AGG_SETTING;
		}
		else if (pTxTs->bUsingBa == false)
		{
			if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
				pTxTs->bUsingBa = true;
			else
				goto FORCED_AGG_SETTING;
		}
#ifndef _RTL8192_EXT_PATCH_
#ifndef RTL8192S_WAPI_SUPPORT  
		if (ieee->iw_mode == IW_MODE_INFRA 
#ifdef ASL
			|| (ieee->iw_mode == IW_MODE_APSTA && ieee->state == RTLLIB_LINKED)
#endif
			)
#endif
#endif
		{
			tcb_desc->bAMPDUEnable = true;
			tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
			tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
		}
	}
FORCED_AGG_SETTING:
	switch(pHTInfo->ForcedAMPDUMode )
	{
		case HT_AGG_AUTO:
			break;

		case HT_AGG_FORCE_ENABLE:
			tcb_desc->bAMPDUEnable = true;
			tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
			tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
			break;

		case HT_AGG_FORCE_DISABLE:
			tcb_desc->bAMPDUEnable = false;
			tcb_desc->ampdu_density = 0;
			tcb_desc->ampdu_factor = 0;
			break;

	}	
		return;
}
VOID
IndicateRxReorderList(
	IN	PADAPTER				Adapter,
	IN	PRX_TS_RECORD			pTS,
	IN	BOOLEAN					bForced
	)
{
	PMGNT_INFO			pMgntInfo = &Adapter->MgntInfo;
	PRT_HIGH_THROUGHPUT	pHTInfo = pMgntInfo->pHTInfo;
	PRX_REORDER_ENTRY 	pReorderEntry = NULL;
	u2Byte				index = 0;
	BOOLEAN				bPktInBuf = FALSE;
//	PRT_RFD				pRfdIndicateArray[REORDER_WIN_SIZE];
	PRT_RFD				*pRfdIndicateArray;
	PRT_GEN_TEMP_BUFFER 	pGenBuf;

	Adapter->rxReorderIndEnterCnt++;

	if(PlatformAtomicExchange(&Adapter->rxReorderRefCount, TRUE) == TRUE)
	{
		Adapter->rxReorderIndRejectCnt[0]++;
		RT_TRACE(COMP_INIT, DBG_LOUD, ("IndicateRxReorderList(): There is already another thread running by AtomicExchange, happened %d times!!!\n", Adapter->rxReorderIndRejectCnt[0]));
		return;
	}

	// Check if there is any other indication thread running.
	if(pTS->RxIndicateState == RXTS_INDICATE_PROCESSING)
	{
		PlatformAtomicExchange(&Adapter->rxReorderRefCount, FALSE);
		Adapter->rxReorderIndRejectCnt[1]++;
		RT_TRACE(COMP_INIT, DBG_LOUD, ("IndicateRxReorderList(): There is already another thread running by RXTS_INDICATE_PROCESSING, happened %d times!!!\n", Adapter->rxReorderIndRejectCnt[1]));
		return;
	}

	// Handling some condition for forced indicate case.
	if(bForced)
	{
		if(RTIsListEmpty(&pTS->RxPendingPktList))
		{
			PlatformAtomicExchange(&Adapter->rxReorderRefCount, FALSE);
			Adapter->rxReorderIndRejectCnt[2]++;
			RT_TRACE(COMP_INIT, DBG_LOUD, ("IndicateRxReorderList(): There is already another thread running by ListEmpty, happened %d times!!!\n", Adapter->rxReorderIndRejectCnt[2]));
			return;
		}
		else
		{
			pReorderEntry = (PRX_REORDER_ENTRY)RTGetHeadList(&pTS->RxPendingPktList);
			pTS->RxIndicateSeq = pReorderEntry->SeqNum;
		}
	}

	Adapter->rxReorderIndAllowCnt++;

	pGenBuf = GetGenTempBuffer (Adapter, sizeof(PRT_RFD)*REORDER_WIN_SIZE);
	pRfdIndicateArray = (PRT_RFD *)pGenBuf->Buffer.Ptr;

	// Prepare indication list and indication.
	do{
		// Check if there is any packet need indicate.
		while(!RTIsListEmpty(&pTS->RxPendingPktList))
		{
			pReorderEntry = (PRX_REORDER_ENTRY)RTGetHeadList(&pTS->RxPendingPktList);

			if(!SN_LESS(pTS->RxIndicateSeq, pReorderEntry->SeqNum))
			{
				// This protect buffer from overflow.
				if(index >= REORDER_WIN_SIZE)
				{
					RT_ASSERT(FALSE, ("IndicateRxReorderList(): Buffer overflow!! \n"));
					bPktInBuf = TRUE;
					break;
				}
				if(index > 0)
				{
					if(PlatformCompareMemory(pReorderEntry->pRfd->Address3,pRfdIndicateArray[index-1]->Address3,6) != 0)		
					{
						bPktInBuf = TRUE;
						break;
					}
				}
			
				pReorderEntry = (PRX_REORDER_ENTRY)RTRemoveHeadList(&pTS->RxPendingPktList);

				if(SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
					pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;

				RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("RxReorderIndicatePacket(): Packets indication!! IndicateSeq: %d\n",  pReorderEntry->SeqNum));
				pRfdIndicateArray[index] = pReorderEntry->pRfd;
				index++;
				
				RTInsertTailList(&pMgntInfo->RxReorder_Unused_List, &pReorderEntry->List);
			}
			else
			{
				bPktInBuf = TRUE;
				break;
			}
		}

		// Handling pending timer. Set this timer to prevent from long time Rx buffering.
		if(index>0)
		{
			// Cancel previous pending timer.
			{
				PlatformCancelTimer(Adapter, &pTS->RxPktPendingTimer);

				// Set this as a lock to make sure that only one thread is indicating packet.
				pTS->RxIndicateState = RXTS_INDICATE_PROCESSING;
			}

			// Indicate packets
			RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!! \n"));

			// Packets indication.
			DrvIFIndicatePackets(Adapter, pRfdIndicateArray, index);

			// Update local variables.
			//bPktInBuf = FALSE;
			index = 0;
		}
		else
		{
			break;
		}
	}while(TRUE);

	ReturnGenTempBuffer(Adapter, pGenBuf);

	// Release the indication lock and set to new indication step.
	if(bPktInBuf)
	{
		u1Byte	set_penf_timer=FALSE;
		
		{
			if(pTS->RxIndicateState != RXTS_INDICATE_REORDER)
				set_penf_timer = TRUE;
		}

		if (set_penf_timer == TRUE)
		{
			// Set new pending timer.
			pTS->RxIndicateState = RXTS_INDICATE_REORDER;
			PlatformSetTimer(Adapter, &pTS->RxPktPendingTimer, pHTInfo->RxReorderPendingTime);
		}
	}
	else
	{
		pTS->RxIndicateState = RXTS_INDICATE_IDLE;
	}

	PlatformAtomicExchange(&Adapter->rxReorderRefCount, FALSE);
}