VOID DoBulkIn(IN RTMP_ADAPTER *pAd) { PRX_CONTEXT pRxContext; PURB pUrb; int ret = 0; unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE)) { RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); return; } pRxContext->InUse = TRUE; pRxContext->IRPPending = TRUE; pAd->PendingRx++; pAd->BulkInReq++; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); // Init Rx context descriptor NdisZeroMemory(pRxContext->TransferBuffer, pRxContext->BulkInOffset); RTUSBInitRxDesc(pAd, pRxContext); pUrb = pRxContext->pUrb; if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { // fail RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pAd->PendingRx--; pAd->BulkInReq--; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret)); } else { // success ASSERT((pRxContext->InUse == pRxContext->IRPPending)); //printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex); } }
/* ======================================================================== Routine Description: This routine is used to do insert packet into power-saveing queue. Arguments: pAd: Pointer to our adapter pPacket: Pointer to send packet pMacEntry: portint to entry of MacTab. the pMacEntry store attribute of client (STA). QueIdx: Priority queue idex. Return Value: NDIS_STATUS_SUCCESS:If succes to queue the packet into TxSwQueue. NDIS_STATUS_FAILURE: If failed to do en-queue. ======================================================================== */ NDIS_STATUS RtmpInsertPsQueue( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket, IN MAC_TABLE_ENTRY *pMacEntry, IN UCHAR QueIdx) { ULONG IrqFlags; #ifdef UAPSD_SUPPORT /* put the U-APSD packet to its U-APSD queue by AC ID */ UINT32 ac_id = QueIdx - QID_AC_BE; /* should be >= 0 */ if (UAPSD_MR_IS_UAPSD_AC(pMacEntry, ac_id)) { UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, ac_id); } else #endif /* UAPSD_SUPPORT */ { if (pMacEntry->PsQueue.Number >= MAX_PACKETS_IN_PS_QUEUE) { RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } else { DBGPRINT(RT_DEBUG_TRACE, ("legacy ps> queue a packet!\n")); RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); InsertTailQueue(&pMacEntry->PsQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); } } #ifdef CONFIG_AP_SUPPORT /* mark corresponding TIM bit in outgoing BEACON frame */ #ifdef UAPSD_SUPPORT if (UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(pMacEntry, QueIdx)) { /* 1. the station is UAPSD station; 2. one of AC is non-UAPSD (legacy) AC; 3. the destinated AC of the packet is UAPSD AC. */ /* So we can not set TIM bit due to one of AC is legacy AC */ } else #endif /* UAPSD_SUPPORT */ { WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid); } #endif /* CONFIG_AP_SUPPORT */ return NDIS_STATUS_SUCCESS; }
VOID MtEnqTxSwqFromPsQueue(RTMP_ADAPTER *pAd, UCHAR qidx, STA_TR_ENTRY *tr_entry) { ULONG IrqFlags = 0; //struct tx_swq_fifo *fifo_swq; QUEUE_ENTRY *pQEntry; QUEUE_HEADER *pAcPsQue; QUEUE_HEADER *pAcTxQue; #ifdef UAPSD_SUPPORT MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[tr_entry->wcid]; #endif /* UAPSD_SUPPORT */ //fifo_swq = &pAd->tx_swq[qidx]; pAcPsQue = &tr_entry->ps_queue; pAcTxQue = &tr_entry->tx_queue[qidx]; RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); #ifdef UAPSD_SUPPORT if (UAPSD_MR_IS_UAPSD_AC(pEntry, qidx)) { while(pAcPsQue->Head) { pQEntry = RemoveTailQueue(pAcPsQue); UAPSD_PacketEnqueue(pAd, pEntry, PACKET_TO_QUEUE_ENTRY(pQEntry), qidx, TRUE); } } else #endif /* UAPSD_SUPPORT */ { /*check and insert PS Token queue*/ if(pAcPsQue->Number > 0 && tr_entry->wcid > 0 && tr_entry->wcid < MAX_LEN_OF_TR_TABLE) { rtmp_ps_enq(pAd,tr_entry); DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS, ("pAcPsQue->Number=%d,PS:%d\n",pAcPsQue->Number,tr_entry->PsTokenFlag)); } while(pAcPsQue->Head) { pQEntry = RemoveTailQueue(pAcPsQue); if(tr_entry->enqCount > SQ_ENQ_NORMAL_MAX) { RELEASE_NDIS_PACKET(pAd, QUEUE_ENTRY_TO_PACKET(pQEntry), NDIS_STATUS_FAILURE); continue; } InsertHeadQueue(pAcTxQue, pQEntry); #ifdef LIMIT_GLOBAL_SW_QUEUE TR_ENQ_COUNT_INC(tr_entry, &pAd->TxSwQueue[qidx]); #else /* LIMIT_GLOBAL_SW_QUEUE */ TR_ENQ_COUNT_INC(tr_entry); #endif /* ! LIMIT_GLOBAL_SW_QUEUE */ } } RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); return; }
void DoBulkIn(struct rt_rtmp_adapter *pAd) { struct rt_rx_context *pRxContext; PURB pUrb; int ret = 0; unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE)) { RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); return; } pRxContext->InUse = TRUE; pRxContext->IRPPending = TRUE; pAd->PendingRx++; pAd->BulkInReq++; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); /* Init Rx context descriptor */ NdisZeroMemory(pRxContext->TransferBuffer, pRxContext->BulkInOffset); RTUSBInitRxDesc(pAd, pRxContext); pUrb = pRxContext->pUrb; ret = RTUSB_SUBMIT_URB(pUrb); if (ret != 0) { /* fail */ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pAd->PendingRx--; pAd->BulkInReq--; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret)); } else { /* success */ ASSERT((pRxContext->InUse == pRxContext->IRPPending)); /*printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex); */ } }
/* ======================================================================== Routine Description: Arguments: Return Value: Note: PsPoll use BulkOutPipeId = 0 ======================================================================== */ void RTUSBBulkOutPsPoll(struct rt_rtmp_adapter *pAd) { struct rt_tx_context *pPsPollContext = &(pAd->PsPollContext); PURB pUrb; int ret = 0; unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); return; } pAd->BulkOutPending[0] = TRUE; pAd->watchDogTxPendingCnt[0] = 1; pPsPollContext->IRPPending = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); /* Clear PS-Poll bulk flag */ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); /* Init Tx context descriptor */ RTUSBInitTxDesc(pAd, pPsPollContext, MGMTPIPEIDX, (usb_complete_t) RTUSBBulkOutPsPollComplete); pUrb = pPsPollContext->pUrb; ret = RTUSB_SUBMIT_URB(pUrb); if (ret != 0) { RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; pPsPollContext->IRPPending = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutPsPoll: Submit Tx URB failed %d\n", ret)); return; } }
VOID RTUSBBulkOutPsPoll( IN PRTMP_ADAPTER pAd) { PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext); PURB pUrb; int ret = 0; unsigned long IrqFlags; RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); return; } pAd->BulkOutPending[0] = TRUE; pAd->watchDogTxPendingCnt[0] = 1; pPsPollContext->IRPPending = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); RTUSBInitTxDesc(pAd, pPsPollContext, MGMTPIPEIDX, (usb_complete_t)RTUSBBulkOutPsPollComplete); pUrb = pPsPollContext->pUrb; if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; pPsPollContext->IRPPending = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutPsPoll: Submit Tx URB failed %d\n", ret)); return; } }
/* ======================================================================== Routine Description: This subroutine will scan through releative ring descriptor to find out avaliable free ring descriptor and compare with request size. Arguments: pAd Pointer to our adapter RingType Selected Ring Return Value: NDIS_STATUS_FAILURE Not enough free descriptor NDIS_STATUS_SUCCESS Enough free descriptor Note: ======================================================================== */ NDIS_STATUS RTUSBFreeDescriptorRequest( IN PRTMP_ADAPTER pAd, IN UCHAR BulkOutPipeId, IN UINT32 NumberRequired) { /* UCHAR FreeNumber = 0;*/ /* UINT Index;*/ NDIS_STATUS Status = NDIS_STATUS_FAILURE; unsigned long IrqFlags; HT_TX_CONTEXT *pHTTXContext; pHTTXContext = &pAd->TxContext[BulkOutPipeId]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); #ifdef USB_BULK_BUF_ALIGMENT if( ((pHTTXContext->CurWriteIdx< pHTTXContext->NextBulkIdx ) && (pHTTXContext->NextBulkIdx - pHTTXContext->CurWriteIdx == 1)) || ((pHTTXContext->CurWriteIdx ==(BUF_ALIGMENT_RINGSIZE -1) ) && (pHTTXContext->NextBulkIdx == 0 ))) { RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } else if (pHTTXContext->bCurWriting == TRUE) { DBGPRINT(RT_DEBUG_TRACE,("BUF_ALIGMENT RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", BulkOutPipeId, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } #else if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition) && ((pHTTXContext->CurWritePosition + NumberRequired + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)) { RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < (NumberRequired + LOCAL_TXBUF_SIZE))) { RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } else if (pHTTXContext->bCurWriting == TRUE) { DBGPRINT(RT_DEBUG_TRACE,("RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", BulkOutPipeId, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } #endif /* USB_BULK_BUF_ALIGMENT */ else { Status = NDIS_STATUS_SUCCESS; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); return (Status); }
static void rtusb_dataout_complete(unsigned long data) { PRTMP_ADAPTER pAd; purbb_t pUrb; POS_COOKIE pObj; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId; NTSTATUS Status; unsigned long IrqFlags; pUrb = (purbb_t)data; /* pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; */ pHTTXContext = (PHT_TX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pHTTXContext->pAd; pObj = (POS_COOKIE) pAd->OS_Cookie; /* Status = pUrb->status; */ /* Store BulkOut PipeId */ BulkOutPipeId = pHTTXContext->BulkOutPipeId; pAd->BulkOutDataOneSecCount++; /*DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition, */ /* pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); */ RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; pHTTXContext->IRPPending = FALSE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; if (Status == USB_ST_NOERROR) { pAd->BulkOutComplete++; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->Counters8023.GoodTransmits++; /*RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); /*RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ #ifdef CONFIG_AP_SUPPORT #ifdef UAPSD_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { UAPSD_UnTagFrame(pAd, BulkOutPipeId, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition); } #endif /* UAPSD_AP_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ }
static void rt2870_rts_frame_complete_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pRTSContext; purbb_t pUrb; NTSTATUS Status; unsigned long irqFlag; pUrb = (purbb_t)data; pRTSContext = (PTX_CONTEXT)pUrb->context; pAd = pRTSContext->pAd; Status = pUrb->status; // Reset RTS frame context flags RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); pRTSContext->IRPPending = FALSE; pRTSContext->InUse = FALSE; if (Status == USB_ST_NOERROR) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else // STATUS_OTHER { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out RTS Frame Failed\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); } } RTMP_SEM_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE; RTMP_SEM_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId]); // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); }
static void rtusb_null_frame_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pNullContext; purbb_t pUrb; NTSTATUS Status; unsigned long irqFlag; pUrb = (purbb_t)data; /* pNullContext = (PTX_CONTEXT)pUrb->context; */ pNullContext = (PTX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pNullContext->pAd; /* Status = pUrb->status; */ /* Reset Null frame context flags */ RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); pNullContext->IRPPending = FALSE; pNullContext->InUse = FALSE; pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; if (Status == USB_ST_NOERROR) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else /* STATUS_OTHER */ { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", Status)); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); } } /* Always call Bulk routine, even reset bulk. */ /* The protectioon of rest bulk should be in BulkOut routine */ RTUSBKickBulkOut(pAd); }
int RTUSBFreeDescriptorRelease(struct rt_rtmp_adapter *pAd, u8 BulkOutPipeId) { unsigned long IrqFlags; struct rt_ht_tx_context *pHTTXContext; pHTTXContext = &pAd->TxContext[BulkOutPipeId]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); return (NDIS_STATUS_SUCCESS); }
NDIS_STATUS RTUSBFreeDescriptorRelease(RTMP_ADAPTER *pAd, UCHAR BulkOutPipeId) { HT_TX_CONTEXT *pHTTXContext; unsigned long IrqFlags; pHTTXContext = &pAd->TxContext[BulkOutPipeId]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); return NDIS_STATUS_SUCCESS; }
VOID RTUSBBulkCmdRspEventReceive(PRTMP_ADAPTER pAd) { unsigned long IrqFlags; PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext; RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags); if ((pCmdRspEventContext->InUse) == FALSE && (pCmdRspEventContext->Readable == TRUE)) { RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags); CmdRspEventHandle(pAd); RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags); pCmdRspEventContext->Readable = FALSE; RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags); } else { RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags); } BulkInCmdRspEvent(pAd); }
static void rtusb_dataout_complete(unsigned long data) { PRTMP_ADAPTER pAd; purbb_t pUrb; POS_COOKIE pObj; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId; NTSTATUS Status; unsigned long IrqFlags; pUrb = (purbb_t)data; pHTTXContext = (PHT_TX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pHTTXContext->pAd; pObj = (POS_COOKIE) pAd->OS_Cookie; /* Store BulkOut PipeId */ BulkOutPipeId = pHTTXContext->BulkOutPipeId; pAd->BulkOutDataOneSecCount++; RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; pHTTXContext->IRPPending = FALSE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; if (Status == USB_ST_NOERROR) { pAd->BulkOutComplete++; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->Counters8023.GoodTransmits++; /*RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); /*RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ #ifdef UAPSD_SUPPORT #ifdef CONFIG_AP_SUPPORT #ifdef RT_CFG80211_P2P_SUPPORT if (RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) #else IF_DEV_CONFIG_OPMODE_ON_AP(pAd) #endif /* RT_CFG80211_P2P_SUPPORT */ { UAPSD_UnTagFrame(pAd, BulkOutPipeId, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition); } #endif /* CONFIG_AP_SUPPORT */ #endif /* UAPSD_SUPPORT */ } else {
/* ======================================================================== Routine Description: This subroutine will scan through releative ring descriptor to find out avaliable free ring descriptor and compare with request size. Arguments: pAd Pointer to our adapter RingType Selected Ring Return Value: NDIS_STATUS_FAILURE Not enough free descriptor NDIS_STATUS_SUCCESS Enough free descriptor Note: ======================================================================== */ int RTUSBFreeDescriptorRequest(struct rt_rtmp_adapter *pAd, u8 BulkOutPipeId, u32 NumberRequired) { /* u8 FreeNumber = 0; */ /* u32 Index; */ int Status = NDIS_STATUS_FAILURE; unsigned long IrqFlags; struct rt_ht_tx_context *pHTTXContext; pHTTXContext = &pAd->TxContext[BulkOutPipeId]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition) && ((pHTTXContext->CurWritePosition + NumberRequired + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)) { RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < (NumberRequired + LOCAL_TXBUF_SIZE))) { RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } else if (pHTTXContext->bCurWriting == TRUE) { DBGPRINT(RT_DEBUG_TRACE, ("RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", BulkOutPipeId, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } else { Status = NDIS_STATUS_SUCCESS; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); return (Status); }
/* ======================================================================== Routine Description: This routine is used to do insert packet into power-saveing queue. Arguments: pAd: Pointer to our adapter pPacket: Pointer to send packet pMacEntry: portint to entry of MacTab. the pMacEntry store attribute of client (STA). QueIdx: Priority queue idex. Return Value: NDIS_STATUS_SUCCESS:If succes to queue the packet into TxSwQueue. NDIS_STATUS_FAILURE: If failed to do en-queue. ======================================================================== */ NDIS_STATUS RtmpInsertPsQueue( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket, IN MAC_TABLE_ENTRY *pMacEntry, IN UCHAR QueIdx) { ULONG IrqFlags; #ifdef UAPSD_SUPPORT /* put the U-APSD packet to its U-APSD queue by AC ID */ UINT32 ac_id = QueIdx - QID_AC_BE; /* should be >= 0 */ if (UAPSD_MR_IS_UAPSD_AC(pMacEntry, ac_id)) { UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, ac_id); #ifdef DOT11Z_TDLS_SUPPORT TDLS_UAPSDP_TrafficIndSend(pAd, pMacEntry->Addr); #endif /* DOT11Z_TDLS_SUPPORT */ } else #endif /* UAPSD_SUPPORT */ { if (pMacEntry->PsQueue.Number >= MAX_PACKETS_IN_PS_QUEUE) { RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } else { DBGPRINT(RT_DEBUG_TRACE, ("legacy ps> queue a packet!\n")); RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); InsertTailQueue(&pMacEntry->PsQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); } } return NDIS_STATUS_SUCCESS; }
/* ======================================================================== Routine Description: Process TX Rings DMA Done interrupt, running in DPC level Arguments: Adapter Pointer to our adapter Return Value: None IRQL = DISPATCH_LEVEL ======================================================================== */ BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( IN PRTMP_ADAPTER pAd, IN INT_SOURCE_CSR_STRUC TxRingBitmap) { // UCHAR Count = 0; unsigned long IrqFlags; BOOLEAN bReschedule = FALSE; // Make sure Tx ring resource won't be used by other threads //NdisAcquireSpinLock(&pAd->TxRingLock); RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); if (TxRingBitmap.field.Ac0DmaDone) bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); if (TxRingBitmap.field.HccaDmaDone) bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA); if (TxRingBitmap.field.Ac3DmaDone) bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO); if (TxRingBitmap.field.Ac2DmaDone) bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI); if (TxRingBitmap.field.Ac1DmaDone) bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); // Make sure to release Tx ring resource //NdisReleaseSpinLock(&pAd->TxRingLock); RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); // Dequeue outgoing frames from TxSwQueue[] and process it RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); return bReschedule; }
static void rtmp_ac0_dma_done_tasklet(unsigned long data) { UINT32 irqsave; UINT32 irqMask; PRTMP_ADAPTER pAdapter = (PRTMP_ADAPTER) data; INT_SOURCE_CSR_STRUC IntSource; /* device had been closed */ if (RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_REMOVE_IN_PROGRESS)) { return; } IntSource.word = 0; IntSource.field.Ac0DmaDone = 1; RTMPHandleTxRingDmaDoneInterrupt(pAdapter, IntSource); RTMP_IRQ_LOCK(irqsave); /* * double check to avoid rotting packet */ if (pAdapter->Rtmp_Masked_Int & RTMP_MASK_INT_AC0_DMA_DONE) { pAdapter->Rtmp_Masked_Int &= ~RTMP_MASK_INT_AC0_DMA_DONE; tasklet_hi_schedule(&pAdapter->ac0_dma_done_task); } else { /* enable ac0 interrupt */ RTMP_IO_READ32(pAdapter, INT_MASK_CSR, &irqMask); RTMP_IO_WRITE32(pAdapter, INT_MASK_CSR, irqMask & ~RTMP_MASK_INT_AC0_DMA_DONE); pAdapter->ac0_dma_done_running = FALSE; } RTMP_IRQ_UNLOCK(irqsave); }
VOID RtmpUSB_FinalWriteTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN USHORT totalMPDUSize, IN USHORT TxIdx) { UCHAR QueIdx; HT_TX_CONTEXT *pHTTXContext; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; UINT32 USBDMApktLen, padding; unsigned long IrqFlags; PUCHAR pWirelessPacket; QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (pHTTXContext->bCurWriting == TRUE) { fillOffset = pHTTXContext->CurWritePosition; if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition)) && (pHTTXContext->bCopySavePad == TRUE)) pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]); else pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]); pTxInfo = (PTXINFO_STRUC)(pWirelessPacket); USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE; padding = (4 - (USBDMApktLen % 4)) & 0x03; USBDMApktLen += padding; pTxInfo->USBDMATxPktLen = USBDMApktLen; pTxWI= (PTXWI_STRUC)(pWirelessPacket + TXINFO_SIZE); pTxWI->MPDUtotalByteCount = totalMPDUSize; pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen); if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT) { pHTTXContext->CurWritePosition = 8; pTxInfo->SwUseLastRound = 1; } pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]); NdisZeroMemory(pWirelessPacket, padding + 8); pHTTXContext->bCurWriting = FALSE; } else { DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n")); } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); }
USHORT RtmpUSB_WriteMultiTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR frameNum, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if(frameNum == 0) { Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->CurWritePosition += 8; pHTTXContext->ENextBulkOutPosition += 8; } fillOffset = pHTTXContext->CurWritePosition; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE , FALSE); NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); pHTTXContext->CurWriteRealPos += pTxBlk->Priv; pWirelessPacket += pTxBlk->Priv; } } else { Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); pWirelessPacket += (pTxBlk->MpduHeaderLen); pTxBlk->Priv += pTxBlk->MpduHeaderLen; } else { DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); Status = NDIS_STATUS_FAILURE; } } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); goto done; } NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; pTxBlk->Priv += pTxBlk->SrcBufLen; done: RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return(Status); }
u16 RtmpUSB_WriteFragTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, u8 fragNum, u16 * FreeNumber) { struct rt_ht_tx_context *pHTTXContext; u16 hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */ u32 fillOffset; struct rt_txinfo *pTxInfo; struct rt_txwi *pTxWI; u8 *pWirelessPacket = NULL; u8 QueIdx; int Status; unsigned long IrqFlags; u32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN TxQLastRound = FALSE; /* */ /* get Tx Ring Resource & Dma Buffer address */ /* */ QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if (fragNum == 0) { /* Check if we have enough space for this bulk-out batch. */ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; /* Reserve space for 8 bytes padding. */ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return (Status); } } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return (Status); } } NdisZeroMemory((u8 *)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Build our URB for USBD */ DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */ RTMPWriteTxInfo(pAd, pTxInfo, (u16)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid */ , FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->USBDMATxburst = 0; if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906) > MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; TxQLastRound = TRUE; } } else { pTxInfo->USBDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); /* Zero the last padding. */ pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame. */ pHTTXContext->CurWritePosition += pTxBlk->Priv; if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; /* Finally, set bCurWriting as FALSE */ pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* succeed and release the skb buffer */ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return (Status); }
/* Must be run in Interrupt context This function handle RT2870 specific TxDesc and cpu index update and kick the packet out. */ int RtmpUSBMgmtKickOut(struct rt_rtmp_adapter *pAd, u8 QueIdx, void *pPacket, u8 *pSrcBufVA, u32 SrcBufLen) { struct rt_txinfo *pTxInfo; unsigned long BulkOutSize; u8 padLen; u8 *pDest; unsigned long SwIdx = pAd->MgmtRing.TxCpuIdx; struct rt_tx_context *pMLMEContext = (struct rt_tx_context *)pAd->MgmtRing.Cell[SwIdx].AllocVa; unsigned long IrqFlags; pTxInfo = (struct rt_txinfo *)(pSrcBufVA); /* Build our URB for USBD */ BulkOutSize = SrcBufLen; BulkOutSize = (BulkOutSize + 3) & (~3); RTMPWriteTxInfo(pAd, pTxInfo, (u16)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); BulkOutSize += 4; /* Always add 4 extra bytes at every packet. */ /* If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again. */ if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0) BulkOutSize += 4; padLen = BulkOutSize - SrcBufLen; ASSERT((padLen <= RTMP_PKT_TAIL_PADDING)); /* Now memzero all extra padding bytes. */ pDest = (u8 *)(pSrcBufVA + SrcBufLen); skb_put(GET_OS_PKT_TYPE(pPacket), padLen); NdisZeroMemory(pDest, padLen); RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket; pMLMEContext->TransferBuffer = (struct rt_tx_buffer *)(GET_OS_PKT_DATAPTR(pPacket)); /* Length in TxInfo should be 8 less than bulkout size. */ pMLMEContext->BulkOutSize = BulkOutSize; pMLMEContext->InUse = TRUE; pMLMEContext->bWaitingBulkOut = TRUE; /*for debug */ /*hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize)); */ /*pAd->RalinkCounters.KickTxCount++; */ /*pAd->RalinkCounters.OneSecTxDoneCount++; */ /*if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE) */ /* needKickOut = TRUE; */ /* Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX */ pAd->MgmtRing.TxSwFreeIdx--; INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); /*if (needKickOut) */ RTUSBKickBulkOut(pAd); return 0; }
void RtmpUSB_FinalWriteTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, u16 totalMPDUSize, u16 TxIdx) { u8 QueIdx; struct rt_ht_tx_context *pHTTXContext; u32 fillOffset; struct rt_txinfo *pTxInfo; struct rt_txwi *pTxWI; u32 USBDMApktLen, padding; unsigned long IrqFlags; u8 *pWirelessPacket; QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (pHTTXContext->bCurWriting == TRUE) { fillOffset = pHTTXContext->CurWritePosition; if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition - 8) == pHTTXContext->CurWritePosition)) && (pHTTXContext->bCopySavePad == TRUE)) pWirelessPacket = (u8 *)(&pHTTXContext->SavedPad[0]); else pWirelessPacket = (u8 *)(&pHTTXContext->TransferBuffer->field. WirelessPacket[fillOffset]); /* */ /* Update TxInfo->USBDMApktLen , */ /* the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding */ /* */ pTxInfo = (struct rt_txinfo *)(pWirelessPacket); /* Calculate the bulk-out padding */ USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE; padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ USBDMApktLen += padding; pTxInfo->USBDMATxPktLen = USBDMApktLen; /* */ /* Update TXWI->MPDUtotalByteCount , */ /* the length = 802.11 header + payload_of_all_batch_frames */ pTxWI = (struct rt_txwi *) (pWirelessPacket + TXINFO_SIZE); pTxWI->MPDUtotalByteCount = totalMPDUSize; /* */ /* Update the pHTTXContext->CurWritePosition */ /* */ pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen); if ((pHTTXContext->CurWritePosition + 3906) > MAX_TXBULK_LIMIT) { /* Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame. */ pHTTXContext->CurWritePosition = 8; pTxInfo->SwUseLastRound = 1; } pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; /* */ /* Zero the last padding. */ /* */ pWirelessPacket = (&pHTTXContext->TransferBuffer->field. WirelessPacket[fillOffset + pTxBlk->Priv]); NdisZeroMemory(pWirelessPacket, padding + 8); /* Finally, set bCurWriting as FALSE */ pHTTXContext->bCurWriting = FALSE; } else { /* It should not happened now unless we are going to shutdown. */ DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n")); } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); }
u16 RtmpUSB_WriteMultiTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, u8 frameNum, u16 * FreeNumber) { struct rt_ht_tx_context *pHTTXContext; u16 hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length. */ u32 fillOffset; struct rt_txinfo *pTxInfo; struct rt_txwi *pTxWI; u8 *pWirelessPacket = NULL; u8 QueIdx; int Status; unsigned long IrqFlags; /*u32 USBDMApktLen = 0, DMAHdrLen, padding; */ /* */ /* get Tx Ring Resource & Dma Buffer address */ /* */ QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (frameNum == 0) { /* Check if we have enough space for this bulk-out batch. */ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); /* Reserve space for 8 bytes padding. */ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->CurWritePosition += 8; pHTTXContext->ENextBulkOutPosition += 8; } fillOffset = pHTTXContext->CurWritePosition; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field. WirelessPacket[fillOffset]; /* */ /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ /* */ if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD; */ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD; else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD; */ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD; else /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Update the pTxBlk->Priv. */ pTxBlk->Priv = TXINFO_SIZE + TXWI_SIZE + hwHdrLen; /* pTxInfo->USBDMApktLen now just a temp value and will to correct latter. */ RTMPWriteTxInfo(pAd, pTxInfo, (u16)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid */ , FALSE); /* Copy it. */ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv); pHTTXContext->CurWriteRealPos += pTxBlk->Priv; pWirelessPacket += pTxBlk->Priv; } } else { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer. */ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv); pWirelessPacket = &pHTTXContext->TransferBuffer->field. WirelessPacket[fillOffset]; /*hwHdrLen = pTxBlk->MpduHeaderLen; */ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen); pWirelessPacket += (pTxBlk->MpduHeaderLen); pTxBlk->Priv += pTxBlk->MpduHeaderLen; } else { /* It should not happened now unless we are going to shutdown. */ DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n")); Status = NDIS_STATUS_FAILURE; } } /* We unlock it here to prevent the first 8 bytes maybe over-write issue. */ /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext. */ /* 2. An interrupt break our routine and handle bulk-out complete. */ /* 3. In the bulk-out compllete, it need to do another bulk-out, */ /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */ /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */ /* 4. Interrupt complete. */ /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */ /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */ /* and the packet will wrong. */ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); if (Status != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition)); goto done; } /* Copy the frame content into DMA buffer and update the pTxBlk->Priv */ NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; pTxBlk->Priv += pTxBlk->SrcBufLen; done: /* Release the skb buffer here */ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return (Status); }
/* ======================================================================== Routine Description: Arguments: Return Value: Note: MLME use BulkOutPipeId = 0 ======================================================================== */ VOID RTUSBBulkOutMLMEPacket( IN PRTMP_ADAPTER pAd, IN UCHAR Index) { PTX_CONTEXT pMLMEContext; PURB pUrb; int ret = 0; unsigned long IrqFlags; pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; pUrb = pMLMEContext->pUrb; if ((pAd->MgmtRing.TxSwFreeIdx >= MGMT_RING_SIZE) || (pMLMEContext->InUse == FALSE) || (pMLMEContext->bWaitingBulkOut == FALSE)) { /* Clear MLME bulk flag*/ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); return; } RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); if ((pAd->BulkOutPending[MGMTPIPEIDX] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); return; } pAd->BulkOutPending[MGMTPIPEIDX] = TRUE; pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 1; pMLMEContext->IRPPending = TRUE; pMLMEContext->bWaitingBulkOut = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); /* Increase Total transmit byte counter*/ pAd->RalinkCounters.TransmittedByteCount += pMLMEContext->BulkOutSize; /* Clear MLME bulk flag*/ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pMLMEContext->TransferBuffer, TYPE_TXINFO); #endif /* RT_BIG_ENDIAN */ /* Init Tx context descriptor*/ RTUSBInitTxDesc(pAd, pMLMEContext, MGMTPIPEIDX, (usb_complete_t)RtmpUsbBulkOutMLMEPacketComplete); RTUSB_URB_DMA_MAPPING(pUrb); pUrb = pMLMEContext->pUrb; if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutMLMEPacket: Submit MLME URB failed %d\n", ret)); RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 0; pMLMEContext->IRPPending = FALSE; pMLMEContext->bWaitingBulkOut = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); return; } }
/* ======================================================================== Routine Description: Arguments: Return Value: Note: NULL frame use BulkOutPipeId = 0 ======================================================================== */ VOID RTUSBBulkOutNullFrame( IN PRTMP_ADAPTER pAd, IN UCHAR BulkOutPipeId) { PTX_CONTEXT pNullContext; PURB pUrb; int ret = 0; unsigned long IrqFlags; if (BulkOutPipeId == EDCA_AC0_PIPE) pNullContext = &pAd->NullContext[0]; else if (BulkOutPipeId == HCCA_PIPE) pNullContext = &pAd->NullContext[1]; else DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow BulkOut Pipe\n", __FUNCTION__)); RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); if ((pAd->BulkOutPending[BulkOutPipeId] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } pAd->BulkOutPending[BulkOutPipeId] = TRUE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 1; pNullContext->IRPPending = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); /* Increase Total transmit byte counter*/ pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize; /* Clear Null frame bulk flag*/ if (BulkOutPipeId == EDCA_AC0_PIPE) RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); else if (BulkOutPipeId == HCCA_PIPE) RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL_HCCA); else DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow BulkOut Pipe\n", __FUNCTION__)); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pNullContext->TransferBuffer, TYPE_TXINFO); #endif /* RT_BIG_ENDIAN */ /* Init Tx context descriptor*/ /* Init Tx context descriptor*/ if (BulkOutPipeId == EDCA_AC0_PIPE) RTUSBInitTxDesc(pAd, pNullContext, BulkOutPipeId, (usb_complete_t)RtmpUsbBulkOutNullFrameComplete); #if defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) else if (BulkOutPipeId == HCCA_PIPE) RTUSBInitTxDesc(pAd, pNullContext, BulkOutPipeId, (usb_complete_t)RtmpUsbBulkOutHCCANullFrameComplete); #endif /* defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) */ pUrb = pNullContext->pUrb; if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; pNullContext->IRPPending = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutNullFrame: Submit Tx URB failed %d\n", ret)); return; } }
NDIS_STATUS IgmpPktClone( IN PRTMP_ADAPTER pAd, IN PNDIS_PACKET pPacket, IN int IgmpPktInGroup, IN PMULTICAST_FILTER_TABLE_ENTRY pGroupEntry, IN UCHAR QueIdx, IN UINT8 UserPriority, IN PNET_DEV pNetDev) { PNDIS_PACKET pSkbClone = NULL; PMEMBER_ENTRY pMemberEntry = NULL; MAC_TABLE_ENTRY *pMacEntry = NULL; USHORT Aid; SST Sst = SST_ASSOC; UCHAR PsMode = PWR_ACTIVE; UCHAR Rate; unsigned long IrqFlags; int MacEntryIdx; BOOLEAN bContinue; PUCHAR pMemberAddr = NULL; bContinue = FALSE; if ((IgmpPktInGroup == IGMP_IN_GROUP) && (pGroupEntry == NULL)) return NDIS_STATUS_FAILURE; if (IgmpPktInGroup == IGMP_IN_GROUP) { pMemberEntry = (PMEMBER_ENTRY)pGroupEntry->MemberList.pHead; if (pMemberEntry != NULL) { pMemberAddr = pMemberEntry->Addr; pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); bContinue = TRUE; } } else if (IgmpPktInGroup == IGMP_PKT) { for(MacEntryIdx=1; MacEntryIdx<MAX_NUMBER_OF_MAC; MacEntryIdx++) { pMemberAddr = pAd->MacTab.Content[MacEntryIdx].Addr; pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) && get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev) { pMemberAddr = pMacEntry->Addr; bContinue = TRUE; break; } } } else { return NDIS_STATUS_FAILURE; } /* check all members of the IGMP group. */ while(bContinue == TRUE) { if (pMacEntry && (Sst == SST_ASSOC)) { OS_PKT_CLONE(pAd, pPacket, pSkbClone, MEM_ALLOC_FLAG); if ((pSkbClone) ) { RTMP_SET_PACKET_WCID(pSkbClone, (UCHAR)pMacEntry->Aid); /* Pkt type must set to PKTSRC_NDIS. */ /* It cause of the deason that APHardTransmit() */ /* doesn't handle PKTSRC_DRIVER pkt type in version 1.3.0.0. */ RTMP_SET_PACKET_SOURCE(pSkbClone, PKTSRC_NDIS); } else { if (IgmpPktInGroup == IGMP_IN_GROUP) { pMemberEntry = pMemberEntry->pNext; if (pMemberEntry != NULL) { pMemberAddr = pMemberEntry->Addr; pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); bContinue = TRUE; } else bContinue = FALSE; } else if (IgmpPktInGroup == IGMP_PKT) { for(MacEntryIdx=pMacEntry->Aid + 1; MacEntryIdx<MAX_NUMBER_OF_MAC; MacEntryIdx++) { pMemberAddr = pAd->MacTab.Content[MacEntryIdx].Addr; pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) && get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev) { pMemberAddr = pMacEntry->Addr; bContinue = TRUE; break; } } if (MacEntryIdx == MAX_NUMBER_OF_MAC) bContinue = FALSE; } else bContinue = FALSE; continue; } if (PsMode == PWR_SAVE) { APInsertPsQueue(pAd, pSkbClone, pMacEntry, QueIdx); } else { /* insert the pkt to TxSwQueue. */ if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE) { #ifdef BLOCK_NET_IF StopNetIfQueue(pAd, QueIdx, pSkbClone); #endif /* BLOCK_NET_IF */ RELEASE_NDIS_PACKET(pAd, pSkbClone, NDIS_STATUS_FAILURE); return NDIS_STATUS_FAILURE; } else { RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pSkbClone)); RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); } } #ifdef DOT11_N_SUPPORT RTMP_BASetup(pAd, pMacEntry, UserPriority); #endif /* DOT11_N_SUPPORT */ } if (IgmpPktInGroup == IGMP_IN_GROUP) { pMemberEntry = pMemberEntry->pNext; if (pMemberEntry != NULL) { pMemberAddr = pMemberEntry->Addr; pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); bContinue = TRUE; } else bContinue = FALSE; } else if (IgmpPktInGroup == IGMP_PKT) { for(MacEntryIdx=pMacEntry->Aid + 1; MacEntryIdx<MAX_NUMBER_OF_MAC; MacEntryIdx++) { pMemberAddr = pAd->MacTab.Content[MacEntryIdx].Addr; pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate); if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) && get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev) { pMemberAddr = pMacEntry->Addr; bContinue = TRUE; break; } } if (MacEntryIdx == MAX_NUMBER_OF_MAC) bContinue = FALSE; } else bContinue = FALSE; } return NDIS_STATUS_SUCCESS; }
USHORT RtmpUSB_WriteFragTxResource( IN PRTMP_ADAPTER pAd, IN TX_BLK *pTxBlk, IN UCHAR fragNum, OUT USHORT *FreeNumber) { HT_TX_CONTEXT *pHTTXContext; USHORT hwHdrLen; UINT32 fillOffset; TXINFO_STRUC *pTxInfo; TXWI_STRUC *pTxWI; PUCHAR pWirelessPacket = NULL; UCHAR QueIdx; NDIS_STATUS Status; unsigned long IrqFlags; UINT32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN TxQLastRound = FALSE; QueIdx = pTxBlk->QueIdx; pHTTXContext = &pAd->TxContext[QueIdx]; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; if(fragNum == 0) { Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pTxBlk->Priv = 0; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } else { Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE); if (Status == NDIS_STATUS_SUCCESS) { fillOffset += pTxBlk->Priv; } else { RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); return(Status); } } NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE); pTxInfo = (PTXINFO_STRUC)(&pTxBlk->HeaderBuf[0]); pTxWI= (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]; hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; USBDMApktLen += padding; pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen); RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE , FALSE); if (fragNum == pTxBlk->TotalFragNum) { pTxInfo->USBDMATxburst = 0; if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; TxQLastRound = TRUE; } } else { pTxInfo->USBDMATxburst = 1; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); if (fragNum == pTxBlk->TotalFragNum) { RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext->CurWritePosition += pTxBlk->Priv; if (TxQLastRound == TRUE) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); } return(Status); }
int RtmpUSBMgmtKickOut( IN RTMP_ADAPTER *pAd, IN UCHAR QueIdx, IN PNDIS_PACKET pPacket, IN PUCHAR pSrcBufVA, IN UINT SrcBufLen) { PTXINFO_STRUC pTxInfo; ULONG BulkOutSize; UCHAR padLen; PUCHAR pDest; ULONG SwIdx = pAd->MgmtRing.TxCpuIdx; PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa; unsigned long IrqFlags; pTxInfo = (PTXINFO_STRUC)(pSrcBufVA); BulkOutSize = SrcBufLen; BulkOutSize = (BulkOutSize + 3) & (~3); RTMPWriteTxInfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE); BulkOutSize += 4; if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0) BulkOutSize += 4; padLen = BulkOutSize - SrcBufLen; ASSERT((padLen <= RTMP_PKT_TAIL_PADDING)); pDest = (PUCHAR)(pSrcBufVA + SrcBufLen); skb_put(GET_OS_PKT_TYPE(pPacket), padLen); NdisZeroMemory(pDest, padLen); RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket; pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket)); pMLMEContext->BulkOutSize = BulkOutSize; pMLMEContext->InUse = TRUE; pMLMEContext->bWaitingBulkOut = TRUE; pAd->MgmtRing.TxSwFreeIdx--; INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); RTUSBKickBulkOut(pAd); return 0; }
u16 RtmpUSB_WriteSingleTxResource(struct rt_rtmp_adapter *pAd, struct rt_tx_blk *pTxBlk, IN BOOLEAN bIsLast, u16 * FreeNumber) { struct rt_ht_tx_context *pHTTXContext; u16 hwHdrLen; u32 fillOffset; struct rt_txinfo *pTxInfo; struct rt_txwi *pTxWI; u8 *pWirelessPacket; u8 QueIdx; unsigned long IrqFlags; int Status; u32 USBDMApktLen = 0, DMAHdrLen, padding; BOOLEAN bTxQLastRound = FALSE; /* For USB, didn't need PCI_MAP_SINGLE() */ /*SrcBufPA = PCI_MAP_SINGLE(pAd, (char *) pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, PCI_DMA_TODEVICE); */ /* */ /* get Tx Ring Resource & Dma Buffer address */ /* */ QueIdx = pTxBlk->QueIdx; RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext = &pAd->TxContext[QueIdx]; fillOffset = pHTTXContext->CurWritePosition; /* Check ring full. */ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext); if (Status == NDIS_STATUS_SUCCESS) { pHTTXContext->bCurWriting = TRUE; pTxInfo = (struct rt_txinfo *)(&pTxBlk->HeaderBuf[0]); pTxWI = (struct rt_txwi *) (&pTxBlk->HeaderBuf[TXINFO_SIZE]); /* Reserve space for 8 bytes padding. */ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)) { pHTTXContext->ENextBulkOutPosition += 8; pHTTXContext->CurWritePosition += 8; fillOffset += 8; } pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pWirelessPacket = &pHTTXContext->TransferBuffer->field. WirelessPacket[fillOffset]; /* copy TXWI + WLAN Header + LLC into DMA Header Buffer */ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4); */ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; /* Build our URB for USBD */ DMAHdrLen = TXWI_SIZE + hwHdrLen; USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen; padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment */ USBDMApktLen += padding; pTxBlk->Priv = (TXINFO_SIZE + USBDMApktLen); /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload */ RTMPWriteTxInfo(pAd, pTxInfo, (u16)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid */ , FALSE); if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT) { pTxInfo->SwUseLastRound = 1; bTxQLastRound = TRUE; } NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHdrLen); pWirelessPacket += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); /* We unlock it here to prevent the first 8 bytes maybe over-writed issue. */ /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext. */ /* 2. An interrupt break our routine and handle bulk-out complete. */ /* 3. In the bulk-out compllete, it need to do another bulk-out, */ /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition, */ /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE. */ /* 4. Interrupt complete. */ /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext. */ /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition. */ /* and the packet will wrong. */ pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWI_SIZE + hwHdrLen); RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); pWirelessPacket += pTxBlk->SrcBufLen; NdisZeroMemory(pWirelessPacket, padding + 8); RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); pHTTXContext->CurWritePosition += pTxBlk->Priv; if (bTxQLastRound) pHTTXContext->CurWritePosition = 8; pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition; pHTTXContext->bCurWriting = FALSE; } RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags); /* succeed and release the skb buffer */ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS); return (Status); }