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; }
/******************************************************************************************************************** *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; } }
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); }
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; }
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; }
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; }
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); }