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