/* ======================================================================== Routine Description: Process MGMT ring DMA done interrupt, running in DPC level Arguments: pAd Pointer to our adapter Return Value: None IRQL = DISPATCH_LEVEL Note: ======================================================================== */ VOID RTMPHandleMgmtRingDmaDoneInterrupt( IN PRTMP_ADAPTER pAd) { PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif PNDIS_PACKET pPacket; // int i; UCHAR FREE = 0; PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; NdisAcquireSpinLock(&pAd->MgmtRingLock); RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) { FREE++; #ifdef RT_BIG_ENDIAN pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #else pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); #endif pTxD->DMADONE = 0; pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; if (pPacket == NULL) continue; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); #endif } NdisReleaseSpinLock(&pAd->MgmtRingLock); #ifdef CONFIG_STA_SUPPORT #endif // CONFIG_STA_SUPPORT // }
/* ======================================================================== Routine Description: Process MGMT ring DMA done interrupt, running in DPC level Arguments: pAd Pointer to our adapter Return Value: None IRQL = DISPATCH_LEVEL Note: ======================================================================== */ void RTMPHandleMgmtRingDmaDoneInterrupt(struct rt_rtmp_adapter *pAd) { struct rt_txd * pTxD; void *pPacket; /* int i; */ u8 FREE = 0; struct rt_rtmp_mgmt_ring *pMgmtRing = &pAd->MgmtRing; NdisAcquireSpinLock(&pAd->MgmtRingLock); RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); while (pMgmtRing->TxSwFreeIdx != pMgmtRing->TxDmaIdx) { FREE++; pTxD = (struct rt_txd *) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx]. AllocVa); pTxD->DMADONE = 0; pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); } NdisReleaseSpinLock(&pAd->MgmtRingLock); }
/* ======================================================================== Routine Description: Process MGMT ring DMA done interrupt, running in DPC level Arguments: pAd Pointer to our adapter Return Value: None IRQL = DISPATCH_LEVEL Note: ======================================================================== */ VOID RTMPHandleMgmtRingDmaDoneInterrupt( IN PRTMP_ADAPTER pAd) { PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif PNDIS_PACKET pPacket; // int i; UCHAR FREE = 0; PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; NdisAcquireSpinLock(&pAd->MgmtRingLock); RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) { FREE++; #ifdef RT_BIG_ENDIAN pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #else pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); #endif pTxD->DMADONE = 0; pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; if (pPacket == NULL) continue; #ifdef CONFIG_AP_SUPPORT #define LMR_FRAME_GET() (GET_OS_PKT_DATAPTR(pPacket)+TXWI_SIZE) #ifdef UAPSD_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, pPacket, LMR_FRAME_GET()); } #endif // UAPSD_AP_SUPPORT // #ifdef WMM_ACM_SUPPORT { HEADER_802_11 *pHeader; /* handle Power Save ADDTS Response */ pHeader = (HEADER_802_11 *)(LMR_FRAME_GET()); if ((pHeader->FC.Type == BTYPE_MGMT) && (pHeader->FC.SubType == SUBTYPE_ACTION)) { ACMP_PsRspDeltsSentOutHandle(pAd, MacTableLookup(pAd, pHeader->Addr1), ((UCHAR *)pHeader)+sizeof(HEADER_802_11)); } } #endif // WMM_ACM_SUPPORT // #endif // CONFIG_AP_SUPPORT // if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); #endif } NdisReleaseSpinLock(&pAd->MgmtRingLock); #ifdef CONFIG_STA_SUPPORT #ifdef WMM_ACM_SUPPORT /* return power save right if possible, ex: 0. sta enter PS mode; 1. sta enters ACTIVE mode; 2. sta sends ADDTS request frame; 3. sta receives ADDTS response frame; 4. sta enter PS mode; (ACMP_StaPsCtrlRightReturn) */ if (ACMR_IS_ENABLED(pAd)) ACMP_StaPsCtrlRightReturn(pAd); /* End of if */ #endif // WMM_ACM_SUPPORT // #endif // CONFIG_STA_SUPPORT // }
BOOLEAN RTMPFreeTXDUponTxDmaDone( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx) { PRTMP_TX_RING pTxRing; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; #endif PNDIS_PACKET pPacket; UCHAR FREE = 0; TXD_STRUC TxD, *pOriTxD; //ULONG IrqFlags; BOOLEAN bReschedule = FALSE; ASSERT(QueIdx < NUM_OF_TX_RING); pTxRing = &pAd->TxRing[QueIdx]; RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) { // RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); #ifdef RALINK_ATE #ifdef RALINK_QA PHEADER_802_11 pHeader80211; if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) { if (pAd->ate.QID == QueIdx) { pAd->ate.TxDoneCount++; pAd->RalinkCounters.KickTxCount++; /* always use QID_AC_BE and FIFO_EDCA */ ASSERT(pAd->ate.QID == 0); pAd->ate.TxAc0++; FREE++; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE); #endif pHeader80211->Sequence = ++pAd->ate.seq; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE); #endif if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount)) { pAd->RalinkCounters.TransmittedByteCount.QuadPart += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); /* get TX_DTX_IDX again */ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); goto kick_out; } else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount)) { DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n")); // Tx status enters idle mode. pAd->ate.TxStatus = 0; } else if (!(pAd->ate.Mode & ATE_TXFRAME)) { /* not complete sending yet, but someone press the Stop TX botton */ DBGPRINT(RT_DEBUG_INFO,("not complete sending yet, but someone pressed the Stop TX bottom\n")); DBGPRINT(RT_DEBUG_INFO,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode)); } else { DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx)); } #ifndef RT_BIG_ENDIAN NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #else RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #endif // RT_BIG_ENDIAN // INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); continue; } } #endif // RALINK_QA // #endif // RALINK_ATE // // static rate also need NICUpdateFifoStaCounters() function. //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) #ifdef VENDOR_FEATURE1_SUPPORT /* Note: Can not take off the NICUpdateFifoStaCounters(); Or the FIFO overflow rate will be high, i.e. > 3% (see the rate by "iwpriv ra0 show stainfo") Based on different platform, try to find the best value to replace '4' here (overflow rate target is about 0%). */ if (++pAd->FifoUpdateRx >= 4) { NICUpdateFifoStaCounters(pAd); pAd->FifoUpdateRx = 0; } #else NICUpdateFifoStaCounters(pAd); #endif // VENDOR_FEATURE1_SUPPORT // /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ FREE++; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; #ifdef CONFIG_AP_SUPPORT #ifdef UAPSD_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { UAPSD_SP_PacketCheck(pAd, pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket, ((UCHAR *)pTxRing->Cell[\ pTxRing->TxSwFreeIdx].DmaBuf.AllocVa)+TXWI_SIZE); } #endif // UAPSD_AP_SUPPORT // #endif // CONFIG_AP_SUPPORT // #ifdef RALINK_ATE /* Execution of this block is not allowed when ATE is running. */ if (!(ATE_ON(pAd))) #endif // RALINK_ATE // { pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; if (pPacket) { #ifdef CONFIG_5VT_ENHANCE if (RTMP_GET_PACKET_5VT(pPacket)) PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); else #endif // CONFIG_5VT_ENHANCE // PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } //Always assign pNdisPacket as NULL after clear pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; if (pPacket) { #ifdef CONFIG_5VT_ENHANCE if (RTMP_GET_PACKET_5VT(pPacket)) PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); else #endif // CONFIG_5VT_ENHANCE // PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } //Always assign pNextNdisPacket as NULL after clear pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; } pAd->RalinkCounters.TransmittedByteCount.QuadPart += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); /* get tx_tdx_idx again */ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #else NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #endif #ifdef RALINK_ATE #ifdef RALINK_QA kick_out: #endif // RALINK_QA // /* ATE_TXCONT mode also need to send some normal frames, so let it in. ATE_STOP must be changed not to be 0xff to prevent it from running into this block. */ if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx)) { // TxDoneCount++ has been done if QA is used. if (pAd->ate.bQATxStart == FALSE) { pAd->ate.TxDoneCount++; } if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE)) { /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */ INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; #ifndef RT_BIG_ENDIAN NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #else RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #endif // kick Tx-Ring RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx); pAd->RalinkCounters.KickTxCount++; } } #endif // RALINK_ATE // // RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); } return bReschedule; }
PNDIS_PACKET GetPacketFromRxRing( IN PRTMP_ADAPTER pAd, OUT PRT28XX_RXD_STRUC pSaveRxD, OUT BOOLEAN *pbReschedule, IN OUT UINT32 *pRxPending) { PRXD_STRUC pRxD; #ifdef RT_BIG_ENDIAN PRXD_STRUC pDestRxD; RXD_STRUC RxD; #endif PNDIS_PACKET pRxPacket = NULL; PNDIS_PACKET pNewPacket; PVOID AllocVa; NDIS_PHYSICAL_ADDRESS AllocPa; BOOLEAN bReschedule = FALSE; RTMP_DMACB *pRxCell; RTMP_SEM_LOCK(&pAd->RxRingLock); if (*pRxPending == 0) { // Get how may packets had been received RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx); if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) { // no more rx packets bReschedule = FALSE; goto done; } // get rx pending count if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; else *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx; } pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx]; #ifdef RT_BIG_ENDIAN pDestRxD = (PRXD_STRUC) pRxCell->AllocVa; RxD = *pDestRxD; pRxD = &RxD; RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); #else // Point to Rx indexed rx ring descriptor pRxD = (PRXD_STRUC) pRxCell->AllocVa; #endif if (pRxD->DDONE == 0) { *pRxPending = 0; // DMAIndx had done but DDONE bit not ready bReschedule = TRUE; goto done; } // return rx descriptor NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); if (pNewPacket) { // unmap the rx buffer PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa, pRxCell->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); pRxPacket = pRxCell->pNdisPacket; pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; pRxCell->pNdisPacket = (PNDIS_PACKET) pNewPacket; pRxCell->DmaBuf.AllocVa = AllocVa; pRxCell->DmaBuf.AllocPa = AllocPa; /* update SDP0 to new buffer of rx packet */ pRxD->SDP0 = AllocPa; } else { //DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n")); pRxPacket = NULL; bReschedule = TRUE; } pRxD->DDONE = 0; // had handled one rx packet *pRxPending = *pRxPending - 1; // update rx descriptor and kick rx #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); #endif INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); done: RTMP_SEM_UNLOCK(&pAd->RxRingLock); *pbReschedule = bReschedule; return pRxPacket; }
/* ======================================================================== Routine Description: Process MGMT ring DMA done interrupt, running in DPC level Arguments: pAd Pointer to our adapter Return Value: None IRQL = DISPATCH_LEVEL Note: ======================================================================== */ VOID RTMPHandleMgmtRingDmaDoneInterrupt( IN PRTMP_ADAPTER pAd) { PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; TXD_STRUC TxD; #endif PNDIS_PACKET pPacket; /* int i;*/ UCHAR FREE = 0; PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing; UINT8 TXWISize = pAd->chipCap.TXWISize; NdisAcquireSpinLock(&pAd->MgmtRingLock); RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx); while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) { FREE++; #ifdef RT_BIG_ENDIAN pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #else pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); #endif /* pTxD->DMADONE = 0; */ pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket; if (pPacket == NULL) { INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); continue; } #define LMR_FRAME_GET() (GET_OS_PKT_DATAPTR(pPacket) + TXWISize) #ifdef UAPSD_SUPPORT #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, pPacket, LMR_FRAME_GET()); } #endif /* CONFIG_AP_SUPPORT */ #endif /* UAPSD_SUPPORT */ #ifdef CONFIG_AP_SUPPORT #endif /* CONFIG_AP_SUPPORT */ if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL; /* flush dcache if no consistent memory is supported */ RTMP_DCACHE_FLUSH(pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocPa, RXD_SIZE); INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); #endif } NdisReleaseSpinLock(&pAd->MgmtRingLock); }
PNDIS_PACKET GetPacketFromRxRing( IN PRTMP_ADAPTER pAd, OUT PRT28XX_RXD_STRUC pSaveRxD, OUT BOOLEAN *pbReschedule, IN OUT UINT32 *pRxPending) { PRXD_STRUC pRxD; #ifdef RT_BIG_ENDIAN PRXD_STRUC pDestRxD; RXD_STRUC RxD; #endif PNDIS_PACKET pRxPacket = NULL; PNDIS_PACKET pNewPacket; PVOID AllocVa; NDIS_PHYSICAL_ADDRESS AllocPa; BOOLEAN bReschedule = FALSE; RTMP_DMACB *pRxCell; RTMP_SEM_LOCK(&pAd->RxRingLock); if (*pRxPending == 0) { /* Get how may packets had been received*/ RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx); if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) { /* no more rx packets*/ bReschedule = FALSE; goto done; } /* get rx pending count*/ if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; else *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx; #ifdef DESC_32B_SUPPORT pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx]; dma_cache_sync(NULL, pRxCell->AllocVa, RXD_SIZE, DMA_FROM_DEVICE); #endif /* DESC_32B_SUPPORT */ } pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx]; /* flush dcache if no consistent memory is supported */ RTMP_DCACHE_FLUSH(pRxCell->AllocPa, RXD_SIZE); #ifdef RT_BIG_ENDIAN pDestRxD = (PRXD_STRUC) pRxCell->AllocVa; RxD = *pDestRxD; pRxD = &RxD; RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); #else /* Point to Rx indexed rx ring descriptor*/ pRxD = (PRXD_STRUC) pRxCell->AllocVa; #endif if (pRxD->DDONE == 0) { *pRxPending = 0; /* DMAIndx had done but DDONE bit not ready*/ bReschedule = TRUE; goto done; } #ifdef DESC_32B_SUPPORT prefetch(&pAd->RxRing.Cell[(pAd->RxRing.RxSwReadIdx + 1) % RX_RING_SIZE].AllocVa); #endif /* DESC_32B_SUPPORT */ /* return rx descriptor*/ NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); if (pNewPacket) { /* unmap the rx buffer*/ PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa, pRxCell->DmaBuf.AllocSize, RTMP_PCI_DMA_FROMDEVICE); /* flush dcache if no consistent memory is supported */ RTMP_DCACHE_FLUSH(pRxCell->DmaBuf.AllocPa, pRxCell->DmaBuf.AllocSize); pRxPacket = pRxCell->pNdisPacket; pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; pRxCell->pNdisPacket = (PNDIS_PACKET) pNewPacket; pRxCell->DmaBuf.AllocVa = AllocVa; pRxCell->DmaBuf.AllocPa = AllocPa; /* flush dcache if no consistent memory is supported */ RTMP_DCACHE_FLUSH(pRxCell->DmaBuf.AllocPa, pRxCell->DmaBuf.AllocSize); /* update SDP0 to new buffer of rx packet */ pRxD->SDP0 = AllocPa; #ifdef RX_DMA_SCATTER pRxD->SDL0 = RX_BUFFER_AGGRESIZE; #endif /* RX_DMA_SCATTER */ } else { /*DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n"));*/ pRxPacket = NULL; bReschedule = TRUE; } /* had handled one rx packet*/ *pRxPending = *pRxPending - 1; #ifndef CACHE_LINE_32B pRxD->DDONE = 0; /* update rx descriptor and kick rx */ #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); #endif #ifdef DESC_32B_SUPPORT dma_cache_sync(NULL, pRxCell->AllocVa, RXD_SIZE, DMA_TO_DEVICE); #endif /* DESC_32B_SUPPORT */ INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); #else /* CACHE_LINE_32B */ /* Because our RXD_SIZE is 16B, but if the cache line size is 32B, we will suffer a problem as below: 1. We flush RXD 0, start address of RXD 0 is 32B-align. Nothing occurs. 2. We flush RXD 1, start address of RXD 1 is 16B-align. Because cache line size is 32B, cache must flush 32B, cannot flush 16B only, so RXD0 and RXD1 will be flushed. But when traffic is busy, maybe RXD0 is updated by MAC, i.e. DDONE bit is 1, so when the cache flushs RXD0, the DDONE bit will be cleared to 0. 3. Then when we handle RXD0 in the future, we will find the DDONE bit is 0 and we will wait for MAC to set it to 1 forever. */ if (pAd->RxRing.RxSwReadIdx & 0x01) { RTMP_DMACB *pRxCellLast; #ifdef RT_BIG_ENDIAN PRXD_STRUC pDestRxDLast; #endif /* 16B-align */ /* update last BD 32B-align, DMA Done bit = 0 */ pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].LastBDInfo.DDONE = 0; #ifdef RT_BIG_ENDIAN pRxCellLast = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx - 1]; pDestRxDLast = (PRXD_STRUC) pRxCellLast->AllocVa; RTMPDescriptorEndianChange((PUCHAR)&pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].LastBDInfo, TYPE_RXD); WriteBackToDescriptor((PUCHAR)pDestRxDLast, (PUCHAR)&pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].LastBDInfo, FALSE, TYPE_RXD); #endif /* update current BD 16B-align, DMA Done bit = 0 */ pRxD->DDONE = 0; #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); #endif /* flush cache from last BD */ RTMP_DCACHE_FLUSH(pRxCellLast->AllocPa, 32); /* use RXD_SIZE should be OK */ /* update SW read and CPU index */ INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); } else { /* 32B-align */ /* do not set DDONE bit and backup it */ if (pAd->RxRing.RxSwReadIdx >= (RX_RING_SIZE-1)) { DBGPRINT(RT_DEBUG_TRACE, ("Please change RX_RING_SIZE to mutiple of 2!\n")); /* flush cache from current BD */ RTMP_DCACHE_FLUSH(pRxCell->AllocPa, RXD_SIZE); /* update SW read and CPU index */ INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); } else { /* backup current BD */ pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx + 1]; pRxCell->LastBDInfo = *pRxD; /* update CPU index */ INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); } } #endif /* CACHE_LINE_32B */ done: RTMP_SEM_UNLOCK(&pAd->RxRingLock); *pbReschedule = bReschedule; return pRxPacket; }
BOOLEAN RTMPFreeTXDUponTxDmaDone( IN PRTMP_ADAPTER pAd, IN UCHAR QueIdx) { PRTMP_TX_RING pTxRing; PTXD_STRUC pTxD; #ifdef RT_BIG_ENDIAN PTXD_STRUC pDestTxD; #endif PNDIS_PACKET pPacket; UCHAR FREE = 0; TXD_STRUC TxD, *pOriTxD; BOOLEAN bReschedule = FALSE; ASSERT(QueIdx < NUM_OF_TX_RING); pTxRing = &pAd->TxRing[QueIdx]; RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) { #ifdef RALINK_ATE #ifdef RALINK_28xx_QA PHEADER_802_11 pHeader80211; if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) { if (pAd->ate.QID == QueIdx) { pAd->ate.TxDoneCount++; pAd->RalinkCounters.KickTxCount++; ASSERT(pAd->ate.QID == 0); pAd->ate.TxAc0++; FREE++; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC); #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE); #endif pHeader80211->Sequence = ++pAd->ate.seq; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE); #endif if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount)) { pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); goto kick_out; } else if ((pAd->ate.TxStatus == 1) && (pAd->ate.TxDoneCount == pAd->ate.TxCount)) { DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n")); pAd->ate.TxStatus = 0; } else if (!(pAd->ate.Mode & ATE_TXFRAME)) { DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n")); DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode)); } else { DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx)); } #ifndef RT_BIG_ENDIAN NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #else RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #endif INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); continue; } } #endif #endif NICUpdateFifoStaCounters(pAd); FREE++; #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; #ifdef RALINK_ATE if (!(ATE_ON(pAd))) #endif { pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; if (pPacket) { #ifdef CONFIG_5VT_ENHANCE if (RTMP_GET_PACKET_5VT(pPacket)) PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); else #endif PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; ASSERT(pPacket == NULL); if (pPacket) { #ifdef CONFIG_5VT_ENHANCE if (RTMP_GET_PACKET_5VT(pPacket)) PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE); else #endif PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; } pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #else NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #endif #ifdef RALINK_ATE #ifdef RALINK_28xx_QA kick_out: #endif if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx)) { if (pAd->ate.bQATxStart == FALSE) { pAd->ate.TxDoneCount++; } if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE)) { INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); #ifndef RT_BIG_ENDIAN pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); pTxD = &TxD; #else pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); pOriTxD = pDestTxD ; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); #endif pTxD->DMADONE = 0; #ifndef RT_BIG_ENDIAN NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); #else RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); *pDestTxD = TxD; #endif RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx); pAd->RalinkCounters.KickTxCount++; } } #endif } return bReschedule; }
PNDIS_PACKET GetPacketFromRxRing( IN PRTMP_ADAPTER pAd, OUT PRT28XX_RXD_STRUC pSaveRxD, OUT BOOLEAN *pbReschedule, IN OUT UINT32 *pRxPending) { PRXD_STRUC pRxD; #ifdef RT_BIG_ENDIAN PRXD_STRUC pDestRxD; RXD_STRUC RxD; #endif PNDIS_PACKET pRxPacket = NULL; PNDIS_PACKET pNewPacket; PVOID AllocVa; NDIS_PHYSICAL_ADDRESS AllocPa; BOOLEAN bReschedule = FALSE; RTMP_SEM_LOCK(&pAd->RxRingLock); if (*pRxPending == 0) { RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx); if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) { bReschedule = FALSE; goto done; } if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; else *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx; } #ifdef RT_BIG_ENDIAN pDestRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa; RxD = *pDestRxD; pRxD = &RxD; RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); #else pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa; #endif if (pRxD->DDONE == 0) { *pRxPending = 0; bReschedule = TRUE; goto done; } NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); if (pNewPacket) { PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket; pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket = (PNDIS_PACKET) pNewPacket; pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa = AllocVa; pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa = AllocPa; pRxD->SDP0 = AllocPa; } else { pRxPacket = NULL; bReschedule = TRUE; } pRxD->DDONE = 0; *pRxPending = *pRxPending - 1; #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); #endif INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1); RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); done: RTMP_SEM_UNLOCK(&pAd->RxRingLock); *pbReschedule = bReschedule; return pRxPacket; }
void *GetPacketFromRxRing(struct rt_rtmp_adapter *pAd, OUT PRT28XX_RXD_STRUC pSaveRxD, OUT BOOLEAN * pbReschedule, IN u32 * pRxPending) { struct rt_rxd * pRxD; void *pRxPacket = NULL; void *pNewPacket; void *AllocVa; dma_addr_t AllocPa; BOOLEAN bReschedule = FALSE; struct rt_rtmp_dmacb *pRxCell; RTMP_SEM_LOCK(&pAd->RxRingLock); if (*pRxPending == 0) { /* Get how may packets had been received */ RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx) { /* no more rx packets */ bReschedule = FALSE; goto done; } /* get rx pending count */ if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx) *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx; else *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx; } pRxCell = &pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx]; /* Point to Rx indexed rx ring descriptor */ pRxD = (struct rt_rxd *) pRxCell->AllocVa; if (pRxD->DDONE == 0) { *pRxPending = 0; /* DMAIndx had done but DDONE bit not ready */ bReschedule = TRUE; goto done; } /* return rx descriptor */ NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE); pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); if (pNewPacket) { /* unmap the rx buffer */ PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa, pRxCell->DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); pRxPacket = pRxCell->pNdisPacket; pRxCell->DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE; pRxCell->pNdisPacket = (void *)pNewPacket; pRxCell->DmaBuf.AllocVa = AllocVa; pRxCell->DmaBuf.AllocPa = AllocPa; /* update SDP0 to new buffer of rx packet */ pRxD->SDP0 = AllocPa; } else { /*DBGPRINT(RT_DEBUG_TRACE,("No Rx Buffer\n")); */ pRxPacket = NULL; bReschedule = TRUE; } pRxD->DDONE = 0; /* had handled one rx packet */ *pRxPending = *pRxPending - 1; /* update rx descriptor and kick rx */ INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE); pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE - 1) : (pAd->RxRing.RxSwReadIdx - 1); RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); done: RTMP_SEM_UNLOCK(&pAd->RxRingLock); *pbReschedule = bReschedule; return pRxPacket; }
BOOLEAN RTMPFreeTXDUponTxDmaDone(struct rt_rtmp_adapter *pAd, u8 QueIdx) { struct rt_rtmp_tx_ring *pTxRing; struct rt_txd * pTxD; void *pPacket; u8 FREE = 0; struct rt_txd TxD, *pOriTxD; /*unsigned long IrqFlags; */ BOOLEAN bReschedule = FALSE; ASSERT(QueIdx < NUM_OF_TX_RING); pTxRing = &pAd->TxRing[QueIdx]; RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) { /* RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); */ /* static rate also need NICUpdateFifoStaCounters() function. */ /*if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ NICUpdateFifoStaCounters(pAd); /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ FREE++; pTxD = (struct rt_txd *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); pOriTxD = pTxD; NdisMoveMemory(&TxD, pTxD, sizeof(struct rt_txd)); pTxD = &TxD; pTxD->DMADONE = 0; { pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } /*Always assign pNdisPacket as NULL after clear */ pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; ASSERT(pPacket == NULL); if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } /*Always assign pNextNdisPacket as NULL after clear */ pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; } pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx]++; INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); /* get tx_tdx_idx again */ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx); NdisMoveMemory(pOriTxD, pTxD, sizeof(struct rt_txd)); /* RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); */ } return bReschedule; }
VOID RTMPFreeTxRxRingMemory( IN PRTMP_ADAPTER pAd) { int index, num , j; PRTMP_TX_RING pTxRing; PTXD_STRUC pTxD; PNDIS_PACKET pPacket; unsigned int IrqFlags; POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie; DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); for (index=0; index <NUM_OF_TX_RING; index++) { PQUEUE_ENTRY pEntry; PNDIS_PACKET pPacket; PQUEUE_HEADER pQueue; RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); pQueue = &pAd->TxSwQueue[index]; while (pQueue->Head) { pEntry = RemoveHeadQueue(pQueue); pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); } RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); } for (index=0;index< NUM_OF_TX_RING;index++) { pTxRing = &pAd->TxRing[index]; for (j=0; j< TX_RING_SIZE; j++) { pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa); pPacket = pTxRing->Cell[j].pNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pTxRing->Cell[j].pNdisPacket = NULL; pPacket = pTxRing->Cell[j].pNextNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); } pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; } } for (index = RX_RING_SIZE - 1 ; index >= 0; index--) { if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket)) { PCI_UNMAP_SINGLE(pObj->pci_dev, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE); RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS); } } NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); if (pAd->RxDescRing.AllocVa) { PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa); } NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF)); if (pAd->MgmtDescRing.AllocVa) { PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa); } NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF)); for (num = 0; num < NUM_OF_TX_RING; num++) { if (pAd->TxBufSpace[num].AllocVa) { PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxBufSpace[num].AllocSize, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa); } NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF)); if (pAd->TxDescRing[num].AllocVa) { PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa); } NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF)); } if (pAd->FragFrame.pFragPacket) RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); }
VOID RTMPRingCleanUp( IN PRTMP_ADAPTER pAd, IN UCHAR RingType) { PTXD_STRUC pTxD; PRXD_STRUC pRxD; PQUEUE_ENTRY pEntry; PNDIS_PACKET pPacket; int i; PRTMP_TX_RING pTxRing; unsigned long IrqFlags; DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount)); switch (RingType) { case QID_AC_BK: case QID_AC_BE: case QID_AC_VI: case QID_AC_VO: case QID_HCCA: RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); pTxRing = &pAd->TxRing[RingType]; for (i=0; i<TX_RING_SIZE; i++) { pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa; pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket; if (pPacket) { RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); pTxRing->Cell[i].pNdisPacket = NULL; } pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket; if (pPacket) { RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); pTxRing->Cell[i].pNextNdisPacket = NULL; } } RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx); pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx); RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); while (pAd->TxSwQueue[RingType].Head != NULL) { pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]); pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n")); } RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); break; case QID_MGMT: NdisAcquireSpinLock(&pAd->MgmtRingLock); for (i=0; i<MGMT_RING_SIZE; i++) { pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa; pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); } pAd->MgmtRing.Cell[i].pNdisPacket = NULL; pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket; if (pPacket) { PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE); RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); } pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL; } RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx); pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx); NdisReleaseSpinLock(&pAd->MgmtRingLock); pAd->RalinkCounters.MgmtRingFullCount = 0; break; case QID_RX: NdisAcquireSpinLock(&pAd->RxRingLock); for (i=0; i<RX_RING_SIZE; i++) { pRxD = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa; pRxD->DDONE = 0 ; } RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx); pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx; pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1)); RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx); NdisReleaseSpinLock(&pAd->RxRingLock); break; default: break; } }