Example #1
0
VOID
FxPkgIo::ResetStateForRestart(
    VOID
)
/*++

Routine Description:
    This is called on a device which has been restarted from the removed
    state.  It will reset purged queues so that they can accept new requests
    when ResumeProcessingForPower is called afterwards.

Arguments:
    None

Return Value:
    None

  --*/
{
    KIRQL irql;
    FxIoQueue* queue;
    SINGLE_LIST_ENTRY queueList, *ple;

    DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIO,
                        "Restart queues from purged state for WDFDEVICE 0x%p due to "
                        "device restart", m_Device->GetHandle());

    queueList.Next = NULL;

    Lock(&irql);

    GetIoQueueListLocked(&queueList, FxIoQueueIteratorListPowerOn);

    Unlock(irql);

    for (ple = PopEntryList(&queueList);
            ple != NULL;
            ple = PopEntryList(&queueList)) {

        queue = FxIoQueue::_FromPowerSListEntry(ple);

        queue->ResetStateForRestart();

        ple->Next = NULL;

        queue->RELEASE(IO_ITERATOR_POWER_TAG);
    }

    Lock(&irql);

    m_PowerStateOn = TRUE;

    m_QueuesAreShuttingDown = FALSE;

    Unlock(irql);

    return;

}
Example #2
0
_Must_inspect_result_
NTSTATUS
FxPkgIo::FlushAllQueuesByFileObject(
    __in MdFileObject FileObject
)

/*++

    Routine Description:

        Enumerate all the queues and cancel the requests that have
        the same fileobject as the Cleanup IRP.

        We are making an assumption that cleanup irps are sent only
        at passive-level.

    Return Value:

    NTSTATUS

--*/
{
    FxIoQueue* queue = NULL;
    PFX_DRIVER_GLOBALS pFxDriverGlobals = GetDriverGlobals();
    FxIoQueueNode flushBookmark(FxIoQueueNodeTypeBookmark);
    KIRQL irql;

    if(Mx::MxGetCurrentIrql() != PASSIVE_LEVEL) {

        DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
                            "Currently framework allow flushing of queues "
                            "by fileobject on cleanup only at PASSIVE_LEVEL");

        FxVerifierDbgBreakPoint(pFxDriverGlobals);
        return STATUS_SUCCESS;
    }

    //
    // Iterate through the queue list and flush each one.
    //
    Lock(&irql);
    queue = GetFirstIoQueueLocked(&flushBookmark, IO_ITERATOR_FLUSH_TAG);
    Unlock(irql);

    while(queue != NULL) {

        queue->FlushByFileObject(FileObject);

        queue->RELEASE(IO_ITERATOR_FLUSH_TAG);

        Lock(&irql);
        queue = GetNextIoQueueLocked(&flushBookmark, IO_ITERATOR_FLUSH_TAG);
        Unlock(irql);
    }

    return STATUS_SUCCESS;
}
Example #3
0
_Must_inspect_result_
NTSTATUS
FxPkgIo::ResumeProcessingForPower()

/*++

    Routine Description:

    Resumes all PowerManaged queues for automatic I/O processing due to
        a power event that allows I/O to resume.

    Non-PowerManaged queues are left alone.

Arguments:

Return Value:

    NTSTATUS

--*/

{
    KIRQL irql;
    FxIoQueue* queue;
    SINGLE_LIST_ENTRY queueList, *ple;

    DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIO,
                        "Power resume all queues of WDFDEVICE 0x%p",
                        m_Device->GetHandle());

    queueList.Next = NULL;

    Lock(&irql);

    GetIoQueueListLocked(&queueList, FxIoQueueIteratorListPowerOn);
    //
    // Change the state so that new queues created while we
    // are resuming the existing queues can be in a powered-on state.
    //
    m_PowerStateOn = TRUE;

    //
    // Change the accepting state so that new queues created while we
    // are resuming the existing queues can be accept request.
    //
    m_QueuesAreShuttingDown = FALSE;

    Unlock(irql);

    //
    // We will power-up the queues in two steps. First we will resume
    // the power of all the queues and then we will start dispatching I/Os.
    // This is to avoid a queue being powered up at the begining of the list
    // trying to forward a request to another queue lower in the list that's
    // not powered up yet.
    //
    for(ple = queueList.Next; ple != NULL; ple = ple->Next) {

        queue = FxIoQueue::_FromPowerSListEntry(ple);

        queue->ResumeProcessingForPower();
    }

    for (ple = PopEntryList(&queueList);
            ple != NULL;
            ple = PopEntryList(&queueList)) {

        queue = FxIoQueue::_FromPowerSListEntry(ple);

        queue->StartPowerTransitionOn();

        ple->Next = NULL;

        queue->RELEASE(IO_ITERATOR_POWER_TAG);
    }

    return STATUS_SUCCESS;
}
Example #4
0
_Must_inspect_result_
NTSTATUS
FxPkgIo::StopProcessingForPower(
    __in FxIoStopProcessingForPowerAction Action
)

/*++

    Routine Description:

    Stops all PowerManaged queues automatic I/O processing due to
        a power event that requires I/O to stop.

    This is called on a PASSIVE_LEVEL thread that can block until
    I/O has been stopped, or completed/cancelled.

Arguments:

    Action -

    FxIoStopProcessingForPowerHold:
    the function returns when the driver has acknowledged that it has
    stopped all I/O processing, but may have outstanding "in-flight" requests
    that have not been completed.

    FxIoStopProcessingForPowerPurgeManaged:
    the function returns when all requests from a power managed queue have
    been completed and/or cancelled., and there are no more in-flight requests.

    FxIoStopProcessingForPowerPurgeNonManaged:
    the function returns when all requests from a non-power managed queue have
    been completed and/or cancelled., and there are no more in-flight requests.
    Only called during device-remove.

Return Value:

    NTSTATUS

--*/

{
    KIRQL irql;
    FxIoQueue* queue;
    SINGLE_LIST_ENTRY queueList, *ple;

    DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGIO,
                        "Perform %!FxIoStopProcessingForPowerAction! for all queues of "
                        "WDFDEVICE 0x%p", Action, m_Device->GetHandle());

    queueList.Next = NULL;

    Lock(&irql);
    //
    // Device is moving into low power state. So any new queues
    // created after this point would start off as powered off.
    //
    m_PowerStateOn = FALSE;

    //
    // If queues are shutting down, any new queue created after
    // this point would not accept any requests.
    //
    switch(Action) {
    case FxIoStopProcessingForPowerPurgeManaged:
    case FxIoStopProcessingForPowerPurgeNonManaged:
        m_QueuesAreShuttingDown = TRUE;
        break;
    }

    GetIoQueueListLocked(&queueList, FxIoQueueIteratorListPowerOff);

    Unlock(irql);

    //
    // If the power action is hold then first change the state of all the queues
    // to PowerStartTransition. This will prevent the queues from dispatching
    // new requests before we start asking each queue to stop processing
    // inflight requests.
    //
    if(Action == FxIoStopProcessingForPowerHold) {

        //
        // Walk the list without popping entries because we need to scan
        // the list again.
        //
        for(ple = queueList.Next; ple != NULL; ple = ple->Next) {

            queue = FxIoQueue::_FromPowerSListEntry(ple);

            queue->StartPowerTransitionOff();
        }
    }

    //
    // Ask the queues to stop processing inflight requests.
    //
    for (ple = PopEntryList(&queueList); ple != NULL;
            ple = PopEntryList(&queueList)) {

        queue = FxIoQueue::_FromPowerSListEntry(ple);

        queue->StopProcessingForPower(Action);

        ple->Next = NULL;

        queue->RELEASE(IO_ITERATOR_POWER_TAG);
    }

    return STATUS_SUCCESS;
}