/* *************************************************************************** * Ralink Tech Inc. * 4F, No. 2 Technology 5th Rd. * Science-based Industrial Park * Hsin-chu, Taiwan, R.O.C. * * (c) Copyright 2002-2006, Ralink Technology, Inc. * * All rights reserved. Ralink's source code is an unpublished work and the * use of a copyright notice does not imply otherwise. This source code * contains confidential trade secret material of Ralink Tech. Any attemp * or participation in deciphering, decoding, reverse engineering or in any * way altering the source code is stricitly prohibited, unless the prior * written consent of Ralink Technology, Inc. is obtained. *************************************************************************** Module Name: rtusb_bulk.c Abstract: Revision History: Who When What -------- ---------- ---------------------------------------------- Name Date Modification logs */ #include "rt_config.h" /* ======================================================================== Routine Description: Create kernel threads & tasklets. Arguments: *net_dev Pointer to wireless net device interface Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_FAILURE Note: ======================================================================== */ NDIS_STATUS RtmpMgmtTaskInit( IN RTMP_ADAPTER *pAd) { RTMP_OS_TASK *pTask; NDIS_STATUS status; /* Creat TimerQ Thread, We need init timerQ related structure before create the timer thread. */ RtmpTimerQInit(pAd); pTask = &pAd->timerTask; RTMP_OS_TASK_INIT(pTask, "RtmpTimerTask", pAd); status = RtmpOSTaskAttach(pTask, RtmpTimerQThread, (ULONG)pTask); if (status == NDIS_STATUS_FAILURE) { printk (KERN_WARNING "%s: unable to start RtmpTimerQThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); return NDIS_STATUS_FAILURE; } /* Creat MLME Thread */ pTask = &pAd->mlmeTask; RTMP_OS_TASK_INIT(pTask, "RtmpMlmeTask", pAd); status = RtmpOSTaskAttach(pTask, MlmeThread, (ULONG)pTask); if (status == NDIS_STATUS_FAILURE) { printk (KERN_WARNING "%s: unable to start MlmeThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); return NDIS_STATUS_FAILURE; } /* Creat Command Thread */ pTask = &pAd->cmdQTask; RTMP_OS_TASK_INIT(pTask, "RtmpCmdQTask", pAd); status = RtmpOSTaskAttach(pTask, RTUSBCmdThread, (ULONG)pTask); if (status == NDIS_STATUS_FAILURE) { printk (KERN_WARNING "%s: unable to start RTUSBCmdThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); return NDIS_STATUS_FAILURE; } #ifdef WSC_INCLUDED /* start the crediential write task first. */ WscThreadInit(pAd); #endif /* WSC_INCLUDED */ return NDIS_STATUS_SUCCESS; } /* ======================================================================== Routine Description: Close kernel threads. Arguments: *pAd the raxx interface data pointer Return Value: NONE Note: ======================================================================== */ VOID RtmpMgmtTaskExit( IN RTMP_ADAPTER *pAd) { INT ret; RTMP_OS_TASK *pTask; /* Sleep 50 milliseconds so pending io might finish normally */ RTMPusecDelay(50000); /* We want to wait until all pending receives and sends to the */ /* device object. We cancel any */ /* irps. Wait until sends and receives have stopped. */ RTUSBCancelPendingIRPs(pAd); /* We need clear timerQ related structure before exits of the timer thread. */ RtmpTimerQExit(pAd); /* Terminate Mlme Thread */ pTask = &pAd->mlmeTask; ret = RtmpOSTaskKill(pTask); if (ret == NDIS_STATUS_FAILURE) { /* DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", */ /* RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev), pTask->taskName)); */ DBGPRINT(RT_DEBUG_ERROR, ("kill mlme task failed!\n")); } /* Terminate cmdQ thread */ pTask = &pAd->cmdQTask; RTMP_OS_TASK_LEGALITY(pTask) { NdisAcquireSpinLock(&pAd->CmdQLock); pAd->CmdQ.CmdQState = RTMP_TASK_STAT_STOPED; NdisReleaseSpinLock(&pAd->CmdQLock); /*RTUSBCMDUp(&pAd->cmdQTask); */ ret = RtmpOSTaskKill(pTask); if (ret == NDIS_STATUS_FAILURE) { /* DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", */ /* RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev), pTask->taskName)); */ DBGPRINT(RT_DEBUG_ERROR, ("kill command task failed!\n")); } pAd->CmdQ.CmdQState = RTMP_TASK_STAT_UNKNOWN; } /* Terminate timer thread */ pTask = &pAd->timerTask; ret = RtmpOSTaskKill(pTask); if (ret == NDIS_STATUS_FAILURE) { /* DBGPRINT(RT_DEBUG_ERROR, ("%s: kill task(%s) failed!\n", */ /* RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev), pTask->taskName)); */ DBGPRINT(RT_DEBUG_ERROR, ("kill timer task failed!\n")); } #ifdef WSC_INCLUDED WscThreadExit(pAd); #endif /* WSC_INCLUDED */ } static void rtusb_dataout_complete(unsigned long data) { PRTMP_ADAPTER pAd; purbb_t pUrb; POS_COOKIE pObj; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId; NTSTATUS Status; unsigned long IrqFlags; pUrb = (purbb_t)data; /* pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; */ pHTTXContext = (PHT_TX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pHTTXContext->pAd; pObj = (POS_COOKIE) pAd->OS_Cookie; /* Status = pUrb->status; */ /* Store BulkOut PipeId */ BulkOutPipeId = pHTTXContext->BulkOutPipeId; pAd->BulkOutDataOneSecCount++; /*DBGPRINT(RT_DEBUG_LOUD, ("Done-B(%d):I=0x%lx, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", BulkOutPipeId, in_interrupt(), pHTTXContext->CurWritePosition, */ /* pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad)); */ RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; pHTTXContext->IRPPending = FALSE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; if (Status == USB_ST_NOERROR) { pAd->BulkOutComplete++; RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->Counters8023.GoodTransmits++; /*RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ FREE_HTTX_RING(pAd, BulkOutPipeId, pHTTXContext); /*RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags); */ #ifdef UAPSD_SUPPORT #ifdef DOT11Z_TDLS_SUPPORT UAPSD_UnTagFrame(pAd, BulkOutPipeId, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition); #else #ifdef CONFIG_AP_SUPPORT #ifdef P2P_SUPPORT if (P2P_GO_ON(pAd)) #else IF_DEV_CONFIG_OPMODE_ON_AP(pAd) #endif /* P2P_SUPPORT */ { UAPSD_UnTagFrame(pAd, BulkOutPipeId, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition); } #endif /* CONFIG_AP_SUPPORT */ #endif /* DOT11Z_TDLS_SUPPORT */ #endif /* UAPSD_SUPPORT */ } else /* STATUS_OTHER */ { PUCHAR pBuf; pAd->BulkOutCompleteOther++; pBuf = &pHTTXContext->TransferBuffer->field.WirelessPacket[pHTTXContext->NextBulkOutPosition]; 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; pAd->bulkResetReq[BulkOutPipeId] = pAd->BulkOutReq; } RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkOutDataPacket failed: ReasonCode=%d!\n", Status)); DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>BulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); DBGPRINT_RAW(RT_DEBUG_ERROR, ("\t>>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)); */ } #ifdef CONFIG_MULTI_CHANNEL if ((pAd->MultiChannelFlowCtl & (1 << BulkOutPipeId)) == (1 << BulkOutPipeId)) return; #endif /* CONFIG_MULTI_CHANNEL */ /* */ /* 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))) #ifdef USB_BULK_BUF_ALIGMENT || (pHTTXContext->NextBulkIdx != pHTTXContext->CurWriteIdx) #endif /* USB_BULK_BUF_ALIGMENT */ ) { /* 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); } static void rtusb_null_frame_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pNullContext; purbb_t pUrb; NTSTATUS Status; unsigned long irqFlag; pUrb = (purbb_t)data; /* pNullContext = (PTX_CONTEXT)pUrb->context; */ pNullContext = (PTX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pNullContext->pAd; /* Status = pUrb->status; */ /* Reset Null frame context flags */ RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], irqFlag); pNullContext->IRPPending = FALSE; pNullContext->InUse = FALSE; pAd->BulkOutPending[0] = FALSE; pAd->watchDogTxPendingCnt[0] = 0; if (Status == USB_ST_NOERROR) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else /* STATUS_OTHER */ { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", Status)); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); #ifdef CONFIG_MULTI_CHANNEL if (pAd->Multi_Channel_Enable == TRUE) pAd->bulkResetPipeid = (0 | BULKOUT_MGMT_RESET_FLAG); else #endif /* CONFIG_MULTI_CHANNEL */ pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], irqFlag); } } /* Always call Bulk routine, even reset bulk. */ /* The protectioon of rest bulk should be in BulkOut routine */ RTUSBKickBulkOut(pAd); } #ifdef CONFIG_MULTI_CHANNEL static void rtusb_hcca_null_frame_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pNullContext; purbb_t pUrb; NTSTATUS Status; unsigned long irqFlag; UCHAR BulkOutPipeId; pUrb = (purbb_t)data; pNullContext = (PTX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pNullContext->pAd; BulkOutPipeId = pNullContext->BulkOutPipeId; /* Status = pUrb->status; */ /* Reset Null frame context flags */ RTMP_IRQ_LOCK(&pAd->BulkOutLock[BulkOutPipeId], irqFlag); pNullContext->IRPPending = FALSE; pNullContext->InUse = FALSE; pAd->BulkOutPending[BulkOutPipeId] = FALSE; pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0; if (Status == USB_ST_NOERROR) { RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], irqFlag); RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else /* STATUS_OTHER */ { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out Null Frame Failed, ReasonCode=%d!\n", Status)); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); pAd->bulkResetPipeid = (BulkOutPipeId | BULKOUT_MGMT_RESET_FLAG); RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], irqFlag); RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], irqFlag); } /* Always call Bulk routine, even reset bulk. */ /* The protectioon of rest bulk should be in BulkOut routine */ RTUSBKickBulkOut(pAd); } #endif /* CONFIG_MULTI_CHANNEL */ static void rtusb_pspoll_frame_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pPsPollContext; purbb_t pUrb; NTSTATUS Status; pUrb = (purbb_t)data; /* pPsPollContext = (PTX_CONTEXT)pUrb->context; */ pPsPollContext = (PTX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pPsPollContext->pAd; /* Status = pUrb->status; */ /* Reset PsPoll context flags */ pPsPollContext->IRPPending = FALSE; pPsPollContext->InUse = FALSE; pAd->watchDogTxPendingCnt[0] = 0; if (Status == USB_ST_NOERROR) { RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS); } else /* STATUS_OTHER */ { if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk Out PSPoll Failed\n")); RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); #ifdef CONFIG_MULTI_CHANNEL if (pAd->Multi_Channel_Enable == TRUE) pAd->bulkResetPipeid = (0 | BULKOUT_MGMT_RESET_FLAG); else #endif /* CONFIG_MULTI_CHANNEL */ pAd->bulkResetPipeid = (MGMTPIPEIDX | BULKOUT_MGMT_RESET_FLAG); RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } } RTMP_SEM_LOCK(&pAd->BulkOutLock[0]); pAd->BulkOutPending[0] = FALSE; RTMP_SEM_UNLOCK(&pAd->BulkOutLock[0]); /* Always call Bulk routine, even reset bulk. */ /* The protectioon of rest bulk should be in BulkOut routine */ RTUSBKickBulkOut(pAd); } /* ======================================================================== Routine Description: Handle received packets. Arguments: data - URB information pointer Return Value: None Note: ======================================================================== */ static void rx_done_tasklet(unsigned long data) { purbb_t pUrb; PRX_CONTEXT pRxContext; PRTMP_ADAPTER pAd; NTSTATUS Status; unsigned int IrqFlags; pUrb = (purbb_t)data; /* pRxContext = (PRX_CONTEXT)pUrb->context; */ pRxContext = (PRX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pRxContext->pAd; /* Status = pUrb->status; */ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); pRxContext->InUse = FALSE; pRxContext->IRPPending = FALSE; pRxContext->BulkInOffset += RTMP_USB_URB_LEN_GET(pUrb); /*pUrb->actual_length; */ /*NdisInterlockedDecrement(&pAd->PendingRx); */ if ( pAd->PendingRx > 0 ) pAd->PendingRx--; if (Status == USB_ST_NOERROR) { pAd->BulkInComplete++; pAd->NextRxBulkInPosition = 0; if (pRxContext->BulkInOffset) /* As jan's comment, it may bulk-in success but size is zero. */ { pRxContext->Readable = TRUE; INC_RING_INDEX(pAd->NextRxBulkInIndex, RX_RING_SIZE); } RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); } else /* STATUS_OTHER */ { pAd->BulkInCompleteFail++; /* Still read this packet although it may comtain wrong bytes. */ pRxContext->Readable = FALSE; RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); /* Parsing all packets. because after reset, the index will reset to all zero. */ if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_BULKIN_RESET | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { DBGPRINT_RAW(RT_DEBUG_ERROR, ("Bulk In Failed. Status=%d, BIIdx=0x%x, BIRIdx=0x%x, actual_length= 0x%x\n", Status, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, RTMP_USB_URB_LEN_GET(pRxContext->pUrb))); /*->actual_length)); */ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0); } } ASSERT((pRxContext->InUse == pRxContext->IRPPending)); #ifdef RALINK_ATE if (ATE_ON(pAd)) { /* If the driver is in ATE mode and Rx frame is set into here. */ if (pAd->ContinBulkIn == TRUE) { RTUSBBulkReceive(pAd); } } else #endif /* RALINK_ATE */ RTUSBBulkReceive(pAd); return; } #ifdef RLT_MAC static void cmd_rsp_event_tasklet(unsigned long data) { purbb_t pUrb; PCMD_RSP_CONTEXT pCmdRspEventContext; PRTMP_ADAPTER pAd; NTSTATUS Status; unsigned int IrqFlags; pUrb = (purbb_t)data; pCmdRspEventContext = (PRX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pCmdRspEventContext->pAd; RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags); pCmdRspEventContext->IRPPending = FALSE; pCmdRspEventContext->InUse = FALSE; RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags); if (Status == USB_ST_NOERROR) { RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags); pCmdRspEventContext->Readable = TRUE; RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags); } else { RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags); pCmdRspEventContext->Readable = FALSE; RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags); } RTUSBBulkCmdRspEventReceive(pAd); } #endif /* RLT_MAC */ static void rtusb_mgmt_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pMLMEContext; int index; PNDIS_PACKET pPacket; purbb_t pUrb; NTSTATUS Status; unsigned long IrqFlags; pUrb = (purbb_t)data; /* pMLMEContext = (PTX_CONTEXT)pUrb->context; */ pMLMEContext = (PTX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); Status = RTMP_USB_URB_STATUS_GET(pUrb); pAd = pMLMEContext->pAd; /* Status = pUrb->status; */ index = pMLMEContext->SelfIdx; ASSERT((pAd->MgmtRing.TxDmaIdx == index)); RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags); #ifdef UAPSD_SUPPORT /* Qos Null frame with EOSP shall have valid Wcid value. reference RtmpUSBMgmtKickOut() API. */ /* otherwise will be value of MCAST_WCID. */ #ifdef DOT11Z_TDLS_SUPPORT if ((pMLMEContext->Wcid != MCAST_WCID) && (pMLMEContext->Wcid < MAX_LEN_OF_MAC_TABLE)) { MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pMLMEContext->Wcid]; UAPSD_SP_Close(pAd, pEntry); pMLMEContext->Wcid = MCAST_WCID; } #else #ifdef CONFIG_AP_SUPPORT #ifdef P2P_SUPPORT if (P2P_GO_ON(pAd)) #else IF_DEV_CONFIG_OPMODE_ON_AP(pAd) #endif /* P2P_SUPPORT */ { /* Qos Null frame with EOSP shall have valid Wcid value. reference RtmpUSBMgmtKickOut() API. */ /* otherwise will be value of MCAST_WCID. */ if ((pMLMEContext->Wcid != MCAST_WCID) && (pMLMEContext->Wcid < MAX_LEN_OF_MAC_TABLE)) { MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pMLMEContext->Wcid]; UAPSD_SP_Close(pAd, pEntry); pMLMEContext->Wcid = MCAST_WCID; } } #endif /* CONFIG_AP_SUPPORT */ #endif /* DOT11Z_TDLS_SUPPORT */ #endif /* UAPSD_SUPPORT */ 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 ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { /* do nothing and return directly. */ } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET) && ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG)) { /* For Mgmt Bulk-Out failed, ignore it now. */ RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { /* Always call Bulk routine, even reset bulk. */ /* The protectioon of rest bulk should be in BulkOut routine */ if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) { RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); } RTUSBKickBulkOut(pAd); } } #ifdef CONFIG_STA_SUPPORT #endif /* CONFIG_STA_SUPPORT */ } static void rtusb_hcca_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 4; purbb_t pUrb; DBGPRINT_RAW(RT_DEBUG_ERROR, ("--->hcca_dma_done_tasklet\n")); pUrb = (purbb_t)data; /* pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; */ pHTTXContext = (PHT_TX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); pAd = pHTTXContext->pAd; rtusb_dataout_complete((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { /* do nothing and return directly. */ } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } #ifdef CONFIG_MULTI_CHANNEL if ((pAd->MultiChannelFlowCtl & (1 << BulkOutPipeId)) == (1 << BulkOutPipeId)) return; #endif /* CONFIG_MULTI_CHANNEL */ RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL); RTUSBKickBulkOut(pAd); } } DBGPRINT_RAW(RT_DEBUG_ERROR, ("<---hcca_dma_done_tasklet\n")); return; } static void rtusb_ac3_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 3; purbb_t pUrb; pUrb = (purbb_t)data; /* pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; */ pHTTXContext = (PHT_TX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); pAd = pHTTXContext->pAd; rtusb_dataout_complete((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { /* do nothing and return directly. */ } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } #ifdef CONFIG_MULTI_CHANNEL if ((pAd->MultiChannelFlowCtl & (1 << BulkOutPipeId)) == (1 << BulkOutPipeId)) return; #endif /* CONFIG_MULTI_CHANNEL */ RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<3); RTUSBKickBulkOut(pAd); } } return; } static void rtusb_ac2_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 2; purbb_t pUrb; pUrb = (purbb_t)data; /* pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; */ pHTTXContext = (PHT_TX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); pAd = pHTTXContext->pAd; rtusb_dataout_complete((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { /* do nothing and return directly. */ } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<2); RTUSBKickBulkOut(pAd); } } return; } static void rtusb_ac1_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 1; purbb_t pUrb; pUrb = (purbb_t)data; /* pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; */ pHTTXContext = (PHT_TX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); pAd = pHTTXContext->pAd; rtusb_dataout_complete((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { /* do nothing and return directly. */ } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /*((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL<<1); RTUSBKickBulkOut(pAd); } } return; } static void rtusb_ac0_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PHT_TX_CONTEXT pHTTXContext; UCHAR BulkOutPipeId = 0; purbb_t pUrb; pUrb = (purbb_t)data; /* pHTTXContext = (PHT_TX_CONTEXT)pUrb->context; */ pHTTXContext = (PHT_TX_CONTEXT)RTMP_USB_URB_DATA_GET(pUrb); pAd = pHTTXContext->pAd; rtusb_dataout_complete((unsigned long)pUrb); if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) { /* do nothing and return directly. */ } else { if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) { RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); } else { pHTTXContext = &pAd->TxContext[BulkOutPipeId]; if ((pAd->TxSwQueue[BulkOutPipeId].Number > 0) && /* ((pHTTXContext->CurWritePosition > (pHTTXContext->NextBulkOutPosition + 0x6000)) || (pHTTXContext->NextBulkOutPosition > pHTTXContext->CurWritePosition + 0x6000)) && */ (pAd->DeQueueRunning[BulkOutPipeId] == FALSE) && (pHTTXContext->bCurWriting == FALSE)) { RTMPDeQueuePacket(pAd, FALSE, BulkOutPipeId, MAX_TX_PROCESS); } #ifdef CONFIG_MULTI_CHANNEL if ((pAd->MultiChannelFlowCtl & (1 << BulkOutPipeId)) == (1 << BulkOutPipeId)) return; #endif /* CONFIG_MULTI_CHANNEL */ RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL); RTUSBKickBulkOut(pAd); } } return; } #ifdef RALINK_ATE static void rtusb_ate_ac0_dma_done_tasklet(unsigned long data) { PRTMP_ADAPTER pAd; PTX_CONTEXT pNullContext; UCHAR BulkOutPipeId; NTSTATUS Status; ULONG IrqFlags; ULONG OldValue; purbb_t pURB; pURB = (purbb_t)data; /*pNullContext = (PTX_CONTEXT)pURB->rtusb_urb_context; */ pNullContext = (PTX_CONTEXT)RTMP_USB_URB_DATA_GET(pURB); pAd = pNullContext->pAd; /* Reset Null frame context flags */ pNullContext->IRPPending = FALSE; pNullContext->InUse = FALSE; Status = RTMP_USB_URB_STATUS_GET(pURB);/*pURB->rtusb_urb_status; */ /* Store BulkOut PipeId. */ BulkOutPipeId = pNullContext->BulkOutPipeId; pAd->BulkOutDataOneSecCount++; if (Status == USB_ST_NOERROR) { #ifdef RALINK_QA if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE)) { if (pAd->ate.QID == BulkOutPipeId) { #ifdef RELASE_EXCLUDE /* Let Rx can have a chance to break in during Tx process, especially for loopback mode in QA ATE. To trade off between tx performance and loopback mode integrity. Q : Now Rx is handled by tasklet, do we still need this delay ? Ans : Even tasklet is used, Rx/Tx < 1 if we do not delay for a while right here. */ #endif /* RELASE_EXCLUDE */ RTMPusecDelay(10); pAd->ate.TxDoneCount++; #ifdef RELASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("pAd->ate.TxDoneCount == %d\n", pAd->ate.TxDoneCount)); #endif /* RELASE_EXCLUDE */ pAd->RalinkCounters.KickTxCount++; ASSERT(pAd->ate.QID == 0); pAd->ate.TxAc0++; } } #endif /* RALINK_QA */ pAd->BulkOutComplete++; pAd->Counters8023.GoodTransmits++; /* Don't worry about the queue is empty or not. This function will check itself. */ /* In RT28xx, SendTxWaitQueue == TxSwQueue */ RTMPDeQueuePacket(pAd, TRUE, BulkOutPipeId, MAX_TX_PROCESS); } else { pAd->BulkOutCompleteOther++; DBGPRINT(RT_DEBUG_ERROR, ("BulkOutDataPacket Failed STATUS_OTHER = 0x%x . \n", Status)); DBGPRINT(RT_DEBUG_ERROR, (">>BulkOutReq=0x%lx, BulkOutComplete=0x%lx\n", pAd->BulkOutReq, pAd->BulkOutComplete)); 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))) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); /* In 28xx, RT_OID_USB_RESET_BULK_OUT ==> CMDTHREAD_RESET_BULK_OUT */ RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_OUT, NULL, 0); /* check */ BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; pAd->bulkResetPipeid = BulkOutPipeId; BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); return; } } #ifdef RELASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("pNullContext->pAd = 0x%lx\n", (ULONG)&pNullContext->pAd)); DBGPRINT(RT_DEBUG_INFO, ("pNullContext->pUrb = 0x%lx\n", (ULONG)&pNullContext->pUrb)); DBGPRINT(RT_DEBUG_INFO, ("pNullContext->TransferBuffer = 0x%lx\n", (ULONG)&pNullContext->TransferBuffer)); DBGPRINT(RT_DEBUG_INFO, ("pNullContext->BulkOutPipeId = %d\n", pNullContext->BulkOutPipeId)); DBGPRINT(RT_DEBUG_INFO, ("pNullContext->BulkOutSize = %ld\n", pNullContext->BulkOutSize)); DBGPRINT(RT_DEBUG_INFO, ("pNullContext->InUse = %d\n", (pNullContext->InUse==TRUE))); DBGPRINT(RT_DEBUG_INFO, ("pNullContext->bWaitingBulkOut = %d\n", (pNullContext->bWaitingBulkOut==TRUE))); DBGPRINT(RT_DEBUG_INFO, ("pNullContext->IRPPending = %d\n", (pNullContext->IRPPending==TRUE))); DBGPRINT(RT_DEBUG_INFO, ("pNullContext->LastOne = %d\n", (pNullContext->LastOne==TRUE))); #endif /* RELASE_EXCLUDE */ if (atomic_read(&pAd->BulkOutRemained) > 0) { atomic_dec(&pAd->BulkOutRemained); #ifdef RELASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("Bulk Out Remained = %d\n", atomic_read(&pAd->BulkOutRemained))); #endif /* RELASE_EXCLUDE */ } /* 1st - Transmit Success */ OldValue = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart; pAd->WlanCounters.TransmittedFragmentCount.u.LowPart++; if (pAd->WlanCounters.TransmittedFragmentCount.u.LowPart < OldValue) { pAd->WlanCounters.TransmittedFragmentCount.u.HighPart++; } if (((pAd->ContinBulkOut == TRUE ) ||(atomic_read(&pAd->BulkOutRemained) > 0)) && (pAd->ate.Mode & ATE_TXFRAME)) { #ifdef RELASE_EXCLUDE DBGPRINT(RT_DEBUG_INFO, ("Continue to BulkOut ! \n")); #endif /* RELASE_EXCLUDE */ RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); } else { RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE); #ifdef RALINK_QA pAd->ate.TxStatus = 0; #endif /* RALINK_QA */ } BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); pAd->BulkOutPending[BulkOutPipeId] = FALSE; BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags); /* Always call Bulk routine, even reset bulk. */ /* The protection of rest bulk should be in BulkOut routine. */ RTUSBKickBulkOut(pAd); } #endif /* RALINK_ATE */ NDIS_STATUS RtmpNetTaskInit( IN RTMP_ADAPTER *pAd) { POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; /* Create receive tasklet */ RTMP_OS_TASKLET_INIT(pAd, &pObj->rx_done_task, rx_done_tasklet, (ULONG)pAd); #ifdef RLT_MAC RTMP_OS_TASKLET_INIT(pAd, &pObj->cmd_rsp_event_task, cmd_rsp_event_tasklet, (ULONG)pAd); #endif /* RLT_MAC */ RTMP_OS_TASKLET_INIT(pAd, &pObj->mgmt_dma_done_task, rtusb_mgmt_dma_done_tasklet, (unsigned long)pAd); RTMP_OS_TASKLET_INIT(pAd, &pObj->ac0_dma_done_task, rtusb_ac0_dma_done_tasklet, (unsigned long)pAd); #ifdef RALINK_ATE RTMP_OS_TASKLET_INIT(pAd, &pObj->ate_ac0_dma_done_task, rtusb_ate_ac0_dma_done_tasklet, (unsigned long)pAd); #endif /* RALINK_ATE */ RTMP_OS_TASKLET_INIT(pAd, &pObj->ac1_dma_done_task, rtusb_ac1_dma_done_tasklet, (unsigned long)pAd); RTMP_OS_TASKLET_INIT(pAd, &pObj->ac2_dma_done_task, rtusb_ac2_dma_done_tasklet, (unsigned long)pAd); RTMP_OS_TASKLET_INIT(pAd, &pObj->ac3_dma_done_task, rtusb_ac3_dma_done_tasklet, (unsigned long)pAd); RTMP_OS_TASKLET_INIT(pAd, &pObj->hcca_dma_done_task, rtusb_hcca_dma_done_tasklet, (unsigned long)pAd); RTMP_OS_TASKLET_INIT(pAd, &pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd); RTMP_OS_TASKLET_INIT(pAd, &pObj->null_frame_complete_task, rtusb_null_frame_done_tasklet, (unsigned long)pAd); RTMP_OS_TASKLET_INIT(pAd, &pObj->pspoll_frame_complete_task, rtusb_pspoll_frame_done_tasklet, (unsigned long)pAd); #ifdef CONFIG_MULTI_CHANNEL RTMP_OS_TASKLET_INIT(pAd, &pObj->hcca_null_frame_complete_task, rtusb_hcca_null_frame_done_tasklet, (unsigned long)pAd); #endif /* CONFIG_MULTI_CHANNEL */ return NDIS_STATUS_SUCCESS; } void RtmpNetTaskExit(IN RTMP_ADAPTER *pAd) { POS_COOKIE pObj; pObj = (POS_COOKIE) pAd->OS_Cookie; RTMP_OS_TASKLET_KILL(&pObj->rx_done_task); #ifdef RLT_MAC RTMP_OS_TASKLET_KILL(&pObj->cmd_rsp_event_task); #endif /* RLT_MAC */ RTMP_OS_TASKLET_KILL(&pObj->mgmt_dma_done_task); RTMP_OS_TASKLET_KILL(&pObj->ac0_dma_done_task); #ifdef RALINK_ATE RTMP_OS_TASKLET_KILL(&pObj->ate_ac0_dma_done_task); #endif RTMP_OS_TASKLET_KILL(&pObj->ac1_dma_done_task); RTMP_OS_TASKLET_KILL(&pObj->ac2_dma_done_task); RTMP_OS_TASKLET_KILL(&pObj->ac3_dma_done_task); RTMP_OS_TASKLET_KILL(&pObj->hcca_dma_done_task); RTMP_OS_TASKLET_KILL(&pObj->tbtt_task); RTMP_OS_TASKLET_KILL(&pObj->null_frame_complete_task); #ifdef CONFIG_MULTI_CHANNEL RTMP_OS_TASKLET_KILL(&pObj->hcca_null_frame_complete_task); #endif /* CONFIG_MULTI_CHANNEL */ RTMP_OS_TASKLET_KILL(&pObj->pspoll_frame_complete_task); } /* ======================================================================== Routine Description: MLME kernel thread. Arguments: *Context the pAd, driver control block pointer Return Value: 0 close the thread Note: ======================================================================== */ INT MlmeThread( 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) goto LabelExit; /* avoid compile warning */ RtmpOSTaskCustomize(pTask); while(!RTMP_OS_TASK_IS_KILLED(pTask)) { if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); break; } /* lock the device pointers , need to check if required*/ /*down(&(pAd->usbdev_semaphore)); */ if (!pAd->PM_FlgSuspend) MlmeHandler(pAd); } /* 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(). */ LabelExit: DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); RtmpOSTaskNotifyToExit(pTask); 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) { 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; }