コード例 #1
0
/**********************************************************
NDIS5.X handler of power management
***********************************************************/
NDIS_STATUS ParaNdis_OnSetPower(PARANDIS_ADAPTER *pContext, tOidDesc *pOid)
{
	NDIS_STATUS status;
	NDIS_DEVICE_POWER_STATE newState;
	DEBUG_ENTRY(0);
	status = ParaNdis_OidSetCopy(pOid, &newState, sizeof(newState));
	if (status == NDIS_STATUS_SUCCESS)
	{
		tPowerWorkItem *pwi = ParaNdis_AllocateMemory(pContext, sizeof(tPowerWorkItem));
		status = NDIS_STATUS_FAILURE;
		if (pwi)
		{
			pwi->pContext = pContext;
			pwi->state    = newState;
			NdisInitializeWorkItem(&pwi->wi, OnSetPowerWorkItem, pwi);
			if (NdisScheduleWorkItem(&pwi->wi) == NDIS_STATUS_SUCCESS)
			{
				status = NDIS_STATUS_PENDING;
			}
			else
				NdisFreeMemory(pwi, 0, 0);
		}
	}
	return status;
}
コード例 #2
0
/*************************************************************
Required NDIS procedure
Called when some procedure (like OID handler) returns PENDING and
does not complete or when CheckForHang return TRUE
*************************************************************/
static NDIS_STATUS ParaNdis5_Reset(
	OUT PBOOLEAN AddressingReset,
	IN NDIS_HANDLE MiniportAdapterContext)
{
	NDIS_STATUS status;
	tGeneralWorkItem *pwi;
	PARANDIS_ADAPTER *pContext = (PARANDIS_ADAPTER *)MiniportAdapterContext;
	DEBUG_ENTRY(0);
	ParaNdis_DebugHistory(pContext, hopSysReset, NULL, 1, 0, 0);
	status = NDIS_STATUS_FAILURE;
	pwi = ParaNdis_AllocateMemory(pContext, sizeof(tGeneralWorkItem));
	if (pwi)
	{
		pwi->pContext = pContext;
		NdisInitializeWorkItem(&pwi->wi, OnResetWorkItem, pwi);
		if (NdisScheduleWorkItem(&pwi->wi) == NDIS_STATUS_SUCCESS)
		{
			status = NDIS_STATUS_PENDING;
		}
		else
		{
			NdisFreeMemory(pwi, 0, 0);
		}
	}
	if (status != NDIS_STATUS_PENDING)
	{
		ParaNdis_DebugHistory(pContext, hopSysReset, NULL, 0, status, 0);
	}
	return status;
}
コード例 #3
0
VOID 
NICFreeNotify(
    IN PNOTICB pNotiCB)
/*++

Routine Description:

    pRCB      - pointer to RCB block
        
Arguments:

    This routine reinitializes the RCB block and puts it back
    into the RecvFreeList for reuse.
    

Return Value:

    VOID

--*/
{
    PMP_ADAPTER Adapter = pNotiCB->Adapter;
    
    DEBUGP(MP_TRACE, ("--> NICFreeNotify %p\n", pNotiCB));
    
    ASSERT(pNotiCB->Irp);    // shouldn't be NULL
    ASSERT(!pNotiCB->Ref); // should be 0
    ASSERT(pNotiCB->Adapter); // shouldn't be NULL

    IoReuseIrp(pNotiCB->Irp, STATUS_SUCCESS);    


	pNotiCB->ulSize=0;
    // 
    // Set the MDL field to NULL so that we don't end up double freeing the
    // MDL in our call to IoFreeIrp.
    // 
      
    pNotiCB->Irp->MdlAddress = NULL;
    
    //
    // Insert the RCB back in the Recv free list     
    //
    NdisAcquireSpinLock(&Adapter->InterruptNotifyLock);
    
    RemoveEntryList(&pNotiCB->List);
    
    InsertTailList(&Adapter->InterruptFreeList, &pNotiCB->List);

    NdisInterlockedDecrement(&Adapter->nBusyNotify);
    ASSERT(Adapter->nBusyNotify >= 0);
    
    NdisReleaseSpinLock(&Adapter->InterruptNotifyLock); 
    
    //
    // For performance, instead of scheduling a workitem at the end of
    // every read completion, we will do it only when the number of 
    // outstanding IRPs goes below NIC_SEND_LOW_WATERMARK.
    // We shouldn't queue a workitem if it's already scheduled and waiting in
    // the system workitem queue to be fired.
    //
    if((Adapter->nBusyNotify ==0)
            && MP_TEST_FLAG(Adapter, fMP_POST_INTERRUPT)) {

        MP_INC_REF(Adapter);                   
        NdisScheduleWorkItem(&Adapter->InterruptNotifyItem);   
    }
    DEBUGP(MP_TRACE, ("<-- NICFreeNotify %d\n", Adapter->nBusyNotify));
    
}
コード例 #4
0
VOID 
NICFreeRCB(
    IN PRCB pRCB)
/*++

Routine Description:

    pRCB      - pointer to RCB block
        
Arguments:

    This routine reinitializes the RCB block and puts it back
    into the RecvFreeList for reuse.
    

Return Value:

    VOID

--*/
{
    PMP_ADAPTER Adapter = pRCB->Adapter;
    ULONG ulSendLowW= NIC_SEND_LOW_WATERMARK;
    
    DEBUGP(MP_TRACE, ("--> NICFreeRCB %p\n", pRCB));
    
    ASSERT(pRCB->Irp);    // shouldn't be NULL
    ASSERT(!pRCB->Ref); // should be 0
    ASSERT(pRCB->Adapter); // shouldn't be NULL

    IoReuseIrp(pRCB->Irp, STATUS_SUCCESS);    

	pRCB->nextndeoffset=0;    
	pRCB->nextndpoffset=0;
	pRCB->bIsOver=FALSE;
	pRCB->ulSize=0;
    // 
    // Set the MDL field to NULL so that we don't end up double freeing the
    // MDL in our call to IoFreeIrp.
    // 
      
    pRCB->Irp->MdlAddress = NULL;
    
    //
    // Re adjust the length to the originl size
    //
    //NdisAdjustBufferLength(pRCB->BufferArray[0], pRCB->ulBufferSize);

    //
    // Insert the RCB back in the Recv free list     
    //
    NdisAcquireSpinLock(&Adapter->RecvLock);
    
    RemoveEntryList(&pRCB->List);
    
    InsertTailList(&Adapter->RecvFreeList, &pRCB->List);

    NdisInterlockedDecrement(&Adapter->nBusyRecv);
    ASSERT(Adapter->nBusyRecv >= 0);
    
    NdisReleaseSpinLock(&Adapter->RecvLock); 
    
    //
    // For performance, instead of scheduling a workitem at the end of
    // every read completion, we will do it only when the number of 
    // outstanding IRPs goes below NIC_SEND_LOW_WATERMARK.
    // We shouldn't queue a workitem if it's already scheduled and waiting in
    // the system workitem queue to be fired.
    //
    if((!ulSendLowW || Adapter->nBusyRecv <= NIC_SEND_LOW_WATERMARK)
            && MP_TEST_FLAG(Adapter, fMP_POST_READS) && 
            (InterlockedExchange(&Adapter->IsReadWorkItemQueued, TRUE) == FALSE)) {

        Adapter->nReadWorkItemScheduled++;
        MP_INC_REF(Adapter);                   
        NdisScheduleWorkItem(&Adapter->ReadWorkItem);   
    }
    DEBUGP(MP_TRACE, ("<-- NICFreeRCB %d\n", Adapter->nBusyRecv));
    
}
コード例 #5
0
ファイル: DtWorkItem.c プロジェクト: planetlabs/dta
//.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtWorkItemSchedule -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
//
DtStatus  DtWorkItemSchedule(DtWorkItem* pWorkItem, DtWorkItemArgs* pArgs)
{
    DtStatus  Result = DT_STATUS_OK;
    Int  OldState;
    Bool  DoRun = FALSE;
    Bool  DoQueue = FALSE;
    DtWorkItemStruct  WorkItemStruct;

    DT_ASSERT(pWorkItem->m_SchedulingEnabled);

    // Allocate workitem
    Result = DtWorkItemStructCreate(&WorkItemStruct, pWorkItem->m_pDevice);
    if (!DT_SUCCESS(Result))
        return Result;
    
    // Try to set running from idle state
    OldState = DtAtomicCompareExchange((Int*)&pWorkItem->m_State, 0, 
                                                                    WI_STATE_BIT_RUNNING);
    if (OldState == 0)
        // Successfully running
        DoRun = TRUE;
    else if (pWorkItem->m_QueueIfRunning)
    {
        // Try to set Queuing
        OldState = DtAtomicCompareExchange((Int*)&pWorkItem->m_State, 
                                               WI_STATE_BIT_RUNNING,
                                               WI_STATE_BIT_RUNNING|WI_STATE_BIT_QUEUING);
        if (OldState == WI_STATE_BIT_RUNNING)
            // Successfully set to queuing
            DoQueue = TRUE;
        // Not running anymore?
        // Try to set running again to be sure a full execution of the worker is pending
        // after the call the DtDpcSchedule... 
        else if ((OldState&WI_STATE_BIT_RUNNING) == 0)
        {
            // Retry to set running from idle state
            OldState = DtAtomicCompareExchange((Int*)&pWorkItem->m_State, 0, 
                                                                    WI_STATE_BIT_RUNNING);
            if (OldState == 0)
                // Successfully set to running
                DoRun = TRUE;
            else
                Result = DT_STATUS_IN_USE;
        } else
            Result = DT_STATUS_IN_USE;
    }

    if (!DT_SUCCESS(Result))
    {
        // Delete workitem
        DtWorkItemStructDelete(&WorkItemStruct);
        return Result;
    }

    // Queue WorkItem?
    if (DoQueue)
    {
        // Copy arguments
        pWorkItem->m_QueuedArgs = *pArgs;
        
        // Set to queued (running|queuing|queued)
        OldState = DtAtomicCompareExchange((Int*)&pWorkItem->m_State,
                           WI_STATE_BIT_RUNNING|WI_STATE_BIT_QUEUING,
                           WI_STATE_BIT_RUNNING|WI_STATE_BIT_QUEUING|WI_STATE_BIT_QUEUED);
        // Check if we failed because we were not running anymore
        if (OldState == WI_STATE_BIT_QUEUING)
        {
            // Choose running slot --> try to set from queuing to running instead of
            // queued
            OldState = DtAtomicCompareExchange((Int*)&pWorkItem->m_State, 
                                              WI_STATE_BIT_QUEUING, WI_STATE_BIT_RUNNING);
            if (OldState == WI_STATE_BIT_QUEUING)
                DoRun = TRUE;
            else {
                Result = DT_STATUS_IN_USE;
                // Can not happen?
                DT_ASSERT(FALSE);
            }
        }
    } 

    // Start initial WorkItem?
    if (DoRun)
    {
        pWorkItem->m_Args = *pArgs;
        DtWorkItemStructCopy(&pWorkItem->m_WorkStruct, &WorkItemStruct);

#ifdef WINBUILD
#ifdef USES_NDIS
        NdisInitializeWorkItem(&pWorkItem->m_WorkStruct.m_NdisWorkItem,
                                                             DtWorkItemWorker, pWorkItem);
        NdisScheduleWorkItem(&pWorkItem->m_WorkStruct.m_NdisWorkItem);
#else
        IoQueueWorkItem(pWorkItem->m_WorkStruct.m_pIoWorkItem, DtWorkItemWorker,
                                                             DelayedWorkQueue, pWorkItem);
#endif // USES_NDIS
#else
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
        // INIT_WORK has been redefined in kernel version 2.6.20 (no 3rd context parameter)
        INIT_WORK(&pWorkItem->m_WorkStruct.m_Work, DtWorkItemWorker);
#else
        INIT_WORK(&pWorkItem->m_WorkStruct.m_Work, DtWorkItemWorker, pWorkItem);
#endif
        schedule_work(&pWorkItem->m_WorkStruct.m_Work);
#endif
        // Running flag is already set...
    } else // We do not need the WorkItemStruct.
        DtWorkItemStructDelete(&WorkItemStruct);

    return Result;
}