VOID CMDHandler( IN PRTMP_ADAPTER pAd) { PCmdQElmt cmdqelmt; PUCHAR pData; NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; // ULONG Now = 0; NTSTATUS ntStatus; // unsigned long IrqFlags; while (pAd && pAd->CmdQ.size > 0) { NdisStatus = NDIS_STATUS_SUCCESS; NdisAcquireSpinLock(&pAd->CmdQLock); RTThreadDequeueCmd(&pAd->CmdQ, &cmdqelmt); NdisReleaseSpinLock(&pAd->CmdQLock); if (cmdqelmt == NULL) break; pData = cmdqelmt->buffer; if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { switch (cmdqelmt->command) { case CMDTHREAD_CHECK_GPIO: { #ifdef CONFIG_STA_SUPPORT UINT32 data; #endif // CONFIG_STA_SUPPORT // #ifdef RALINK_ATE if(ATE_ON(pAd)) { ATEDBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); break; } #endif // RALINK_ATE // #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { // Read GPIO pin2 as Hardware controlled radio state RTUSBReadMACRegister( pAd, GPIO_CTRL_CFG, &data); if (data & 0x04) { pAd->StaCfg.bHwRadio = TRUE; } else { pAd->StaCfg.bHwRadio = FALSE; } if(pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) { pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio); if(pAd->StaCfg.bRadio == TRUE) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio On !!!\n")); MlmeRadioOn(pAd); // Update extra information pAd->ExtraInfo = EXTRA_INFO_CLEAR; } else { DBGPRINT_RAW(RT_DEBUG_ERROR, ("!!! Radio Off !!!\n")); MlmeRadioOff(pAd); // Update extra information pAd->ExtraInfo = HW_RADIO_OFF; } } } #endif // CONFIG_STA_SUPPORT // } break; #ifdef CONFIG_STA_SUPPORT case CMDTHREAD_QKERIODIC_EXECUT: { StaQuickResponeForRateUpExec(NULL, pAd, NULL, NULL); } break; #endif // CONFIG_STA_SUPPORT // case CMDTHREAD_RESET_BULK_OUT: { UINT32 MACValue; UCHAR Index; int ret=0; PHT_TX_CONTEXT pHTTXContext; // RTMP_TX_RING *pTxRing; unsigned long IrqFlags; DBGPRINT(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid)); // All transfers must be aborted or cancelled before attempting to reset the pipe. //RTUSBCancelPendingBulkOutIRP(pAd); // Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007 Index = 0; do { if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) break; RTUSBReadMACRegister(pAd, TXRXQ_PCNT, &MACValue); if ((MACValue & 0xf00000/*0x800000*/) == 0) break; Index++; RTMPusecDelay(10000); }while(Index < 100); MACValue = 0; RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); // 2nd, to prevent Read Register error, we check the validity. if ((MACValue & 0xc00000) == 0) RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); // 3rd, to prevent Read Register error, we check the validity. if ((MACValue & 0xc00000) == 0) RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue); MACValue |= 0x80000; RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); // Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 RTMPusecDelay(1000); MACValue &= (~0x80000); RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue); DBGPRINT(RT_DEBUG_TRACE, ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n")); // Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007 //RTMPusecDelay(5000); if ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG) { RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) { RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); } RTUSBKickBulkOut(pAd); DBGPRINT(RT_DEBUG_TRACE, ("\tTX MGMT RECOVER Done!\n")); } else { pHTTXContext = &(pAd->TxContext[pAd->bulkResetPipeid]); //NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); if ( pAd->BulkOutPending[pAd->bulkResetPipeid] == FALSE) { pAd->BulkOutPending[pAd->bulkResetPipeid] = TRUE; pHTTXContext->IRPPending = TRUE; pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 1; // no matter what, clean the flag RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); #ifdef RALINK_ATE if(ATE_ON(pAd)) { ret = ATEResetBulkOut(pAd); } else #endif // RALINK_ATE // { RTUSBInitHTTxDesc(pAd, pHTTXContext, pAd->bulkResetPipeid, pHTTXContext->BulkOutSize, (usb_complete_t)RTUSBBulkOutDataPacketComplete); if((ret = RTUSB_SUBMIT_URB(pHTTXContext->pUrb))!=0) { RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); pAd->BulkOutPending[pAd->bulkResetPipeid] = FALSE; pHTTXContext->IRPPending = FALSE; pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 0; RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_OUT:Submit Tx URB failed %d\n", ret)); } else { RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_TRACE,("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n", pAd->bulkResetPipeid, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, pAd->BulkOutPending[pAd->bulkResetPipeid])); DBGPRINT(RT_DEBUG_TRACE,("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_TRACE, ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pHTTXContext->pUrb->rtusb_urb_status)); } } } else { //NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]); //RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); DBGPRINT(RT_DEBUG_ERROR, ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n", pAd->bulkResetReq[pAd->bulkResetPipeid], pAd->bulkResetPipeid)); if (pAd->bulkResetPipeid == 0) { UCHAR pendingContext = 0; PHT_TX_CONTEXT pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[pAd->bulkResetPipeid ]); PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa); PTX_CONTEXT pNULLContext = (PTX_CONTEXT)(&pAd->PsPollContext); PTX_CONTEXT pPsPollContext = (PTX_CONTEXT)(&pAd->NullContext); if (pHTTXContext->IRPPending) pendingContext |= 1; else if (pMLMEContext->IRPPending) pendingContext |= 2; else if (pNULLContext->IRPPending) pendingContext |= 4; else if (pPsPollContext->IRPPending) pendingContext |= 8; else pendingContext = 0; DBGPRINT(RT_DEBUG_ERROR, ("\tTX Occupied by %d!\n", pendingContext)); } // no matter what, clean the flag RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << pAd->bulkResetPipeid)); } RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); //RTUSBKickBulkOut(pAd); } } /* // Don't cancel BULKIN. while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { if (atomic_read(&pAd->PendingRx) > 0) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!cancel it!\n")); RTUSBCancelPendingBulkInIRP(pAd); } RTMPusecDelay(100000); } if ((atomic_read(&pAd->PendingRx) == 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { UCHAR i; RTUSBRxPacket(pAd); pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer for (i = 0; i < (RX_RING_SIZE); i++) { PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); pRxContext->pAd = pAd; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->Readable = FALSE; pRxContext->ReorderInUse = FALSE; } RTUSBBulkReceive(pAd); DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTUSBBulkReceive\n")); }*/ DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n")); break; case CMDTHREAD_RESET_BULK_IN: DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n")); // All transfers must be aborted or cancelled before attempting to reset the pipe. { UINT32 MACValue; #ifdef RALINK_ATE if (ATE_ON(pAd)) { ATEResetBulkIn(pAd); } else #endif // RALINK_ATE // { //while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!!\n")); RTUSBCancelPendingBulkInIRP(pAd); RTMPusecDelay(100000); pAd->PendingRx = 0; } } // Wait 10ms before reading register. RTMPusecDelay(10000); ntStatus = RTUSBReadMACRegister(pAd, MAC_CSR0, &MACValue); if ((NT_SUCCESS(ntStatus) == TRUE) && (!(RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))))) { UCHAR i; if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))) break; pAd->NextRxBulkInPosition = pAd->RxContext[pAd->NextRxBulkInIndex].BulkInOffset; DBGPRINT(RT_DEBUG_TRACE, ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n", pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pAd->NextRxBulkInPosition, pAd->BulkInReq, pAd->BulkInComplete, pAd->BulkInCompleteFail)); for (i = 0; i < RX_RING_SIZE; i++) { DBGPRINT(RT_DEBUG_TRACE, ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n" , i, pAd->RxContext[i].IRPPending, pAd->RxContext[i].InUse, pAd->RxContext[i].Readable)); } /* DBGPRINT_RAW(RT_DEBUG_ERROR, ("==========================================\n")); pAd->NextRxBulkInReadIndex = 0; // Next Rx Read index pAd->NextRxBulkInIndex = 0; // Rx Bulk pointer for (i = 0; i < (RX_RING_SIZE); i++) { PRX_CONTEXT pRxContext = &(pAd->RxContext[i]); pRxContext->pAd = pAd; pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->Readable = FALSE; pRxContext->ReorderInUse = FALSE; }*/ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); for (i = 0; i < pAd->CommonCfg.NumOfBulkInIRP; i++) { //RTUSBBulkReceive(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); break; } pRxContext->InUse = TRUE; pRxContext->IRPPending = TRUE; pAd->PendingRx++; pAd->BulkInReq++; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); // Init Rx context descriptor 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, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", ret, pUrb->rtusb_urb_status)); } else { // success //DBGPRINT(RT_DEBUG_TRACE, ("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", // pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex)); DBGPRINT_RAW(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", pUrb->rtusb_urb_status)); ASSERT((pRxContext->InUse == pRxContext->IRPPending)); } } } else { // Card must be removed if (NT_SUCCESS(ntStatus) != TRUE) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n")); } else { DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", pAd->Flags)); } } } DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n")); break; case CMDTHREAD_SET_ASIC_WCID: { RT_SET_ASIC_WCID SetAsicWcid; USHORT offset; UINT32 MACValue, MACRValue = 0; SetAsicWcid = *((PRT_SET_ASIC_WCID)(pData)); if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE) return; offset = MAC_WCID_BASE + ((UCHAR)SetAsicWcid.WCID)*HW_WCID_ENTRY_SIZE; DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid = %lx, DeleteTid = %lx.\n", SetAsicWcid.WCID, SetAsicWcid.SetTid, SetAsicWcid.DeleteTid)); MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[3]<<24)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[2]<<16)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[1]<<8)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[0]); DBGPRINT_RAW(RT_DEBUG_TRACE, ("1-MACValue= %x,\n", MACValue)); RTUSBWriteMACRegister(pAd, offset, MACValue); // Read bitmask RTUSBReadMACRegister(pAd, offset+4, &MACRValue); if ( SetAsicWcid.DeleteTid != 0xffffffff) MACRValue &= (~SetAsicWcid.DeleteTid); if (SetAsicWcid.SetTid != 0xffffffff) MACRValue |= (SetAsicWcid.SetTid); MACRValue &= 0xffff0000; MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[5]<<8)+pAd->MacTab.Content[SetAsicWcid.WCID].Addr[4]; MACValue |= MACRValue; RTUSBWriteMACRegister(pAd, offset+4, MACValue); DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-MACValue= %x,\n", MACValue)); } break; /* Security Related for Asic command */ case CMDTHREAD_SET_WCID_SEC_INFO: { PRT_ASIC_WCID_SEC_INFO pInfo; pInfo = (PRT_ASIC_WCID_SEC_INFO)pData; RTMPSetWcidSecurityInfo(pAd, pInfo->BssIdx, pInfo->KeyIdx, pInfo->CipherAlg, pInfo->Wcid, pInfo->KeyTabFlag); } break; case CMDTHREAD_SET_ASIC_WCID_IVEIV: { PRT_ASIC_WCID_IVEIV_ENTRY pInfo; pInfo = (PRT_ASIC_WCID_IVEIV_ENTRY)pData; AsicUpdateWCIDIVEIV(pAd, pInfo->Wcid, pInfo->Iv, pInfo->Eiv); } break; case CMDTHREAD_SET_ASIC_WCID_ATTR: { PRT_ASIC_WCID_ATTR_ENTRY pInfo; pInfo = (PRT_ASIC_WCID_ATTR_ENTRY)pData; AsicUpdateWcidAttributeEntry(pAd, pInfo->BssIdx, pInfo->KeyIdx, pInfo->CipherAlg, pInfo->Wcid, pInfo->KeyTabFlag); } break; case CMDTHREAD_SET_ASIC_SHARED_KEY: { PRT_ASIC_SHARED_KEY pInfo; pInfo = (PRT_ASIC_SHARED_KEY)pData; AsicAddSharedKeyEntry(pAd, pInfo->BssIndex, pInfo->KeyIdx, &pInfo->CipherKey); } break; case CMDTHREAD_SET_ASIC_PAIRWISE_KEY: { PRT_ASIC_PAIRWISE_KEY pInfo; pInfo = (PRT_ASIC_PAIRWISE_KEY)pData; AsicAddPairwiseKeyEntry(pAd, pInfo->WCID, &pInfo->CipherKey); } break; case CMDTHREAD_SET_PORT_SECURED: { #ifdef CONFIG_STA_SUPPORT STA_PORT_SECURED(pAd); #endif // CONFIG_STA_SUPPORT // } break; case CMDTHREAD_REMOVE_PAIRWISE_KEY: { UCHAR Wcid = *((PUCHAR)(pData)); AsicRemovePairwiseKeyEntry(pAd, Wcid); } break; case CMDTHREAD_SET_CLIENT_MAC_ENTRY: { PRT_SET_ASIC_WCID pInfo; pInfo = (PRT_SET_ASIC_WCID)pData; AsicUpdateRxWCIDTable(pAd, pInfo->WCID, pInfo->Addr); } break; // add by johnli, fix "in_interrupt" error when call "MacTableDeleteEntry" in Rx tasklet case CMDTHREAD_UPDATE_PROTECT: { AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT), TRUE, 0); } break; // end johnli case CMDTHREAD_802_11_COUNTER_MEASURE: break; #ifdef CONFIG_STA_SUPPORT case CMDTHREAD_SET_PSM_BIT: IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { USHORT *pPsm = (USHORT *)pData; MlmeSetPsmBit(pAd, *pPsm); } break; case CMDTHREAD_FORCE_WAKE_UP: IF_DEV_CONFIG_OPMODE_ON_STA(pAd) AsicForceWakeup(pAd, TRUE); break; case CMDTHREAD_FORCE_SLEEP_AUTO_WAKEUP: { USHORT TbttNumToNextWakeUp; USHORT NextDtim = pAd->StaCfg.DtimPeriod; ULONG Now; NdisGetSystemUpTime(&Now); NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod; TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) TbttNumToNextWakeUp = NextDtim; RTMP_SET_PSM_BIT(pAd, PWR_SAVE); // if WMM-APSD is failed, try to disable following line AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); } break; #endif // CONFIG_STA_SUPPORT // default: DBGPRINT(RT_DEBUG_ERROR, ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", cmdqelmt->command)); break; } } if (cmdqelmt->CmdFromNdis == TRUE) { if (cmdqelmt->buffer != NULL) os_free_mem(pAd, cmdqelmt->buffer); os_free_mem(pAd, cmdqelmt); } else { if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0)) os_free_mem(pAd, cmdqelmt->buffer); os_free_mem(pAd, cmdqelmt); } } /* end of while */ }
/* ======================================================================== Routine Description: USB command kernel thread. Arguments: *Context the pAd, driver control block pointer Return Value: 0 close the thread Note: ======================================================================== */ INT RTUSBCmdThread( IN ULONG Context) { RTMP_ADAPTER *pAd; RTMP_OS_TASK *pTask; int status; status = 0; pTask = (RTMP_OS_TASK *)Context; pAd = (PRTMP_ADAPTER)pTask->priv; RtmpOSTaskCustomize(pTask); NdisAcquireSpinLock(&pAd->CmdQLock); pAd->CmdQ.CmdQState = RTMP_TASK_STAT_RUNNING; NdisReleaseSpinLock(&pAd->CmdQLock); while (pAd && pAd->CmdQ.CmdQState == RTMP_TASK_STAT_RUNNING) { #ifdef KTHREAD_SUPPORT RTMP_WAIT_EVENT_INTERRUPTIBLE(pAd, pTask); #else /* lock the device pointers */ RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), status); if (status != 0) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); break; } #endif if (pAd->CmdQ.CmdQState == RTMP_TASK_STAT_STOPED) break; if (!pAd->PM_FlgSuspend) CMDHandler(pAd); } if (pAd && !pAd->PM_FlgSuspend) { // Clear the CmdQElements. CmdQElmt *pCmdQElmt = NULL; NdisAcquireSpinLock(&pAd->CmdQLock); pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED; while(pAd->CmdQ.size) { RTThreadDequeueCmd(&pAd->CmdQ, &pCmdQElmt); if (pCmdQElmt) { if (pCmdQElmt->CmdFromNdis == TRUE) { if (pCmdQElmt->buffer != NULL) os_free_mem(pAd, pCmdQElmt->buffer); os_free_mem(pAd, (PUCHAR)pCmdQElmt); } else { if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0)) os_free_mem(pAd, pCmdQElmt->buffer); os_free_mem(pAd, (PUCHAR)pCmdQElmt); } } } NdisReleaseSpinLock(&pAd->CmdQLock); } /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), * except that complete() is safe in the case where the structure * is getting deleted in a parallel mode of execution (i.e. just * after the down() -- that's necessary for the thread-shutdown * case. * * complete_and_exit() goes even further than this -- it is safe in * the case that the thread of the caller is going away (not just * the structure) -- this is necessary for the module-remove case. * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n")); #ifndef KTHREAD_SUPPORT pTask->taskPID = THREAD_PID_INIT_VALUE; complete_and_exit (&pTask->taskComplete, 0); #endif return 0; }
/* ======================================================================== Routine Description: USB command kernel thread. Arguments: *Context the pAd, driver control block pointer Return Value: 0 close the thread Note: ======================================================================== */ INT RTUSBCmdThread( IN ULONG Context) { RTMP_ADAPTER *pAd; RTMP_OS_TASK *pTask; int status; status = 0; pTask = (RTMP_OS_TASK *)Context; pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); if (pAd == NULL) return 0; RtmpOSTaskCustomize(pTask); NdisAcquireSpinLock(&pAd->CmdQLock); pAd->CmdQ.CmdQState = RTMP_TASK_STAT_RUNNING; NdisReleaseSpinLock(&pAd->CmdQLock); while (pAd->CmdQ.CmdQState == RTMP_TASK_STAT_RUNNING) { if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) { DBGPRINT_ERR(("RtmpOSTaskWait returned false in RTUSBCmdThread, setting halt in progress flag!\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); break; } if (pAd->CmdQ.CmdQState == RTMP_TASK_STAT_STOPED) break; if (!pAd->PM_FlgSuspend) CMDHandler(pAd); } if (!pAd->PM_FlgSuspend) { /* Clear the CmdQElements. */ CmdQElmt *pCmdQElmt = NULL; NdisAcquireSpinLock(&pAd->CmdQLock); pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED; while(pAd->CmdQ.size) { RTThreadDequeueCmd(&pAd->CmdQ, &pCmdQElmt); if (pCmdQElmt) { if (pCmdQElmt->CmdFromNdis == TRUE) { if (pCmdQElmt->buffer != NULL) os_free_mem(pAd, pCmdQElmt->buffer); os_free_mem(pAd, (PUCHAR)pCmdQElmt); } else { if ((pCmdQElmt->buffer != NULL) && (pCmdQElmt->bufferlength != 0)) os_free_mem(pAd, pCmdQElmt->buffer); os_free_mem(pAd, (PUCHAR)pCmdQElmt); } } } NdisReleaseSpinLock(&pAd->CmdQLock); } /* notify the exit routine that we're actually exiting now * * complete()/wait_for_completion() is similar to up()/down(), * except that complete() is safe in the case where the structure * is getting deleted in a parallel mode of execution (i.e. just * after the down() -- that's necessary for the thread-shutdown * case. * * complete_and_exit() goes even further than this -- it is safe in * the case that the thread of the caller is going away (not just * the structure) -- this is necessary for the module-remove case. * This is important in preemption kernels, which transfer the flow * of execution immediately upon a complete(). */ DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n")); RtmpOSTaskNotifyToExit(pTask); return 0; }