[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] Asynchronous power handling.
On 12/03/2024 07:23, Owen Smith wrote: From: Martin Harvey <Martin.Harvey@xxxxxxxxxx> Use completion routines and IO_WORKITEMs to handle power state transitions, allowing execution to run at PASSIVE_LEVEL without blocking the current thread, and avoid blocking all power IRPs while another is executing (power IRPs should be synchronized by the power manager, but this doesnt appear to be the case in all situations). Signed-off-by: Martin Harvey <martin.harvey@xxxxxxxxxx> Refactored Unfortunately, not enough... Signed-off-by: Owen Smith <owen.smith@xxxxxxxxx> --- src/xenvif/fdo.c | 803 +++++++++++++++++++++++++++++------------------ src/xenvif/pdo.c | 263 +++++++--------- 2 files changed, 608 insertions(+), 458 deletions(-) diff --git a/src/xenvif/fdo.c b/src/xenvif/fdo.c index 451d582..7fa2d04 100644 --- a/src/xenvif/fdo.c +++ b/src/xenvif/fdo.c @@ -81,9 +81,9 @@ struct _XENVIF_FDO { ULONG Usage[DeviceUsageTypeDumpFile + 1]; BOOLEAN NotDisableable;- PXENVIF_THREAD SystemPowerThread;+ PIO_WORKITEM SystemPowerWorkItem; PIRP SystemPowerIrp; - PXENVIF_THREAD DevicePowerThread; + PIO_WORKITEM DevicePowerWorkItem; PIRP DevicePowerIrp;CHAR VendorName[MAXNAMELEN];@@ -2168,6 +2168,68 @@ FdoDispatchPnp( return status; }+__drv_functionClass(IO_WORKITEM_ROUTINE)+__drv_sameIRQL +static VOID +FdoDevicePowerUpWorker( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context + ) +{ + PXENVIF_FDO Fdo = (PXENVIF_FDO) Context; + PIRP Irp; + + UNREFERENCED_PARAMETER(DeviceObject); + + Irp = InterlockedExchangePointer(&Fdo->DevicePowerIrp, NULL); + ASSERT(Irp != NULL); + + (VOID) FdoD3ToD0(Fdo); + + /* Cannot change Irp->IoStatus */ + /* Continue completion chain */ + IoCompleteRequest(Irp, IO_NO_INCREMENT); +} + +__drv_functionClass(IO_COMPLETION_ROUTINE) +__drv_sameIRQL +static NTSTATUS +FdoSetDevicePowerUpComplete( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) +{ + PXENVIF_FDO Fdo = (PXENVIF_FDO) Context; + PIO_STACK_LOCATION StackLocation; + DEVICE_POWER_STATE DeviceState; + PVOID Exchange; + + UNREFERENCED_PARAMETER(DeviceObject); + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + DeviceState = StackLocation->Parameters.Power.State.DeviceState; + + /* Already marked pending by us */ + Info("%s -> %s\n", Lack of device name in the Info() message make it less useful + PowerDeviceStateName(__FdoGetDevicePowerState(Fdo)), + PowerDeviceStateName(DeviceState)); + + /* Don't worry about IRP IoStatus */ + ASSERT3U(DeviceState, ==, PowerDeviceD0); + + Exchange = InterlockedExchangePointer(&Fdo->DevicePowerIrp, Irp); + ASSERT(Exchange == NULL); + + IoQueueWorkItem(Fdo->DevicePowerWorkItem, + FdoDevicePowerUpWorker, + DelayedWorkQueue, + Fdo); + + /* Stop completion chain in all circumstances. */ + return STATUS_MORE_PROCESSING_REQUIRED; +} + static FORCEINLINE NTSTATUS __FdoSetDevicePowerUp( IN PXENVIF_FDO Fdo, @@ -2176,7 +2238,6 @@ __FdoSetDevicePowerUp( { PIO_STACK_LOCATION StackLocation; DEVICE_POWER_STATE DeviceState; - NTSTATUS status;Trace("====>\n"); @@ -2185,25 +2246,41 @@ __FdoSetDevicePowerUp( ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo)); - status = FdoForwardIrpSynchronously(Fdo, Irp);- if (!NT_SUCCESS(status)) - goto done; + IoMarkIrpPending(Irp); + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, + FdoSetDevicePowerUpComplete, + Fdo, + TRUE, + TRUE, + TRUE);- Info("%s: %s -> %s\n",- __FdoGetName(Fdo), - PowerDeviceStateName(__FdoGetDevicePowerState(Fdo)), - PowerDeviceStateName(DeviceState)); + (VOID) IoCallDriver(Fdo->LowerDeviceObject, Irp);- ASSERT3U(DeviceState, ==, PowerDeviceD0);- status = FdoD3ToD0(Fdo); - ASSERT(NT_SUCCESS(status)); + return STATUS_PENDING; +}-done:- Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); +__drv_functionClass(IO_WORKITEM_ROUTINE) +__drv_sameIRQL +static VOID +FdoDevicePowerDownWorker( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context + ) +{ + PXENVIF_FDO Fdo = (PXENVIF_FDO) Context; + PIRP Irp;- Trace("<==== (%08x)\n", status);- return status; + UNREFERENCED_PARAMETER(DeviceObject); + + Irp = InterlockedExchangePointer(&Fdo->DevicePowerIrp, NULL); + ASSERT(Irp != NULL); + + FdoD0ToD3(Fdo); + + /* We are on dispatch path here. */ + IoCopyCurrentIrpStackLocationToNext(Irp); + IoCallDriver(Fdo->LowerDeviceObject, Irp); }static FORCEINLINE NTSTATUS@@ -2221,18 +2298,32 @@ __FdoSetDevicePowerDown(ASSERT3U(DeviceState, >, __FdoGetDevicePowerState(Fdo)); - Info("%s: %s -> %s\n",- __FdoGetName(Fdo), + Info("%s -> %s\n", Device name being gratuitously removed here. PowerDeviceStateName(__FdoGetDevicePowerState(Fdo)), PowerDeviceStateName(DeviceState));ASSERT3U(DeviceState, ==, PowerDeviceD3); - if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0)- FdoD0ToD3(Fdo); + /* All handled in dispatch, no extra error handling */ + if (__FdoGetDevicePowerState(Fdo) != PowerDeviceD0) { + /* Not marked pending, can skip */ Inconsistent comment format. + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + } else { + PVOID Exchange;- IoSkipCurrentIrpStackLocation(Irp);- status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + IoMarkIrpPending(Irp); + + Exchange = InterlockedExchangePointer(&Fdo->DevicePowerIrp, Irp); + ASSERT(Exchange == NULL); + + IoQueueWorkItem(Fdo->DevicePowerWorkItem, + FdoDevicePowerDownWorker, + DelayedWorkQueue, + Fdo); + + status = STATUS_PENDING; + }return status;} @@ -2253,11 +2344,9 @@ __FdoSetDevicePower( PowerAction = StackLocation->Parameters.Power.ShutdownType;Trace("====> (%s:%s)\n",- PowerDeviceStateName(DeviceState), + PowerDeviceStateName(DeviceState), PowerActionName(PowerAction));- ASSERT3U(PowerAction, <, PowerActionShutdown);- if (DeviceState == __FdoGetDevicePowerState(Fdo)) { IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(Fdo->LowerDeviceObject, Irp); @@ -2271,7 +2360,7 @@ __FdoSetDevicePower(done:Trace("<==== (%s:%s)(%08x)\n", - PowerDeviceStateName(DeviceState), + PowerDeviceStateName(DeviceState), PowerActionName(PowerAction), status); return status; @@ -2279,8 +2368,8 @@ done:__drv_functionClass(REQUEST_POWER_COMPLETE)__drv_sameIRQL -VOID -__FdoRequestSetDevicePower( +static VOID +FdoRequestSetDevicePowerUpComplete( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, @@ -2288,47 +2377,130 @@ __FdoRequestSetDevicePower( IN PIO_STATUS_BLOCK IoStatus ) { - PKEVENT Event = Context; + PIRP Irp = (PIRP) Context;UNREFERENCED_PARAMETER(DeviceObject);UNREFERENCED_PARAMETER(MinorFunction); UNREFERENCED_PARAMETER(PowerState); + UNREFERENCED_PARAMETER(IoStatus);- ASSERT(NT_SUCCESS(IoStatus->Status));- - KeSetEvent(Event, IO_NO_INCREMENT, FALSE); + /* Although can change Irp->IoStatus for pended IRP, drivers should not fail this. */ Again, wrong comment style. + IoCompleteRequest(Irp, IO_NO_INCREMENT); }+__drv_functionClass(IO_WORKITEM_ROUTINE)+__drv_sameIRQL static VOID -FdoRequestSetDevicePower( - IN PXENVIF_FDO Fdo, - IN DEVICE_POWER_STATE DeviceState +FdoSystemPowerUpWorker( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context ) { - POWER_STATE PowerState; - KEVENT Event; - NTSTATUS status; + PXENVIF_FDO Fdo = (PXENVIF_FDO) Context; + PIRP Irp; + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + POWER_STATE PowerState; + NTSTATUS status;- Trace("%s\n", PowerDeviceStateName(DeviceState));+ UNREFERENCED_PARAMETER(DeviceObject);- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);+ Irp = InterlockedExchangePointer(&Fdo->SystemPowerIrp, NULL); + ASSERT(Irp != NULL);- PowerState.DeviceState = DeviceState;- KeInitializeEvent(&Event, NotificationEvent, FALSE); + StackLocation = IoGetCurrentIrpStackLocation(Irp);; + SystemState = StackLocation->Parameters.Power.State.SystemState; + + Info("%s -> %s\n", Lack of device name in Info() again. + PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), + PowerSystemStateName(SystemState)); + + __FdoSetSystemPowerState(Fdo, PowerSystemHibernate); + FdoS4ToS3(Fdo); + __FdoSetSystemPowerState(Fdo, SystemState); + + PowerState.DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];status = PoRequestPowerIrp(Fdo->LowerDeviceObject,IRP_MN_SET_POWER, PowerState, - __FdoRequestSetDevicePower, - &Event, + FdoRequestSetDevicePowerUpComplete, + Irp, NULL); - ASSERT(NT_SUCCESS(status));- (VOID) KeWaitForSingleObject(&Event,- Executive, - KernelMode, - FALSE, - NULL); + /* Whatever happens, we have stopped completion processing for SIrp, + to restart SIrp processing, call IoCompleteRequest. */ And again. In fact they are everywhere; please remove them or fix them. TBH it looks like many of them are OTT and can be removed. + if (!NT_SUCCESS(status)) + goto fail1; + + return; /* FdoRequestSetDevicePowerUpComplete will complete the request.*/ + +fail1: + Error("fail1 - but continue IRP processing. (%08x)\n", status); + /* Although can change Irp->IoStatus for pended IRP, drivers should not fail this. */ + IoCompleteRequest(Irp, IO_NO_INCREMENT); +} + +__drv_functionClass(IO_COMPLETION_ROUTINE) +__drv_sameIRQL +static NTSTATUS +FdoSetSystemPowerUpComplete( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) +{ + PXENVIF_FDO Fdo = (PXENVIF_FDO) Context; + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + POWER_STATE PowerState; + NTSTATUS status; + + UNREFERENCED_PARAMETER(DeviceObject); + + /* IRP marked as pending on dispatch path, no need to check pending returned */ + + /* Don't worry about IRP IoStatus */ + StackLocation = IoGetCurrentIrpStackLocation(Irp); + SystemState = StackLocation->Parameters.Power.State.SystemState; + + if (SystemState < PowerSystemHibernate && + __FdoGetSystemPowerState(Fdo) >= PowerSystemHibernate) { + PVOID Exchange; + + Exchange = InterlockedExchangePointer(&Fdo->SystemPowerIrp, Irp); + ASSERT(Exchange == NULL); + + IoQueueWorkItem(Fdo->SystemPowerWorkItem, + FdoSystemPowerUpWorker, + DelayedWorkQueue, + Fdo); + } else { + Info("%s -> %s\n", Lack of device name in Info() again. + PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), + PowerSystemStateName(SystemState)); + + __FdoSetSystemPowerState(Fdo, SystemState); + + PowerState.DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState]; + + status = PoRequestPowerIrp(Fdo->LowerDeviceObject, + IRP_MN_SET_POWER, + PowerState, + FdoRequestSetDevicePowerUpComplete, + Irp, + NULL); + if (!NT_SUCCESS(status)) + goto fail1; + } + + /* Will later complete the IRP (which is marked pending, in worker or 2nd level comp routine.)*/ + return STATUS_MORE_PROCESSING_REQUIRED; + +fail1: + Error("fail1 - but continue IRP processing. (%08x)\n", status); + /* marked pending on dispatch path, don't change Irp->IoStatus, keep going.*/ + return STATUS_CONTINUE_COMPLETION; }static FORCEINLINE NTSTATUS@@ -2337,42 +2509,103 @@ __FdoSetSystemPowerUp( IN PIRP Irp ) { - PIO_STACK_LOCATION StackLocation; SYSTEM_POWER_STATE SystemState; - DEVICE_POWER_STATE DeviceState; - NTSTATUS status;StackLocation = IoGetCurrentIrpStackLocation(Irp);SystemState = StackLocation->Parameters.Power.State.SystemState;ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo)); - status = FdoForwardIrpSynchronously(Fdo, Irp);- if (!NT_SUCCESS(status)) - goto done; + /* IRP already pended, and we want to complete it *after* completion routine. */ + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, + FdoSetSystemPowerUpComplete, + Fdo, + TRUE, + TRUE, + TRUE);- Info("%s: %s -> %s\n",- __FdoGetName(Fdo), - PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), - PowerSystemStateName(SystemState)); + IoCallDriver(Fdo->LowerDeviceObject, Irp);- if (SystemState < PowerSystemHibernate &&- __FdoGetSystemPowerState(Fdo) >= PowerSystemHibernate) { - __FdoSetSystemPowerState(Fdo, PowerSystemHibernate); - FdoS4ToS3(Fdo); - } + return STATUS_PENDING; +} + +__drv_functionClass(IO_WORKITEM_ROUTINE) +__drv_sameIRQL +static VOID +FdoSystemPowerDownWorker( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context + ) +{ + PXENVIF_FDO Fdo = (PXENVIF_FDO) Context; + PIRP Irp; + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + + UNREFERENCED_PARAMETER(DeviceObject); + + Irp = InterlockedExchangePointer(&Fdo->SystemPowerIrp, NULL); + ASSERT(Irp != NULL);+ StackLocation = IoGetCurrentIrpStackLocation(Irp);+ SystemState = StackLocation->Parameters.Power.State.SystemState; + + __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3); + FdoS3ToS4(Fdo); __FdoSetSystemPowerState(Fdo, SystemState);- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];- FdoRequestSetDevicePower(Fdo, DeviceState); + IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */ + IoCallDriver(Fdo->LowerDeviceObject, Irp); +}-done:- Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); +__drv_functionClass(REQUEST_POWER_COMPLETE) +__drv_sameIRQL +static VOID +FdoRequestSetDevicePowerDownComplete( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatus + ) +{ + PIRP Irp = (PIRP) Context; + PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp); + PDEVICE_OBJECT UpperDeviceObject = StackLocation->DeviceObject; + PXENVIF_DX Dx = (PXENVIF_DX)UpperDeviceObject->DeviceExtension; + PXENVIF_FDO Fdo = Dx->Fdo; + SYSTEM_POWER_STATE SystemState = StackLocation->Parameters.Power.State.SystemState;- return status;+ UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(MinorFunction); + UNREFERENCED_PARAMETER(PowerState); + + if (!NT_SUCCESS(IoStatus->Status)) + Error("fail1 - but continue IRP processing. (%08x)\n", IoStatus->Status); + + Info("%s -> %s\n", + PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), + PowerSystemStateName(SystemState)); + + if (SystemState >= PowerSystemHibernate && + __FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) { + PVOID Exchange; + + Exchange = InterlockedExchangePointer(&Fdo->SystemPowerIrp, Irp); + ASSERT(Exchange == NULL); + + IoQueueWorkItem(Fdo->DevicePowerWorkItem, + FdoSystemPowerDownWorker, + DelayedWorkQueue, + Fdo); + } else { + __FdoSetSystemPowerState(Fdo, SystemState); + + IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */ + IoCallDriver(Fdo->LowerDeviceObject, Irp); + } }static FORCEINLINE NTSTATUS@@ -2383,33 +2616,44 @@ __FdoSetSystemPowerDown( { PIO_STACK_LOCATION StackLocation; SYSTEM_POWER_STATE SystemState; - DEVICE_POWER_STATE DeviceState; + POWER_STATE PowerState; NTSTATUS status;StackLocation = IoGetCurrentIrpStackLocation(Irp);+ BUG_ON(StackLocation->DeviceObject != Fdo->Dx->DeviceObject); SystemState = StackLocation->Parameters.Power.State.SystemState;ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo)); - DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];- - FdoRequestSetDevicePower(Fdo, DeviceState); + PowerState.DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];- Info("%s: %s -> %s\n",- __FdoGetName(Fdo), - PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), - PowerSystemStateName(SystemState)); - - if (SystemState >= PowerSystemHibernate && - __FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) { - __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3); - FdoS3ToS4(Fdo); + if (SystemState >= PowerSystemShutdown) { + /* No DIrp generation, no FDO Powerdown. + Legacy shutdown just yanks system power. + Best device state for S5 is advertised as D3, + which is not *really* the case, but we can't increase it. */ + IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */ + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + } else { + status = PoRequestPowerIrp(Fdo->LowerDeviceObject, + IRP_MN_SET_POWER, + PowerState, + FdoRequestSetDevicePowerDownComplete, + Irp, + NULL); + if (!NT_SUCCESS(status)) + goto fail1; } + /* IRP already marked pending - nothing more to do if awaiting callback. */- __FdoSetSystemPowerState(Fdo, SystemState);+ return status;- IoSkipCurrentIrpStackLocation(Irp);- status = IoCallDriver(Fdo->LowerDeviceObject, Irp); +fail1: + /* In theory could change IRP status, but are not supposed to fail this IRP. */ + Error("fail1 - but continue IRP processing. (%08x)\n", status); + + IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */ + IoCallDriver(Fdo->LowerDeviceObject, Irp);return status;} @@ -2429,29 +2673,31 @@ __FdoSetSystemPower( SystemState = StackLocation->Parameters.Power.State.SystemState; PowerAction = StackLocation->Parameters.Power.ShutdownType;+ /* IRP_MN_SET_POWER Setting system power, IRP's *must* be pended. */+ IoMarkIrpPending(Irp); + Trace("====> (%s:%s)\n", - PowerSystemStateName(SystemState), + PowerSystemStateName(SystemState), PowerActionName(PowerAction));- ASSERT3U(PowerAction, <, PowerActionShutdown);- if (SystemState == __FdoGetSystemPowerState(Fdo)) { - IoSkipCurrentIrpStackLocation(Irp); + IoCopyCurrentIrpStackLocationToNext(Irp); /* Pended, copy not skip */ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);goto done;}- status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?+ status = SystemState < __FdoGetSystemPowerState(Fdo) ? __FdoSetSystemPowerUp(Fdo, Irp) : __FdoSetSystemPowerDown(Fdo, Irp);done:Trace("<==== (%s:%s)(%08x)\n", - PowerSystemStateName(SystemState), + PowerSystemStateName(SystemState), PowerActionName(PowerAction), status); - return status; + + return STATUS_PENDING; }static FORCEINLINE NTSTATUS@@ -2469,10 +2715,9 @@ __FdoQueryDevicePowerUp(ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo)); - status = FdoForwardIrpSynchronously(Fdo, Irp);- - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + /* N.B. Shutdown / hibernation failures caused by our device state could be vetoed here. */ + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp);return status;} @@ -2492,6 +2737,7 @@ __FdoQueryDevicePowerDown(ASSERT3U(DeviceState, >, __FdoGetDevicePowerState(Fdo)); + /* N.B. Shutdown / hibernation failures caused by our device state could be vetoed here. */IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(Fdo->LowerDeviceObject, Irp);@@ -2514,11 +2760,9 @@ __FdoQueryDevicePower(PowerAction = StackLocation->Parameters.Power.ShutdownType;Trace("====> (%s:%s)\n",- PowerDeviceStateName(DeviceState), + PowerDeviceStateName(DeviceState), PowerActionName(PowerAction));- ASSERT3U(PowerAction, <, PowerActionShutdown);- if (DeviceState == __FdoGetDevicePowerState(Fdo)) { IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(Fdo->LowerDeviceObject, Irp); @@ -2532,7 +2776,7 @@ __FdoQueryDevicePower(done:Trace("<==== (%s:%s)(%08x)\n", - PowerDeviceStateName(DeviceState), + PowerDeviceStateName(DeviceState), PowerActionName(PowerAction), status); return status; @@ -2540,8 +2784,8 @@ done:__drv_functionClass(REQUEST_POWER_COMPLETE)__drv_sameIRQL -VOID -__FdoRequestQueryDevicePower( +static VOID +FdoRequestQueryDevicePowerUpComplete( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, @@ -2549,47 +2793,58 @@ __FdoRequestQueryDevicePower( IN PIO_STATUS_BLOCK IoStatus ) { - PKEVENT Event = Context; + PIRP Irp = (PIRP) Context;UNREFERENCED_PARAMETER(DeviceObject);UNREFERENCED_PARAMETER(MinorFunction); UNREFERENCED_PARAMETER(PowerState);- ASSERT(NT_SUCCESS(IoStatus->Status));+ if (!NT_SUCCESS(IoStatus->Status)) + Irp->IoStatus.Status = IoStatus->Status;- KeSetEvent(Event, IO_NO_INCREMENT, FALSE);+ IoCompleteRequest(Irp, IO_NO_INCREMENT); }-static VOID-FdoRequestQueryDevicePower( - IN PXENVIF_FDO Fdo, - IN DEVICE_POWER_STATE DeviceState +__drv_functionClass(IO_COMPLETION_ROUTINE) +__drv_sameIRQL +static NTSTATUS +FdoQuerySystemPowerUpComplete( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context ) { - POWER_STATE PowerState; - KEVENT Event; - NTSTATUS status; - - Trace("%s\n", PowerDeviceStateName(DeviceState)); + PXENVIF_FDO Fdo = (PXENVIF_FDO) Context; + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + POWER_STATE PowerState; + NTSTATUS status;- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);+ UNREFERENCED_PARAMETER(DeviceObject);- PowerState.DeviceState = DeviceState;- KeInitializeEvent(&Event, NotificationEvent, FALSE); + /* IRP marked as pending on dispatch path. */ + StackLocation = IoGetCurrentIrpStackLocation(Irp); + SystemState = StackLocation->Parameters.Power.State.SystemState; + PowerState.DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];status = PoRequestPowerIrp(Fdo->LowerDeviceObject,IRP_MN_QUERY_POWER, PowerState, - __FdoRequestQueryDevicePower, - &Event, + FdoRequestQueryDevicePowerUpComplete, + Irp, NULL); - ASSERT(NT_SUCCESS(status)); + if (!NT_SUCCESS(status)) + goto fail1;- (VOID) KeWaitForSingleObject(&Event,- Executive, - KernelMode, - FALSE, - NULL); + /* Will later complete the IRP (which is marked pending, in 2nd level comp routine.)*/ + return STATUS_MORE_PROCESSING_REQUIRED; + +fail1: + /* Irp marked as pending on dispatch path, so can change final IoStatus, pass to completion routine above. */ + Error("fail1 (%08x)\n", status); + Irp->IoStatus.Status = status; + + return STATUS_CONTINUE_COMPLETION; }static FORCEINLINE NTSTATUS@@ -2598,30 +2853,61 @@ __FdoQuerySystemPowerUp( IN PIRP Irp ) { - PIO_STACK_LOCATION StackLocation; SYSTEM_POWER_STATE SystemState; - DEVICE_POWER_STATE DeviceState; - NTSTATUS status;StackLocation = IoGetCurrentIrpStackLocation(Irp);SystemState = StackLocation->Parameters.Power.State.SystemState;ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo)); - status = FdoForwardIrpSynchronously(Fdo, Irp);- if (!NT_SUCCESS(status)) - goto done; + IoMarkIrpPending(Irp); /* Must mark IRP pending because we want to complete it *after* completion routine. */ + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, + FdoQuerySystemPowerUpComplete, + Fdo, + TRUE, + TRUE, + TRUE); + (VOID) IoCallDriver(Fdo->LowerDeviceObject, Irp);- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];+ return STATUS_PENDING; +}- FdoRequestQueryDevicePower(Fdo, DeviceState);+__drv_functionClass(REQUEST_POWER_COMPLETE) +__drv_sameIRQL +static VOID +FdoRequestQueryDevicePowerDownComplete( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatus + ) +{ + PIRP Irp = (PIRP) Context; + PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp); + PDEVICE_OBJECT UpperDeviceObject = StackLocation->DeviceObject; + PXENVIF_DX Dx = (PXENVIF_DX)UpperDeviceObject->DeviceExtension; + PXENVIF_FDO Fdo = Dx->Fdo;-done:- Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(MinorFunction); + UNREFERENCED_PARAMETER(PowerState);- return status;+ if (!NT_SUCCESS(IoStatus->Status)) + goto fail1; + + IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended. */ + IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return; + +fail1: + Error("fail1 (%08x)\n", IoStatus->Status); + + Irp->IoStatus.Status = IoStatus->Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); }static FORCEINLINE NTSTATUS@@ -2632,7 +2918,7 @@ __FdoQuerySystemPowerDown( { PIO_STACK_LOCATION StackLocation; SYSTEM_POWER_STATE SystemState; - DEVICE_POWER_STATE DeviceState; + POWER_STATE PowerState; NTSTATUS status;StackLocation = IoGetCurrentIrpStackLocation(Irp);@@ -2640,12 +2926,26 @@ __FdoQuerySystemPowerDown(ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo)); - DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];+ PowerState.DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];- FdoRequestQueryDevicePower(Fdo, DeviceState);+ status = PoRequestPowerIrp(Fdo->LowerDeviceObject, + IRP_MN_QUERY_POWER, + PowerState, + FdoRequestQueryDevicePowerDownComplete, + Irp, + NULL); + if (!NT_SUCCESS(status)) + goto fail1;- IoSkipCurrentIrpStackLocation(Irp);- status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + IoMarkIrpPending(Irp); + + return STATUS_PENDING; + +fail1: + Error("fail1 (%08x)\n", status); + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT);return status;} @@ -2666,11 +2966,9 @@ __FdoQuerySystemPower( PowerAction = StackLocation->Parameters.Power.ShutdownType;Trace("====> (%s:%s)\n",- PowerSystemStateName(SystemState), + PowerSystemStateName(SystemState), PowerActionName(PowerAction));- ASSERT3U(PowerAction, <, PowerActionShutdown);- if (SystemState == __FdoGetSystemPowerState(Fdo)) { IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(Fdo->LowerDeviceObject, Irp); @@ -2684,183 +2982,91 @@ __FdoQuerySystemPower(done:Trace("<==== (%s:%s)(%08x)\n", - PowerSystemStateName(SystemState), + PowerSystemStateName(SystemState), PowerActionName(PowerAction), status);return status;}-static NTSTATUS-FdoDevicePower( - IN PXENVIF_THREAD Self, - IN PVOID Context +static FORCEINLINE NTSTATUS +__FdoDevicePower( + IN PXENVIF_FDO Fdo, + IN PIRP Irp ) { - PXENVIF_FDO Fdo = Context; - PKEVENT Event; - - Event = ThreadGetEvent(Self); - - for (;;) { - PIRP Irp; - PIO_STACK_LOCATION StackLocation; - UCHAR MinorFunction; - - if (Fdo->DevicePowerIrp == NULL) { - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - } - - if (ThreadIsAlerted(Self)) - break; - - Irp = Fdo->DevicePowerIrp; - - if (Irp == NULL) - continue; - - Fdo->DevicePowerIrp = NULL; - KeMemoryBarrier(); + PIO_STACK_LOCATION StackLocation; + NTSTATUS status;- StackLocation = IoGetCurrentIrpStackLocation(Irp);- MinorFunction = StackLocation->MinorFunction; + StackLocation = IoGetCurrentIrpStackLocation(Irp);- switch (StackLocation->MinorFunction) {- case IRP_MN_SET_POWER: - (VOID) __FdoSetDevicePower(Fdo, Irp); - break; + switch (StackLocation->MinorFunction) { + case IRP_MN_SET_POWER: + status = __FdoSetDevicePower(Fdo, Irp); + break;- case IRP_MN_QUERY_POWER:- (VOID) __FdoQueryDevicePower(Fdo, Irp); - break; + case IRP_MN_QUERY_POWER: + status = __FdoQueryDevicePower(Fdo, Irp); + break;- default:- ASSERT(FALSE); - break; - } + default: + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + break; }- return STATUS_SUCCESS;+ return status; }-static NTSTATUS-FdoSystemPower( - IN PXENVIF_THREAD Self, - IN PVOID Context +static FORCEINLINE NTSTATUS +__FdoSystemPower( + IN PXENVIF_FDO Fdo, + IN PIRP Irp ) { - PXENVIF_FDO Fdo = Context; - PKEVENT Event; - - Event = ThreadGetEvent(Self); - - for (;;) { - PIRP Irp; - PIO_STACK_LOCATION StackLocation; - UCHAR MinorFunction; - - if (Fdo->SystemPowerIrp == NULL) { - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - } - - if (ThreadIsAlerted(Self)) - break; - - Irp = Fdo->SystemPowerIrp; - - if (Irp == NULL) - continue; - - Fdo->SystemPowerIrp = NULL; - KeMemoryBarrier(); + PIO_STACK_LOCATION StackLocation; + NTSTATUS status;- StackLocation = IoGetCurrentIrpStackLocation(Irp);- MinorFunction = StackLocation->MinorFunction; + StackLocation = IoGetCurrentIrpStackLocation(Irp);- switch (StackLocation->MinorFunction) {- case IRP_MN_SET_POWER: - (VOID) __FdoSetSystemPower(Fdo, Irp); - break; + switch (StackLocation->MinorFunction) { + case IRP_MN_SET_POWER: + status = __FdoSetSystemPower(Fdo, Irp); + break;- case IRP_MN_QUERY_POWER:- (VOID) __FdoQuerySystemPower(Fdo, Irp); - break; + case IRP_MN_QUERY_POWER: + status = __FdoQuerySystemPower(Fdo, Irp); + break;- default:- ASSERT(FALSE); - break; - } + default: + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + break; }- return STATUS_SUCCESS;+ return status; }static DECLSPEC_NOINLINE NTSTATUSFdoDispatchPower( - IN PXENVIF_FDO Fdo, + IN PXENVIF_FDO Fdo, IN PIRP Irp ) { PIO_STACK_LOCATION StackLocation; - UCHAR MinorFunction; POWER_STATE_TYPE PowerType; - POWER_ACTION PowerAction; NTSTATUS status;StackLocation = IoGetCurrentIrpStackLocation(Irp);- MinorFunction = StackLocation->MinorFunction; - - if (MinorFunction != IRP_MN_QUERY_POWER && - MinorFunction != IRP_MN_SET_POWER) { - IoSkipCurrentIrpStackLocation(Irp); - status = IoCallDriver(Fdo->LowerDeviceObject, Irp); - - goto done; - } - PowerType = StackLocation->Parameters.Power.Type; - PowerAction = StackLocation->Parameters.Power.ShutdownType; - - if (PowerAction >= PowerActionShutdown) { - IoSkipCurrentIrpStackLocation(Irp); - status = IoCallDriver(Fdo->LowerDeviceObject, Irp); - - goto done; - }switch (PowerType) {case DevicePowerState: - IoMarkIrpPending(Irp); - - ASSERT3P(Fdo->DevicePowerIrp, ==, NULL); - Fdo->DevicePowerIrp = Irp; - KeMemoryBarrier(); - - ThreadWake(Fdo->DevicePowerThread); - - status = STATUS_PENDING; + status = __FdoDevicePower(Fdo, Irp); break;case SystemPowerState:- IoMarkIrpPending(Irp); - - ASSERT3P(Fdo->SystemPowerIrp, ==, NULL); - Fdo->SystemPowerIrp = Irp; - KeMemoryBarrier(); - - ThreadWake(Fdo->SystemPowerThread); - - status = STATUS_PENDING; + status = __FdoSystemPower(Fdo, Irp); break;default:@@ -2869,7 +3075,6 @@ FdoDispatchPower( break; }-done:return status; }@@ -3063,12 +3268,12 @@ FdoCreate(Fdo->LowerDeviceObject = IoAttachDeviceToDeviceStack(FunctionDeviceObject, PhysicalDeviceObject);- status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread);- if (!NT_SUCCESS(status)) + Fdo->SystemPowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject); + if (Fdo->SystemPowerWorkItem == NULL) goto fail3;- status = ThreadCreate(FdoDevicePower, Fdo, &Fdo->DevicePowerThread);- if (!NT_SUCCESS(status)) + Fdo->DevicePowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject); + if (Fdo->DevicePowerWorkItem == NULL) goto fail4;status = __FdoAcquireLowerBusInterface(Fdo);@@ -3226,16 +3431,14 @@ fail6: fail5: Error("fail5\n");- ThreadAlert(Fdo->DevicePowerThread);- ThreadJoin(Fdo->DevicePowerThread); - Fdo->DevicePowerThread = NULL; - + IoFreeWorkItem(Fdo->DevicePowerWorkItem); + Fdo->DevicePowerWorkItem = NULL; + fail4: Error("fail4\n");- ThreadAlert(Fdo->SystemPowerThread);- ThreadJoin(Fdo->SystemPowerThread); - Fdo->SystemPowerThread = NULL; + IoFreeWorkItem(Fdo->SystemPowerWorkItem); + Fdo->SystemPowerWorkItem = NULL;fail3:Error("fail3\n"); @@ -3311,13 +3514,11 @@ FdoDestroy(__FdoReleaseLowerBusInterface(Fdo); - ThreadAlert(Fdo->DevicePowerThread);- ThreadJoin(Fdo->DevicePowerThread); - Fdo->DevicePowerThread = NULL; + IoFreeWorkItem(Fdo->DevicePowerWorkItem); + Fdo->DevicePowerWorkItem = NULL;- ThreadAlert(Fdo->SystemPowerThread);- ThreadJoin(Fdo->SystemPowerThread); - Fdo->SystemPowerThread = NULL; + IoFreeWorkItem(Fdo->SystemPowerWorkItem); + Fdo->SystemPowerWorkItem = NULL;IoDetachDevice(Fdo->LowerDeviceObject); diff --git a/src/xenvif/pdo.c b/src/xenvif/pdo.cindex 0cef2d5..2979f53 100644 --- a/src/xenvif/pdo.c +++ b/src/xenvif/pdo.c @@ -68,9 +68,9 @@ struct _XENVIF_PDO { PXENVIF_DX Dx;- PXENVIF_THREAD SystemPowerThread;+ PIO_WORKITEM SystemPowerWorkItem; PIRP SystemPowerIrp; - PXENVIF_THREAD DevicePowerThread; + PIO_WORKITEM DevicePowerWorkItem; PIRP DevicePowerIrp;PXENVIF_FDO Fdo;@@ -2365,28 +2365,31 @@ PdoDispatchPnp( return status; }-static FORCEINLINE NTSTATUS-__PdoSetDevicePower( - IN PXENVIF_PDO Pdo, - IN PIRP Irp +__drv_functionClass(IO_WORKITEM_ROUTINE) +__drv_sameIRQL +static VOID +PdoDevicePowerWorker( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context ) { + PXENVIF_PDO Pdo = (PXENVIF_PDO) Context; + PIRP Irp; PIO_STACK_LOCATION StackLocation; DEVICE_POWER_STATE DeviceState; POWER_ACTION PowerAction; NTSTATUS status;+ UNREFERENCED_PARAMETER(DeviceObject);+ + Irp = InterlockedExchangePointer(&Pdo->DevicePowerIrp, NULL); + ASSERT(Irp != NULL); + StackLocation = IoGetCurrentIrpStackLocation(Irp); DeviceState = StackLocation->Parameters.Power.State.DeviceState; PowerAction = StackLocation->Parameters.Power.ShutdownType;- Trace("====> (%s) (%s:%s)\n",- __PdoGetName(Pdo), - PowerDeviceStateName(DeviceState), - PowerActionName(PowerAction)); - - ASSERT3U(PowerAction, <, PowerActionShutdown); - + status = STATUS_SUCCESS; if (__PdoGetDevicePowerState(Pdo) > DeviceState) { Trace("%s: POWERING UP: %s -> %s\n", __PdoGetName(Pdo), @@ -2395,7 +2398,6 @@ __PdoSetDevicePower(ASSERT3U(DeviceState, ==, PowerDeviceD0);status = PdoD3ToD0(Pdo); - ASSERT(NT_SUCCESS(status)); } else if (__PdoGetDevicePowerState(Pdo) < DeviceState) { Trace("%s: POWERING DOWN: %s -> %s\n", __PdoGetName(Pdo), @@ -2406,77 +2408,71 @@ __PdoSetDevicePower( PdoD0ToD3(Pdo); }+ /* Cannot fail the IRP at this point, keep going. */Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT);- Trace("<==== (%s:%s)\n",+ Trace("<==== (%s:%s)(%08x)\n", PowerDeviceStateName(DeviceState), - PowerActionName(PowerAction)); - - return STATUS_SUCCESS; + PowerActionName(PowerAction), + status); }-static NTSTATUS-PdoDevicePower( - IN PXENVIF_THREAD Self, - IN PVOID Context +static FORCEINLINE NTSTATUS +__PdoSetDevicePower( + IN PXENVIF_PDO Pdo, + IN PIRP Irp ) { - PXENVIF_PDO Pdo = Context; - PKEVENT Event; - - Event = ThreadGetEvent(Self); - - for (;;) { - PIRP Irp; - - if (Pdo->DevicePowerIrp == NULL) { - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - } + PIO_STACK_LOCATION StackLocation; + DEVICE_POWER_STATE DeviceState; + POWER_ACTION PowerAction; + PVOID Exchange;- if (ThreadIsAlerted(Self))- break; + StackLocation = IoGetCurrentIrpStackLocation(Irp); + DeviceState = StackLocation->Parameters.Power.State.DeviceState; + PowerAction = StackLocation->Parameters.Power.ShutdownType;- Irp = Pdo->DevicePowerIrp;+ Trace("====> (%s:%s)\n", + PowerDeviceStateName(DeviceState), + PowerActionName(PowerAction));- if (Irp == NULL)- continue; + IoMarkIrpPending(Irp);- Pdo->DevicePowerIrp = NULL;- KeMemoryBarrier(); + Exchange = InterlockedExchangePointer(&Pdo->DevicePowerIrp, Irp); + ASSERT(Exchange == NULL);- (VOID) __PdoSetDevicePower(Pdo, Irp);- } + IoQueueWorkItem(Pdo->DevicePowerWorkItem, + PdoDevicePowerWorker, + DelayedWorkQueue, + Pdo);- return STATUS_SUCCESS;+ return STATUS_PENDING; }-static FORCEINLINE NTSTATUS-__PdoSetSystemPower( - IN PXENVIF_PDO Pdo, - IN PIRP Irp +__drv_functionClass(IO_WORKITEM_ROUTINE) +__drv_sameIRQL +static VOID +PdoSystemPowerWorker( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context ) { - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - POWER_ACTION PowerAction; + PXENVIF_PDO Pdo = (PXENVIF_PDO) Context; + PIRP Irp; + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + POWER_ACTION PowerAction; + + UNREFERENCED_PARAMETER(DeviceObject); + + Irp = InterlockedExchangePointer(&Pdo->SystemPowerIrp, NULL); + ASSERT(Irp != NULL);StackLocation = IoGetCurrentIrpStackLocation(Irp);SystemState = StackLocation->Parameters.Power.State.SystemState; PowerAction = StackLocation->Parameters.Power.ShutdownType;- Trace("====> (%s) (%s:%s)\n",- __PdoGetName(Pdo), - PowerSystemStateName(SystemState), - PowerActionName(PowerAction)); - - ASSERT3U(PowerAction, <, PowerActionShutdown); - if (__PdoGetSystemPowerState(Pdo) > SystemState) { if (SystemState < PowerSystemHibernate && __PdoGetSystemPowerState(Pdo) >= PowerSystemHibernate) { @@ -2488,6 +2484,7 @@ __PdoSetSystemPower( __PdoGetName(Pdo), PowerSystemStateName(__PdoGetSystemPowerState(Pdo)), PowerSystemStateName(SystemState)); + } else if (__PdoGetSystemPowerState(Pdo) < SystemState) { Trace("%s: POWERING DOWN: %s -> %s\n", __PdoGetName(Pdo), @@ -2509,97 +2506,60 @@ __PdoSetSystemPower( Trace("<==== (%s:%s)\n", PowerSystemStateName(SystemState), PowerActionName(PowerAction)); - - return STATUS_SUCCESS; }-static NTSTATUS-PdoSystemPower( - IN PXENVIF_THREAD Self, - IN PVOID Context +static FORCEINLINE NTSTATUS +__PdoSetSystemPower( + IN PXENVIF_PDO Pdo, + IN PIRP Irp ) { - PXENVIF_PDO Pdo = Context; - PKEVENT Event; - - Event = ThreadGetEvent(Self); - - for (;;) { - PIRP Irp; - - if (Pdo->SystemPowerIrp == NULL) { - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - } + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + POWER_ACTION PowerAction; + PVOID Exchange;- if (ThreadIsAlerted(Self))- break; + StackLocation = IoGetCurrentIrpStackLocation(Irp); + SystemState = StackLocation->Parameters.Power.State.SystemState; + PowerAction = StackLocation->Parameters.Power.ShutdownType;- Irp = Pdo->SystemPowerIrp;+ Trace("====> (%s:%s)\n", + PowerSystemStateName(SystemState), + PowerActionName(PowerAction));- if (Irp == NULL)- continue; + IoMarkIrpPending(Irp);- Pdo->SystemPowerIrp = NULL;- KeMemoryBarrier(); + Exchange = InterlockedExchangePointer(&Pdo->SystemPowerIrp, Irp); + ASSERT(Exchange == NULL);- (VOID) __PdoSetSystemPower(Pdo, Irp);- } + IoQueueWorkItem(Pdo->SystemPowerWorkItem, + PdoSystemPowerWorker, + DelayedWorkQueue, + Pdo);- return STATUS_SUCCESS;+ return STATUS_PENDING; }-static DECLSPEC_NOINLINE NTSTATUS-PdoSetPower( +static FORCEINLINE NTSTATUS +__PdoSetPower( IN PXENVIF_PDO Pdo, IN PIRP Irp ) { PIO_STACK_LOCATION StackLocation; POWER_STATE_TYPE PowerType; - POWER_ACTION PowerAction; NTSTATUS status;StackLocation = IoGetCurrentIrpStackLocation(Irp);PowerType = StackLocation->Parameters.Power.Type; - PowerAction = StackLocation->Parameters.Power.ShutdownType; - - if (PowerAction >= PowerActionShutdown) { - Irp->IoStatus.Status = STATUS_SUCCESS; - - status = Irp->IoStatus.Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - goto done; - }switch (PowerType) {case DevicePowerState: - IoMarkIrpPending(Irp); - - ASSERT3P(Pdo->DevicePowerIrp, ==, NULL); - Pdo->DevicePowerIrp = Irp; - KeMemoryBarrier(); - - ThreadWake(Pdo->DevicePowerThread); - - status = STATUS_PENDING; + status = __PdoSetDevicePower(Pdo, Irp); break;case SystemPowerState:- IoMarkIrpPending(Irp); - - ASSERT3P(Pdo->SystemPowerIrp, ==, NULL); - Pdo->SystemPowerIrp = Irp; - KeMemoryBarrier(); - - ThreadWake(Pdo->SystemPowerThread); - - status = STATUS_PENDING; + status = __PdoSetSystemPower(Pdo, Irp); break;default:@@ -2608,48 +2568,41 @@ PdoSetPower( break; }-done:return status; }-static DECLSPEC_NOINLINE NTSTATUS-PdoQueryPower( - IN PXENVIF_PDO Pdo, - IN PIRP Irp +static FORCEINLINE NTSTATUS +__PdoQueryPower( + IN PXENVIF_PDO Pdo, + IN PIRP Irp ) { - NTSTATUS status; - UNREFERENCED_PARAMETER(Pdo);Irp->IoStatus.Status = STATUS_SUCCESS;- - status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; + + return STATUS_SUCCESS; }-static DECLSPEC_NOINLINE NTSTATUS+static NTSTATUS PdoDispatchPower( IN PXENVIF_PDO Pdo, IN PIRP Irp ) { PIO_STACK_LOCATION StackLocation; - UCHAR MinorFunction; NTSTATUS status;StackLocation = IoGetCurrentIrpStackLocation(Irp);- MinorFunction = StackLocation->MinorFunction;switch (StackLocation->MinorFunction) {case IRP_MN_SET_POWER: - status = PdoSetPower(Pdo, Irp); + status = __PdoSetPower(Pdo, Irp); break;case IRP_MN_QUERY_POWER:- status = PdoQueryPower(Pdo, Irp); + status = __PdoQueryPower(Pdo, Irp); break;default:@@ -2762,12 +2715,12 @@ PdoCreate( Pdo->Dx = Dx; Pdo->Fdo = Fdo;- status = ThreadCreate(PdoSystemPower, Pdo, &Pdo->SystemPowerThread);- if (!NT_SUCCESS(status)) + Pdo->SystemPowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject); + if (Pdo->SystemPowerWorkItem == NULL) goto fail3;- status = ThreadCreate(PdoDevicePower, Pdo, &Pdo->DevicePowerThread);- if (!NT_SUCCESS(status)) + Pdo->DevicePowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject); + if (Pdo->DevicePowerWorkItem == NULL) goto fail4;__PdoSetName(Pdo, Number);@@ -2860,16 +2813,14 @@ fail6: fail5: Error("fail5\n");- ThreadAlert(Pdo->DevicePowerThread);- ThreadJoin(Pdo->DevicePowerThread); - Pdo->DevicePowerThread = NULL; + IoFreeWorkItem(Pdo->DevicePowerWorkItem); + Pdo->DevicePowerWorkItem = NULL;fail4:Error("fail4\n");- ThreadAlert(Pdo->SystemPowerThread);- ThreadJoin(Pdo->SystemPowerThread); - Pdo->SystemPowerThread = NULL; + IoFreeWorkItem(Pdo->SystemPowerWorkItem); + Pdo->SystemPowerWorkItem = NULL;fail3:Error("fail3\n"); @@ -2939,13 +2890,11 @@ PdoDestroy(__PdoClearPermanentAddress(Pdo); - ThreadAlert(Pdo->DevicePowerThread);- ThreadJoin(Pdo->DevicePowerThread); - Pdo->DevicePowerThread = NULL; + IoFreeWorkItem(Pdo->DevicePowerWorkItem); + Pdo->DevicePowerWorkItem = NULL;- ThreadAlert(Pdo->SystemPowerThread);- ThreadJoin(Pdo->SystemPowerThread); - Pdo->SystemPowerThread = NULL; + IoFreeWorkItem(Pdo->SystemPowerWorkItem); + Pdo->SystemPowerWorkItem = NULL;Pdo->Fdo = NULL;Pdo->Dx = NULL;
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |