/* ************************************************************************* * Ralink Tech Inc. * 5F., No.36, Taiyuan St., Jhubei City, * Hsinchu County 302, * Taiwan, R.O.C. * * (c) Copyright 2002-2007, Ralink Technology, Inc. * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* Module Name: rtusb_bulk.c Abstract: Revision History: Who When What -------- ---------- ---------------------------------------------- Name Date Modification logs Paul Lin 06-25-2004 created */ #include "../rt_config.h" // Match total 6 bulkout endpoint to corresponding queue. UCHAR EpToQueue[6]={FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_MGMT}; //static BOOLEAN SingleBulkOut = FALSE; void RTUSB_FILL_BULK_URB (struct urb *pUrb, struct usb_device *pUsb_Dev, unsigned int bulkpipe, void *pTransferBuf, int BufSize, usb_complete_t Complete, void *pContext) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) usb_fill_bulk_urb(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, (usb_complete_t)Complete, pContext); #else FILL_BULK_URB(pUrb, pUsb_Dev, bulkpipe, pTransferBuf, BufSize, Complete, pContext); #endif } VOID RTUSBInitTxDesc( IN PRTMP_ADAPTER pAd, IN PTX_CONTEXT pTxContext, IN UCHAR BulkOutPipeId, IN usb_complete_t Func) { PURB pUrb; PUCHAR pSrc = NULL; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; pUrb = pTxContext->pUrb; ASSERT(pUrb); // Store BulkOut PipeId pTxContext->BulkOutPipeId = BulkOutPipeId; if (pTxContext->bAggregatible) { pSrc = &pTxContext->TransferBuffer->Aggregation[2]; } else { pSrc = (PUCHAR) pTxContext->TransferBuffer->field.WirelessPacket; } //Initialize a tx bulk urb RTUSB_FILL_BULK_URB(pUrb, pObj->pUsb_Dev, usb_sndbulkpipe(pObj->pUsb_Dev, pAd->BulkOutEpAddr[BulkOutPipeId]), pSrc, pTxContext->BulkOutSize, Func, pTxContext); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) if (pTxContext->bAggregatible) pUrb->transfer_dma = (pTxContext->data_dma + TX_BUFFER_NORMSIZE + 2); else pUrb->transfer_dma = pTxContext->data_dma; pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; #endif } VOID RTUSBInitHTTxDesc( IN PRTMP_ADAPTER pAd, IN PHT_TX_CONTEXT pTxContext, IN UCHAR BulkOutPipeId, IN ULONG BulkOutSize, IN usb_complete_t Func) { PURB pUrb; PUCHAR pSrc = NULL; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; pUrb = pTxContext->pUrb; ASSERT(pUrb); // Store BulkOut PipeId pTxContext->BulkOutPipeId = BulkOutPipeId; pSrc = &pTxContext->TransferBuffer->field.WirelessPacket[pTxContext->NextBulkOutPosition]; //Initialize a tx bulk urb RTUSB_FILL_BULK_URB(pUrb, pObj->pUsb_Dev, usb_sndbulkpipe(pObj->pUsb_Dev, pAd->BulkOutEpAddr[BulkOutPipeId]), pSrc, BulkOutSize, Func, pTxContext); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) pUrb->transfer_dma = (pTxContext->data_dma + pTxContext->NextBulkOutPosition); pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; #endif } VOID RTUSBInitRxDesc( IN PRTMP_ADAPTER pAd, IN PRX_CONTEXT pRxContext) { PURB pUrb; POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; ULONG RX_bulk_size; pUrb = pRxContext->pUrb; ASSERT(pUrb); if ( pAd->BulkInMaxPacketSize == 64) RX_bulk_size = 4096; else RX_bulk_size = MAX_RXBULK_SIZE; //Initialize a rx bulk urb RTUSB_FILL_BULK_URB(pUrb, pObj->pUsb_Dev, usb_rcvbulkpipe(pObj->pUsb_Dev, pAd->BulkInEpAddr), &(pRxContext->TransferBuffer[pAd->NextRxBulkInPosition]), RX_bulk_size - (pAd->NextRxBulkInPosition), (usb_complete_t)RTUSBBulkRxComplete, (void *)pRxContext); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) pUrb->transfer_dma = pRxContext->data_dma + pAd->NextRxBulkInPosition; pUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; #endif } /* ======================================================================== Routine Description: Arguments: Return Value: Note: ======================================================================== */ #define BULK_OUT_LOCK(pLock, IrqFlags) \ if(1 /*!(in_interrupt() & 0xffff0000)*/) \ RTMP_IRQ_LOCK((pLock), IrqFlags); #define BULK_OUT_UNLOCK(pLock, IrqFlags) \ if(1 /*!(in_interrupt() & 0xffff0000)*/) \ RTMP_IRQ_UNLOCK((pLock), IrqFlags); VOID RTUSBBulkOutDataPacket( IN PRTMP_ADAPTER pAd, IN UCHAR BulkOutPipeId, IN UCHAR Index) { PHT_TX_CONTEXT pHTTXContext; PURB pUrb; int ret = 0; PTXINFO_STRUC pTxInfo, pLastTxInfo = NULL; PTXWI_STRUC pTxWI; ULONG TmpBulkEndPos, ThisBulkSize; unsigned long IrqFlags = 0, IrqFlags2 = 0; PUCHAR pWirelessPkt, pAppendant; BOOLEAN bTxQLastRound = FALSE; UCHAR allzero[4]= {0x0,0x0,0x0,0x0}; BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); if ((pAd->BulkOutPending[BulkOutPipeId] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } pAd->BulkOutPending[BulkOutPipeId] = TRUE; if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) ) { pAd->BulkOutPending[BulkOutPipeId] = FALSE; BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pHTTXContext = &(pAd->TxContext[BulkOutPipeId]); BULK_OUT_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition)) { BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; // Clear Data flag RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)); RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } // Clear Data flag RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId)); RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); //DBGPRINT(RT_DEBUG_TRACE,("BulkOut-B:I=0x%lx, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", in_interrupt(), // pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, // pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); pHTTXContext->NextBulkOutPosition = pHTTXContext->ENextBulkOutPosition; ThisBulkSize = 0; TmpBulkEndPos = pHTTXContext->NextBulkOutPosition; pWirelessPkt = &pHTTXContext->TransferBuffer->field.WirelessPacket[0]; if ((pHTTXContext->bCopySavePad == TRUE)) { if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4)) { DBGPRINT_RAW(RT_DEBUG_ERROR,("e1, allzero : %x %x %x %x %x %x %x %x \n", pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3] ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7])); } NdisMoveMemory(&pWirelessPkt[TmpBulkEndPos], pHTTXContext->SavedPad, 8); pHTTXContext->bCopySavePad = FALSE; if (pAd->bForcePrintTX == TRUE) DBGPRINT(RT_DEBUG_TRACE,("RTUSBBulkOutDataPacket --> COPY PAD. CurWrite = %ld, NextBulk = %ld. ENextBulk = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition)); } do { pTxInfo = (PTXINFO_STRUC)&pWirelessPkt[TmpBulkEndPos]; pTxWI = (PTXWI_STRUC)&pWirelessPkt[TmpBulkEndPos + TXINFO_SIZE]; if (pAd->bForcePrintTX == TRUE) DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkOutDataPacket AMPDU = %d.\n", pTxWI->AMPDU)); // add by Iverson, limit BulkOut size to 4k to pass WMM b mode 2T1R test items //if ((ThisBulkSize != 0) && (pTxWI->AMPDU == 0)) if ((ThisBulkSize != 0) && (pTxWI->PHYMODE == MODE_CCK)) { if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x1000) == 0x1000)) { // Limit BulkOut size to about 4k bytes. pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; break; } else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/) { // For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. // For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; break; } } // end Iverson else { if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000)) { // Limit BulkOut size to about 24k bytes. pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; break; } else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/) { // For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. // For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04. pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; break; } } if (TmpBulkEndPos == pHTTXContext->CurWritePosition) { pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos; break; } if (pTxInfo->QSEL != FIFO_EDCA) { printk("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n", __func__, pTxInfo->QSEL); printk("\tCWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad); hex_dump("Wrong QSel Pkt:", (PUCHAR)&pWirelessPkt[TmpBulkEndPos], (pHTTXContext->CurWritePosition - pHTTXContext->NextBulkOutPosition)); } if (pTxInfo->USBDMATxPktLen <= 8) { BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); DBGPRINT(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("e2, USBDMATxPktLen==0, Size=%ld, bCSPad=%d, CWPos=%ld, NBPos=%ld, CWRPos=%ld!\n", pHTTXContext->BulkOutSize, pHTTXContext->bCopySavePad, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->CurWriteRealPos)); { DBGPRINT_RAW(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("%x %x %x %x %x %x %x %x \n", pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3] ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7])); } pAd->bForcePrintTX = TRUE; BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); //DBGPRINT(RT_DEBUG_LOUD,("Out:pTxInfo->USBDMATxPktLen=%d!\n", pTxInfo->USBDMATxPktLen)); return; } // Increase Total transmit byte counter pAd->RalinkCounters.OneSecTransmittedByteCount += pTxWI->MPDUtotalByteCount; pAd->RalinkCounters.TransmittedByteCount += pTxWI->MPDUtotalByteCount; pLastTxInfo = pTxInfo; // Make sure we use EDCA QUEUE. pTxInfo->QSEL = FIFO_EDCA; ThisBulkSize += (pTxInfo->USBDMATxPktLen+4); TmpBulkEndPos += (pTxInfo->USBDMATxPktLen+4); if (TmpBulkEndPos != pHTTXContext->CurWritePosition) pTxInfo->USBDMANextVLD = 1; if (pTxInfo->SwUseLastRound == 1) { if (pHTTXContext->CurWritePosition == 8) pTxInfo->USBDMANextVLD = 0; pTxInfo->SwUseLastRound = 0; bTxQLastRound = TRUE; pHTTXContext->ENextBulkOutPosition = 8; #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO); RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); #endif // RT_BIG_ENDIAN // break; } #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO); RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI); #endif // RT_BIG_ENDIAN // }while (TRUE); // adjust the pTxInfo->USBDMANextVLD value of last pTxInfo. if (pLastTxInfo) { #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pLastTxInfo, TYPE_TXINFO); #endif // RT_BIG_ENDIAN // pLastTxInfo->USBDMANextVLD = 0; #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pLastTxInfo, TYPE_TXINFO); #endif // RT_BIG_ENDIAN // } /* We need to copy SavedPad when following condition matched! 1. Not the last round of the TxQueue and 2. any match of following cases: (1). The End Position of this bulk out is reach to the Currenct Write position and the TxInfo and related header already write to the CurWritePosition. =>(ENextBulkOutPosition == CurWritePosition) && (CurWriteRealPos > CurWritePosition) (2). The EndPosition of the bulk out is not reach to the Current Write Position. =>(ENextBulkOutPosition != CurWritePosition) */ if ((bTxQLastRound == FALSE) && (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) && (pHTTXContext->CurWriteRealPos > pHTTXContext->CurWritePosition)) || (pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition)) ) { NdisMoveMemory(pHTTXContext->SavedPad, &pWirelessPkt[pHTTXContext->ENextBulkOutPosition], 8); pHTTXContext->bCopySavePad = TRUE; if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4)) { PUCHAR pBuf = &pHTTXContext->SavedPad[0]; DBGPRINT_RAW(RT_DEBUG_ERROR,("WARNING-Zero-3:%02x%02x%02x%02x%02x%02x%02x%02x,CWPos=%ld, CWRPos=%ld, bCW=%d, NBPos=%ld, TBPos=%ld, TBSize=%ld\n", pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7], pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->bCurWriting, pHTTXContext->NextBulkOutPosition, TmpBulkEndPos, ThisBulkSize)); pBuf = &pWirelessPkt[pHTTXContext->CurWritePosition]; DBGPRINT_RAW(RT_DEBUG_ERROR,("\tCWPos=%02x%02x%02x%02x%02x%02x%02x%02x\n", pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7])); } //DBGPRINT(RT_DEBUG_LOUD,("ENPos==CWPos=%ld, CWRPos=%ld, bCSPad=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->bCopySavePad)); } if (pAd->bForcePrintTX == TRUE) DBGPRINT(RT_DEBUG_TRACE,("BulkOut-A:Size=%ld, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); //DBGPRINT(RT_DEBUG_LOUD,("BulkOut-A:Size=%ld, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, bLRound=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, bTxQLastRound)); // USB DMA engine requires to pad extra 4 bytes. This pad doesn't count into real bulkoutsize. pAppendant = &pWirelessPkt[TmpBulkEndPos]; NdisZeroMemory(pAppendant, 8); ThisBulkSize += 4; pHTTXContext->LastOne = TRUE; if ((ThisBulkSize % pAd->BulkOutMaxPacketSize) == 0) ThisBulkSize += 4; pHTTXContext->BulkOutSize = ThisBulkSize; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 1; BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2); // Init Tx context descriptor RTUSBInitHTTxDesc(pAd, pHTTXContext, BulkOutPipeId, ThisBulkSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete); pUrb = pHTTXContext->pUrb; if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret)); BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pHTTXContext->IRPPending = TRUE; BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutReq++; } VOID RTUSBBulkOutDataPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) { #if 0 // sample, IRQ LOCK PRTMP_ADAPTER pAd; POS_COOKIE pObj; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId; NTSTATUS Status; unsigned long IrqFlags; DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutDataPacketComplete\n")); pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; 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; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); if (Status == USB_ST_NOERROR) { pAd->BulkOutComplete++; pAd->Counters8023.GoodTransmits++; //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); } else // STATUS_OTHER { PUCHAR pBuf; pAd->BulkOutCompleteOther++; pBuf = &pHTTXContext->TransferBuffer->WirelessPacket[pHTTXContext->NextBulkOutPosition]; DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkOutDataPacket failed: ReasonCode=%d!\n", Status)); DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOut Header:%x %x %x %x %x %x %x %x\n", pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5], pBuf[6], pBuf[7])); //DBGPRINT_RAW(RT_DEBUG_ERROR, (">>BulkOutCompleteCancel=0x%x, BulkOutCompleteOther=0x%x\n", pAd->BulkOutCompleteCancel, pAd->BulkOutCompleteOther)); if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET))) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = BulkOutPipeId; } } // // bInUse = TRUE, means some process are filling TX data, after that must turn on bWaitingBulkOut // bWaitingBulkOut = TRUE, means the TX data are waiting for bulk out. // //RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); if ((pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition) && (pHTTXContext->ENextBulkOutPosition != (pHTTXContext->CurWritePosition+8)) && !RTUSB_TEST_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId))) { // Indicate There is data avaliable RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId)); } //RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); // Always call Bulk routine, even reset bulk. // The protection of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); //DBGPRINT(RT_DEBUG_LOUD,("Done-A(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d\n", BulkOutPipeId, in_interrupt(), // pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); switch (BulkOutPipeId) { case 0: pObj->ac0_dma_done_task.data = (unsigned long)pAd; tasklet_hi_schedule(&pObj->ac0_dma_done_task); break; case 1: pObj->ac1_dma_done_task.data = (unsigned long)pAd; tasklet_hi_schedule(&pObj->ac1_dma_done_task); break; case 2: pObj->ac2_dma_done_task.data = (unsigned long)pAd; tasklet_hi_schedule(&pObj->ac2_dma_done_task); break; case 3: pObj->ac3_dma_done_task.data = (unsigned long)pAd; tasklet_hi_schedule(&pObj->ac3_dma_done_task); break; case 4: pObj->hcca_dma_done_task.data = (unsigned long)pAd; tasklet_hi_schedule(&pObj->hcca_dma_done_task); break; } #else { PHT_TX_CONTEXT pHTTXContext; PRTMP_ADAPTER pAd; POS_COOKIE pObj; UCHAR BulkOutPipeId; pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; pAd = pHTTXContext->pAd; pObj = (POS_COOKIE) pAd->OS_Cookie; // Store BulkOut PipeId BulkOutPipeId = pHTTXContext->BulkOutPipeId; pAd->BulkOutDataOneSecCount++; switch (BulkOutPipeId) { case 0: pObj->ac0_dma_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->ac0_dma_done_task); break; case 1: pObj->ac1_dma_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->ac1_dma_done_task); break; case 2: pObj->ac2_dma_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->ac2_dma_done_task); break; case 3: pObj->ac3_dma_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->ac3_dma_done_task); break; case 4: pObj->hcca_dma_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->hcca_dma_done_task); break; } } #endif } /* ======================================================================== Routine Description: Arguments: Return Value: Note: NULL frame use BulkOutPipeId = 0 ======================================================================== */ VOID RTUSBBulkOutNullFrame( IN PRTMP_ADAPTER pAd) { PTX_CONTEXT pNullContext = &(pAd->NullContext); 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; pNullContext->IRPPending = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); // Increase Total transmit byte counter pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize; // Clear Null frame bulk flag RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pNullContext->TransferBuffer, TYPE_TXINFO); #endif // RT_BIG_ENDIAN // // Init Tx context descriptor RTUSBInitTxDesc(pAd, pNullContext, 0, (usb_complete_t)RTUSBBulkOutNullFrameComplete); pUrb = pNullContext->pUrb; if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; pNullContext->IRPPending = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutNullFrame: Submit Tx URB failed %d\n", ret)); return; } } // NULL frame use BulkOutPipeId = 0 VOID RTUSBBulkOutNullFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs) { PRTMP_ADAPTER pAd; PTX_CONTEXT pNullContext; NTSTATUS Status; #if 0 // sample, IRQ LOCK unsigned long IrqFlags; #endif POS_COOKIE pObj; pNullContext = (PTX_CONTEXT)pUrb->context; pAd = pNullContext->pAd; Status = pUrb->status; #if 0 // sample, IRQ LOCK // Reset Null frame context flags pNullContext->IRPPending = FALSE; pNullContext->InUse = FALSE; if (Status == USB_ST_NOERROR) { // Don't worry about the queue is empty or not, this function will check itself //RTMPUSBDeQueuePacket(pAd, 0); RTMPDeQueuePacket(pAd, TRUE, 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\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } } RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); pAd->BulkOutPending[0] = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); #else pObj = (POS_COOKIE) pAd->OS_Cookie; pObj->null_frame_complete_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->null_frame_complete_task); #endif } #if 0 // For RT2870, RTS frame not used now, but maybe will use it latter. /* ======================================================================== Routine Description: Arguments: Return Value: Note: RTS frame use BulkOutPipeId = 0 ======================================================================== */ VOID RTUSBBulkOutRTSFrame( IN PRTMP_ADAPTER pAd) { PTX_CONTEXT pRTSContext = &(pAd->RTSContext); PURB pUrb; int ret = 0; unsigned long IrqFlags; UCHAR PipeID=0; if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4)) PipeID= 3; else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3)) PipeID= 2; else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2)) PipeID= 1; else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL)) PipeID= 0; RTMP_IRQ_LOCK(&pAd->BulkOutLock[PipeID], IrqFlags); if ((pAd->BulkOutPending[PipeID] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX)) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[PipeID], IrqFlags); return; } pAd->BulkOutPending[PipeID] = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[PipeID], IrqFlags); // Increase Total transmit byte counter pAd->RalinkCounters.TransmittedByteCount += pRTSContext->BulkOutSize; DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutRTSFrame \n")); // Clear RTS frame bulk flag RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_RTS); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pRTSContext->TransferBuffer, TYPE_TXINFO); #endif // RT_BIG_ENDIAN // // Init Tx context descriptor RTUSBInitTxDesc(pAd, pRTSContext, PipeID, (usb_complete_t)RTUSBBulkOutRTSFrameComplete); pRTSContext->IRPPending = TRUE; pUrb = pRTSContext->pUrb; if((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutRTSFrame: Submit Tx URB failed %d\n", ret)); return; } DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutRTSFrame \n")); } // RTS frame use BulkOutPipeId = 0 VOID RTUSBBulkOutRTSFrameComplete(purbb_t pUrb, struct pt_regs *pt_regs) { PRTMP_ADAPTER pAd; PTX_CONTEXT pRTSContext; NTSTATUS Status; #if 0 // sample, IRQ LOCK unsigned long IrqFlags; #endif POS_COOKIE pObj; DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutRTSFrameComplete\n")); pRTSContext = (PTX_CONTEXT)pUrb->context; pAd = pRTSContext->pAd; Status = pUrb->status; #if 0 // sample, IRQ LOCK // Reset RTS frame context flags pRTSContext->IRPPending = FALSE; pRTSContext->InUse = FALSE; if (Status == USB_ST_NOERROR) { // Don't worry about the queue is empty or not, this function will check itself //RTMPUSBDeQueuePacket(pAd, pRTSContext->BulkOutPipeId); RTMPDeQueuePacket(pAd, TRUE, 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); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } } RTMP_IRQ_LOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId], IrqFlags); pAd->BulkOutPending[pRTSContext->BulkOutPipeId] = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[pRTSContext->BulkOutPipeId], IrqFlags); // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); #else pObj = (POS_COOKIE) pAd->OS_Cookie; pObj->rts_frame_complete_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->rts_frame_complete_task); #endif DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutRTSFrameComplete\n")); } #endif /* ======================================================================== 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); //DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutMLMEPacket\n")); #if 0 // for debug { printk("MLME-Out, C=%d!, D=%d, F=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx); //TODO: Need to remove it when formal release PTXINFO_STRUC pTxInfo; pTxInfo = (PTXINFO_STRUC)pMLMEContext->TransferBuffer; if (pTxInfo->QSEL != FIFO_EDCA) { printk("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n", __func__, pTxInfo->QSEL); printk("\tMLME_Index=%d!\n", Index); hex_dump("Wrong QSel Pkt:", (PUCHAR)pMLMEContext->TransferBuffer, pTxInfo->USBDMATxPktLen); } } #endif #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)RTUSBBulkOutMLMEPacketComplete); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) //For mgmt urb buffer, because we use sk_buff, so we need to notify the USB controller do dma mapping. pUrb->transfer_dma = 0; pUrb->transfer_flags &= (~URB_NO_TRANSFER_DMA_MAP); #endif 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; } //DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutMLMEPacket \n")); // printk("<---RTUSBBulkOutMLMEPacket,Cpu=%d!, Dma=%d, SwIdx=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx); } VOID RTUSBBulkOutMLMEPacketComplete(purbb_t pUrb, struct pt_regs *pt_regs) { PTX_CONTEXT pMLMEContext; PRTMP_ADAPTER pAd; NTSTATUS Status; POS_COOKIE pObj; int index; #if 0 // sample, IRQ LOCK unsigned long IrqFlags; PNDIS_PACKET pPacket; #endif //DBGPRINT_RAW(RT_DEBUG_INFO, ("--->RTUSBBulkOutMLMEPacketComplete\n")); pMLMEContext = (PTX_CONTEXT)pUrb->context; pAd = pMLMEContext->pAd; pObj = (POS_COOKIE)pAd->OS_Cookie; Status = pUrb->status; index = pMLMEContext->SelfIdx; #if 0 // sample, IRQ LOCK ASSERT((pAd->MgmtRing.TxDmaIdx == index)); //printk("MLME-Done-B: C=%d, D=%d, F=%d, Self=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx, pMLMEContext->SelfIdx); RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); if (Status != USB_ST_NOERROR) { //Bulk-Out fail status handle 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 MLME Failed, Status=%d!\n", Status)); // TODO: How to handle about the MLMEBulkOut failed issue. Need to resend the mgmt pkt? RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); } } pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags); // Reset MLME context flags pMLMEContext->IRPPending = FALSE; pMLMEContext->InUse = FALSE; pMLMEContext->bWaitingBulkOut = FALSE; pMLMEContext->BulkOutSize = 0; pPacket = pAd->MgmtRing.Cell[index].pNdisPacket; pAd->MgmtRing.Cell[index].pNdisPacket = NULL; // Increase MgmtRing Index INC_RING_INDEX(pAd->MgmtRing.TxDmaIdx, MGMT_RING_SIZE); pAd->MgmtRing.TxSwFreeIdx++; RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags); // No-matter success or fail, we free the mgmt packet. if (pPacket) RTMPFreeNdisPacket(pAd, pPacket); #if 0 //Bulk-Out fail status handle if (Status != USB_ST_NOERROR) { 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 MLME Failed, Status=%d!\n", Status)); // TODO: How to handle about the MLMEBulkOut failed issue. Need to reset the endpoint? RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); } } #endif //printk("MLME-Done-A: C=%d, D=%d, F=%d!\n", pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx); pObj->mgmt_dma_done_task.data = (unsigned long)pAd; tasklet_hi_schedule(&pObj->mgmt_dma_done_task); //DBGPRINT_RAW(RT_DEBUG_INFO, ("<---RTUSBBulkOutMLMEPacketComplete\n")); // printk("<---RTUSBBulkOutMLMEPacketComplete, Cpu=%d, Dma=%d, SwIdx=%d!\n", // pAd->MgmtRing.TxCpuIdx, pAd->MgmtRing.TxDmaIdx, pAd->MgmtRing.TxSwFreeIdx); #else pObj->mgmt_dma_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->mgmt_dma_done_task); #endif } /* ======================================================================== Routine Description: Arguments: Return Value: Note: PsPoll use BulkOutPipeId = 0 ======================================================================== */ 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); // Clear PS-Poll bulk flag RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL); #ifdef RT_BIG_ENDIAN RTMPDescriptorEndianChange((PUCHAR)pPsPollContext->TransferBuffer, TYPE_TXINFO); #endif // RT_BIG_ENDIAN // // Init Tx context descriptor 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; } } // PS-Poll frame use BulkOutPipeId = 0 VOID RTUSBBulkOutPsPollComplete(purbb_t pUrb,struct pt_regs *pt_regs) { PRTMP_ADAPTER pAd; PTX_CONTEXT pPsPollContext; NTSTATUS Status; #if 0 // sample, IRQ LOCK unsigned long IrqFlags; #endif POS_COOKIE pObj; pPsPollContext= (PTX_CONTEXT)pUrb->context; pAd = pPsPollContext->pAd; Status = pUrb->status; #if 0 // sample, IRQ LOCK // Reset PsPoll context flags pPsPollContext->IRPPending = FALSE; pPsPollContext->InUse = FALSE; if (Status == USB_ST_NOERROR) { // Don't worry about the queue is empty or not, this function will check itself RTMPDeQueuePacket(pAd, TRUE, 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 PSPoll Failed\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } } RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags); pAd->BulkOutPending[0] = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags); // Always call Bulk routine, even reset bulk. // The protectioon of rest bulk should be in BulkOut routine RTUSBKickBulkOut(pAd); #else pObj = (POS_COOKIE) pAd->OS_Cookie; pObj->pspoll_frame_complete_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->pspoll_frame_complete_task); #endif } #if 0 /* ======================================================================== Routine Description: USB_RxPacket initializes a URB and uses the Rx IRP to submit it to USB. It checks if an Rx Descriptor is available and passes the the coresponding buffer to be filled. If no descriptor is available fails the request. When setting the completion routine we pass our Adapter Object as Context. Arguments: Return Value: TRUE found matched tuple cache FALSE no matched found Note: ======================================================================== */ VOID RTUSBBulkReceive( IN PRTMP_ADAPTER pAd) { PRX_CONTEXT pRxContext; PURB pUrb; int ret = 0; unsigned long IrqFlags; /* device had been closed */ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS)) return; RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); // Last is time point between 2 separate URB. if (pAd->NextRxBulkInPosition == 0) { //pAd->NextRxBulkInIndex = (pAd->NextRxBulkInIndex + 1) % (RX_RING_SIZE); INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE); } else if ((pAd->NextRxBulkInPosition&0x1ff) != 0) { //pAd->NextRxBulkInIndex = (pAd->NextRxBulkInIndex + 1) % (RX_RING_SIZE); INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE); DBGPRINT_RAW(RT_DEBUG_TRACE, ("pAd->NextRxBulkInPosition = 0x%lx. End of URB.\n", pAd->NextRxBulkInPosition )); pAd->NextRxBulkInPosition = 0; } if (pAd->NextRxBulkInPosition == MAX_RXBULK_SIZE) pAd->NextRxBulkInPosition = 0; pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); // TODO: Why need to check if pRxContext->InUsed == TRUE? //if ((pRxContext->InUse == TRUE) || (pRxContext->Readable == TRUE)) if ((pRxContext->InUse == FALSE) && (pRxContext->Readable == TRUE)) { DBGPRINT_RAW(RT_DEBUG_TRACE, ("pRxContext[%d] InUse = %d.pRxContext->Readable = %d. Return.\n", pAd->NextRxBulkInIndex,pRxContext->InUse, pRxContext->Readable )); RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); // read RxContext, Since not #ifdef CONFIG_STA_SUPPORT STARxDoneInterruptHandle(pAd, TRUE); #endif // CONFIG_STA_SUPPORT // //return; } pRxContext->InUse = TRUE; pRxContext->IRPPending= TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); // Init Rx context descriptor NdisZeroMemory(pRxContext->TransferBuffer, BUFFER_SIZE); RTUSBInitRxDesc(pAd, pRxContext); pUrb = pRxContext->pUrb; if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0) { DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret)); return; } else // success { NdisInterlockedIncrement(&pAd->PendingRx); pAd->BulkInReq++; } // read RxContext, Since not #ifdef CONFIG_STA_SUPPORT STARxDoneInterruptHandle(pAd, FALSE); #endif // CONFIG_STA_SUPPORT // } /* ======================================================================== Routine Description: This routine process Rx Irp and call rx complete function. Arguments: DeviceObject Pointer to the device object for next lower device. DeviceObject passed in here belongs to the next lower driver in the stack because we were invoked via IoCallDriver in USB_RxPacket AND it is not OUR device object Irp Ptr to completed IRP Context Ptr to our Adapter object (context specified in IoSetCompletionRoutine Return Value: Always returns STATUS_MORE_PROCESSING_REQUIRED Note: Always returns STATUS_MORE_PROCESSING_REQUIRED ======================================================================== */ VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs) { #if 0 PRX_CONTEXT pRxContext; PRTMP_ADAPTER pAd; NTSTATUS Status; // POS_COOKIE pObj; pRxContext = (PRX_CONTEXT)pUrb->context; pAd = pRxContext->pAd; // pObj = (POS_COOKIE) pAd->OS_Cookie; Status = pUrb->status; //pRxContext->pIrp = NULL; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; if (Status == USB_ST_NOERROR) { pAd->BulkInComplete++; pRxContext->Readable = TRUE; pAd->NextRxBulkInPosition = 0; } else // STATUS_OTHER { pAd->BulkInCompleteFail++; // Still read this packet although it may comtain wrong bytes. pRxContext->Readable = FALSE; // Parsing all packets. because after reset, the index will reset to all zero. if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk In Failed. Status = %d\n", Status)); DBGPRINT_RAW(RT_DEBUG_ERROR, ("==>NextRxBulkInIndex=0x%x, NextRxBulkInReadIndex=0x%x, TransferBufferLength= 0x%x\n", pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pRxContext->pUrb->actual_length)); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); RTUSBEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0); } //pUrb = NULL; } if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET)) && // (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { RTUSBBulkReceive(pAd); #if 0 #if 1 STARxDoneInterruptHandle(pAd, FALSE); #else pObj->rx_bh.data = (unsigned long)pUrb; tasklet_schedule(&pObj->rx_bh); #endif #endif } // Call RxPacket to process packet and return the status NdisInterlockedDecrement(&pAd->PendingRx); #else // use a receive tasklet to handle received packets; // or sometimes hardware IRQ will be disabled here, so we can not // use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :< PRX_CONTEXT pRxContext; PRTMP_ADAPTER pAd; POS_COOKIE pObj; pRxContext = (PRX_CONTEXT)pUrb->context; pAd = pRxContext->pAd; pObj = (POS_COOKIE) pAd->OS_Cookie; pObj->rx_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->rx_done_task); #endif } #else 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 #if 0 RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->IRPPending = TRUE; //NdisInterlockedIncrement(&pAd->PendingRx); pAd->PendingRx++; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); pAd->BulkInReq++; #endif ASSERT((pRxContext->InUse == pRxContext->IRPPending)); //printk("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex); } } /* ======================================================================== Routine Description: USB_RxPacket initializes a URB and uses the Rx IRP to submit it to USB. It checks if an Rx Descriptor is available and passes the the coresponding buffer to be filled. If no descriptor is available fails the request. When setting the completion routine we pass our Adapter Object as Context. Arguments: Return Value: TRUE found matched tuple cache FALSE no matched found Note: ======================================================================== */ #define fRTMP_ADAPTER_NEED_STOP_RX \ (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \ fRTMP_ADAPTER_REMOVE_IN_PROGRESS | fRTMP_ADAPTER_BULKIN_RESET) #define fRTMP_ADAPTER_NEED_STOP_HANDLE_RX \ (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \ fRTMP_ADAPTER_REMOVE_IN_PROGRESS) VOID RTUSBBulkReceive( IN PRTMP_ADAPTER pAd) { PRX_CONTEXT pRxContext; unsigned long IrqFlags; /* sanity check */ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_HANDLE_RX)) return; while(1) { RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext = &(pAd->RxContext[pAd->NextRxBulkInReadIndex]); if (((pRxContext->InUse == FALSE) && (pRxContext->Readable == TRUE)) && (pRxContext->bRxHandling == FALSE)) { pRxContext->bRxHandling = TRUE; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); // read RxContext, Since not #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) STARxDoneInterruptHandle(pAd, TRUE); #endif // CONFIG_STA_SUPPORT // // Finish to handle this bulkIn buffer. RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->BulkInOffset = 0; pRxContext->Readable = FALSE; pRxContext->bRxHandling = FALSE; pAd->ReadPosition = 0; pAd->TransferBufferLength = 0; INC_RING_INDEX(pAd->NextRxBulkInReadIndex, RX_RING_SIZE); RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); } else { RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); break; } } if (!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_RX))) DoBulkIn(pAd); } /* ======================================================================== Routine Description: This routine process Rx Irp and call rx complete function. Arguments: DeviceObject Pointer to the device object for next lower device. DeviceObject passed in here belongs to the next lower driver in the stack because we were invoked via IoCallDriver in USB_RxPacket AND it is not OUR device object Irp Ptr to completed IRP Context Ptr to our Adapter object (context specified in IoSetCompletionRoutine Return Value: Always returns STATUS_MORE_PROCESSING_REQUIRED Note: Always returns STATUS_MORE_PROCESSING_REQUIRED ======================================================================== */ VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs) { // use a receive tasklet to handle received packets; // or sometimes hardware IRQ will be disabled here, so we can not // use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :< PRX_CONTEXT pRxContext; PRTMP_ADAPTER pAd; POS_COOKIE pObj; pRxContext = (PRX_CONTEXT)pUrb->context; pAd = pRxContext->pAd; pObj = (POS_COOKIE) pAd->OS_Cookie; pObj->rx_done_task.data = (unsigned long)pUrb; tasklet_hi_schedule(&pObj->rx_done_task); } #endif /* ======================================================================== Routine Description: Arguments: Return Value: Note: ======================================================================== */ VOID RTUSBKickBulkOut( IN PRTMP_ADAPTER pAd) { // BulkIn Reset will reset whole USB PHY. So we need to make sure fRTMP_ADAPTER_BULKIN_RESET not flaged. if (!RTMP_TEST_FLAG(pAd ,fRTMP_ADAPTER_NEED_STOP_TX) #ifdef RALINK_ATE && !(ATE_ON(pAd)) #endif // RALINK_ATE // ) { #if 0 // not used now in RT28xx, but may used latter. // 1. Data Fragment has highest priority if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_FRAG)) { if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) )) { RTUSBBulkOutDataPacket(pAd, 0, pAd->NextBulkOutIndex[0]); } } if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_FRAG_2)) { if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) )) { RTUSBBulkOutDataPacket(pAd, 1, pAd->NextBulkOutIndex[1]); } } if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_FRAG_3)) { if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) )) { RTUSBBulkOutDataPacket(pAd, 2, pAd->NextBulkOutIndex[2]); } } if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_FRAG_4)) { if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) )) { RTUSBBulkOutDataPacket(pAd, 3, pAd->NextBulkOutIndex[3]); } } #endif // 2. PS-Poll frame is next if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL)) { RTUSBBulkOutPsPoll(pAd); } // 5. Mlme frame is next else if ((RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME)) && (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE)) { RTUSBBulkOutMLMEPacket(pAd, pAd->MgmtRing.TxDmaIdx); } // 6. Data frame normal is next if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL)) { if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) )) { RTUSBBulkOutDataPacket(pAd, 0, pAd->NextBulkOutIndex[0]); } } if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2)) { if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) )) { RTUSBBulkOutDataPacket(pAd, 1, pAd->NextBulkOutIndex[1]); } } if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3)) { if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) )) { RTUSBBulkOutDataPacket(pAd, 2, pAd->NextBulkOutIndex[2]); } } if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4)) { if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) || (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) )) { RTUSBBulkOutDataPacket(pAd, 3, pAd->NextBulkOutIndex[3]); } } // 7. Null frame is the last else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL)) { if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) { RTUSBBulkOutNullFrame(pAd); } } // 8. No data avaliable else { } } #ifdef RALINK_ATE /* If the mode is in ATE mode. */ else if((ATE_ON(pAd)) && !RTMP_TEST_FLAG(pAd ,fRTMP_ADAPTER_NEED_STOP_TX))// PETER : watch out ! { if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE)) { ATE_RTUSBBulkOutDataPacket(pAd, 0); } } #endif // RALINK_ATE // } /* ======================================================================== Routine Description: Call from Reset action after BulkOut failed. Arguments: Return Value: Note: ======================================================================== */ VOID RTUSBCleanUpDataBulkOutQueue( IN PRTMP_ADAPTER pAd) { UCHAR Idx; PHT_TX_CONTEXT pTxContext; DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpDataBulkOutQueue\n")); for (Idx = 0; Idx < 4; Idx++) { pTxContext = &pAd->TxContext[Idx]; pTxContext->CurWritePosition = pTxContext->NextBulkOutPosition; pTxContext->LastOne = FALSE; NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]); pAd->BulkOutPending[Idx] = FALSE; NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]); } DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpDataBulkOutQueue\n")); } /* ======================================================================== Routine Description: Arguments: Return Value: Note: ======================================================================== */ VOID RTUSBCleanUpMLMEBulkOutQueue( IN PRTMP_ADAPTER pAd) { DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpMLMEBulkOutQueue\n")); #if 0 // Do nothing! NdisAcquireSpinLock(&pAd->MLMEBulkOutLock); while (pAd->PrioRingTxCnt > 0) { pAd->MLMEContext[pAd->PrioRingFirstIndex].InUse = FALSE; pAd->PrioRingFirstIndex++; if (pAd->PrioRingFirstIndex >= MGMT_RING_SIZE) { pAd->PrioRingFirstIndex = 0; } pAd->PrioRingTxCnt--; } NdisReleaseSpinLock(&pAd->MLMEBulkOutLock); #endif DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpMLMEBulkOutQueue\n")); } /* ======================================================================== Routine Description: Arguments: Return Value: Note: ======================================================================== */ VOID RTUSBCancelPendingIRPs( IN PRTMP_ADAPTER pAd) { RTUSBCancelPendingBulkInIRP(pAd); RTUSBCancelPendingBulkOutIRP(pAd); } /* ======================================================================== Routine Description: Arguments: Return Value: Note: ======================================================================== */ VOID RTUSBCancelPendingBulkInIRP( IN PRTMP_ADAPTER pAd) { PRX_CONTEXT pRxContext; UINT i; DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->RTUSBCancelPendingBulkInIRP\n")); for ( i = 0; i < (RX_RING_SIZE); i++) { pRxContext = &(pAd->RxContext[i]); if(pRxContext->IRPPending == TRUE) { RTUSB_UNLINK_URB(pRxContext->pUrb); pRxContext->IRPPending = FALSE; pRxContext->InUse = FALSE; //NdisInterlockedDecrement(&pAd->PendingRx); //pAd->PendingRx--; } } DBGPRINT_RAW(RT_DEBUG_TRACE, ("<---RTUSBCancelPendingBulkInIRP\n")); } /* ======================================================================== Routine Description: Arguments: Return Value: Note: ======================================================================== */ VOID RTUSBCancelPendingBulkOutIRP( IN PRTMP_ADAPTER pAd) { PHT_TX_CONTEXT pHTTXContext; PTX_CONTEXT pMLMEContext; PTX_CONTEXT pBeaconContext; PTX_CONTEXT pNullContext; PTX_CONTEXT pPsPollContext; PTX_CONTEXT pRTSContext; UINT i, Idx; // unsigned int IrqFlags; // NDIS_SPIN_LOCK *pLock; // BOOLEAN *pPending; // pLock = &pAd->BulkOutLock[MGMTPIPEIDX]; // pPending = &pAd->BulkOutPending[MGMTPIPEIDX]; for (Idx = 0; Idx < 4; Idx++) { pHTTXContext = &(pAd->TxContext[Idx]); if (pHTTXContext->IRPPending == TRUE) { // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself // remove it from the HeadPendingSendList and NULL out HeadPendingSendList // when the last IRP on the list has been cancelled; that's how we exit this loop // RTUSB_UNLINK_URB(pHTTXContext->pUrb); // Sleep 200 microseconds to give cancellation time to work RTMPusecDelay(200); } #ifdef RALINK_ATE pHTTXContext->bCopySavePad = 0; pHTTXContext->CurWritePosition = 0; pHTTXContext->CurWriteRealPos = 0; pHTTXContext->bCurWriting = FALSE; pHTTXContext->NextBulkOutPosition = 0; pHTTXContext->ENextBulkOutPosition = 0; #endif // RALINK_ATE // pAd->BulkOutPending[Idx] = FALSE; } //RTMP_IRQ_LOCK(pLock, IrqFlags); for (i = 0; i < MGMT_RING_SIZE; i++) { pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa; if(pMLMEContext && (pMLMEContext->IRPPending == TRUE)) { // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself // remove it from the HeadPendingSendList and NULL out HeadPendingSendList // when the last IRP on the list has been cancelled; that's how we exit this loop // RTUSB_UNLINK_URB(pMLMEContext->pUrb); pMLMEContext->IRPPending = FALSE; // Sleep 200 microsecs to give cancellation time to work RTMPusecDelay(200); } } pAd->BulkOutPending[MGMTPIPEIDX] = FALSE; //RTMP_IRQ_UNLOCK(pLock, IrqFlags); for (i = 0; i < BEACON_RING_SIZE; i++) { pBeaconContext = &(pAd->BeaconContext[i]); if(pBeaconContext->IRPPending == TRUE) { // Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself // remove it from the HeadPendingSendList and NULL out HeadPendingSendList // when the last IRP on the list has been cancelled; that's how we exit this loop // RTUSB_UNLINK_URB(pBeaconContext->pUrb); // Sleep 200 microsecs to give cancellation time to work RTMPusecDelay(200); } } pNullContext = &(pAd->NullContext); if (pNullContext->IRPPending == TRUE) RTUSB_UNLINK_URB(pNullContext->pUrb); pRTSContext = &(pAd->RTSContext); if (pRTSContext->IRPPending == TRUE) RTUSB_UNLINK_URB(pRTSContext->pUrb); pPsPollContext = &(pAd->PsPollContext); if (pPsPollContext->IRPPending == TRUE) RTUSB_UNLINK_URB(pPsPollContext->pUrb); for (Idx = 0; Idx < 4; Idx++) { NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]); pAd->BulkOutPending[Idx] = FALSE; NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]); } }