[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Asynchronous power handling.



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, wrong format comments removed
Signed-off-by: Owen Smith <owen.smith@xxxxxxxxx>

---
 src/xenvif/fdo.c | 810 +++++++++++++++++++++++++++++------------------
 src/xenvif/pdo.c | 263 +++++++--------
 2 files changed, 602 insertions(+), 471 deletions(-)

diff --git a/src/xenvif/fdo.c b/src/xenvif/fdo.c
index 451d582..efcd131 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,42 +2168,112 @@ FdoDispatchPnp(
     return status;
 }
 
-static FORCEINLINE NTSTATUS
-__FdoSetDevicePowerUp(
-    IN  PXENVIF_FDO     Fdo,
-    IN  PIRP            Irp
+__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);
+
+    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;
-    NTSTATUS            status;
+    PVOID               Exchange;
 
-    Trace("====>\n");
+    UNREFERENCED_PARAMETER(DeviceObject);
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
 
-    ASSERT3U(DeviceState, <,  __FdoGetDevicePowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
-
     Info("%s: %s -> %s\n",
          __FdoGetName(Fdo),
          PowerDeviceStateName(__FdoGetDevicePowerState(Fdo)),
          PowerDeviceStateName(DeviceState));
 
     ASSERT3U(DeviceState, ==, PowerDeviceD0);
-    status = FdoD3ToD0(Fdo);
-    ASSERT(NT_SUCCESS(status));
 
-done:
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    Exchange = InterlockedExchangePointer(&Fdo->DevicePowerIrp, Irp);
+    ASSERT(Exchange == NULL);
 
-    Trace("<==== (%08x)\n", status);
-    return status;
+    IoQueueWorkItem(Fdo->DevicePowerWorkItem,
+                    FdoDevicePowerUpWorker,
+                    DelayedWorkQueue,
+                    Fdo);
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+static FORCEINLINE NTSTATUS
+__FdoSetDevicePowerUp(
+    IN  PXENVIF_FDO     Fdo,
+    IN  PIRP            Irp
+    )
+{
+    PIO_STACK_LOCATION  StackLocation;
+    DEVICE_POWER_STATE  DeviceState;
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
+
+    ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo));
+
+    IoMarkIrpPending(Irp);
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           FdoSetDevicePowerUpComplete,
+                           Fdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+
+    (VOID) IoCallDriver(Fdo->LowerDeviceObject, Irp);
+
+    return STATUS_PENDING;
+}
+
+__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;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Irp = InterlockedExchangePointer(&Fdo->DevicePowerIrp, NULL);
+    ASSERT(Irp != NULL);
+
+    FdoD0ToD3(Fdo);
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
 }
 
 static FORCEINLINE NTSTATUS
@@ -2228,11 +2298,24 @@ __FdoSetDevicePowerDown(
 
     ASSERT3U(DeviceState, ==, PowerDeviceD3);
 
-    if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0)
-        FdoD0ToD3(Fdo);
+    if (__FdoGetDevicePowerState(Fdo) != PowerDeviceD0) {
+        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;
 }
@@ -2252,12 +2335,11 @@ __FdoSetDevicePower(
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("====> (%s:%s)\n",
-          PowerDeviceStateName(DeviceState), 
+    Trace("%s: ====> (%s:%s)\n",
+          __FdoGetName(Fdo),
+          PowerDeviceStateName(DeviceState),
           PowerActionName(PowerAction));
 
-    ASSERT3U(PowerAction, <, PowerActionShutdown);
-
     if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
         IoSkipCurrentIrpStackLocation(Irp);
         status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
@@ -2270,8 +2352,9 @@ __FdoSetDevicePower(
              __FdoSetDevicePowerDown(Fdo, Irp);
 
 done:
-    Trace("<==== (%s:%s)(%08x)\n",
-          PowerDeviceStateName(DeviceState), 
+    Trace("%s: <==== (%s:%s)(%08x)\n",
+          __FdoGetName(Fdo),
+          PowerDeviceStateName(DeviceState),
           PowerActionName(PowerAction),
           status);
     return status;
@@ -2279,8 +2362,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 +2371,123 @@ __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);
+    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;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-    Trace("%s\n", PowerDeviceStateName(DeviceState));
+    Irp = InterlockedExchangePointer(&Fdo->SystemPowerIrp, NULL);
+    ASSERT(Irp != NULL);
 
-    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);;
+    SystemState = StackLocation->Parameters.Power.State.SystemState;
 
-    PowerState.DeviceState = DeviceState;
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    Info("%s: %s -> %s\n",
+         __FdoGetName(Fdo),
+         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);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return;
+
+fail1:
+    Error("fail1 - but continue IRP processing. (%08x)\n", status);
+    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);
+
+    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 -> %s\n",
+             __FdoGetName(Fdo),
+             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;
+    }
+
+    return STATUS_MORE_PROCESSING_REQUIRED;
+
+fail1:
+    Error("fail1 - but continue IRP processing. (%08x)\n", status);
+    return STATUS_CONTINUE_COMPLETION;
 }
 
 static FORCEINLINE NTSTATUS
@@ -2337,42 +2496,103 @@ __FdoSetSystemPowerUp(
     IN  PIRP            Irp
     )
 {
+    PIO_STACK_LOCATION  StackLocation;
+    SYSTEM_POWER_STATE  SystemState;
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    SystemState = StackLocation->Parameters.Power.State.SystemState;
 
+    ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo));
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           FdoSetSystemPowerUpComplete,
+                           Fdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
+
+    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;
-    DEVICE_POWER_STATE  DeviceState;
-    NTSTATUS            status;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Irp = InterlockedExchangePointer(&Fdo->SystemPowerIrp, NULL);
+    ASSERT(Irp != NULL);
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
 
-    ASSERT3U(SystemState, <,  __FdoGetSystemPowerState(Fdo));
+    __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
+    FdoS3ToS4(Fdo);
+    __FdoSetSystemPowerState(Fdo, SystemState);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
+}
+
+__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;
+
+    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 -> %s\n",
          __FdoGetName(Fdo),
-         PowerSystemStateName(__FdoGetSystemPowerState(Fdo)),
-         PowerSystemStateName(SystemState));
+        PowerSystemStateName(__FdoGetSystemPowerState(Fdo)),
+        PowerSystemStateName(SystemState));
 
-    if (SystemState < PowerSystemHibernate &&
-        __FdoGetSystemPowerState(Fdo) >= PowerSystemHibernate) {
-        __FdoSetSystemPowerState(Fdo, PowerSystemHibernate);
-        FdoS4ToS3(Fdo);
-    }
-
-    __FdoSetSystemPowerState(Fdo, SystemState);
+    if (SystemState >= PowerSystemHibernate &&
+        __FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) {
+        PVOID Exchange;
 
-    DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
-    FdoRequestSetDevicePower(Fdo, DeviceState);
+        Exchange = InterlockedExchangePointer(&Fdo->SystemPowerIrp, Irp);
+        ASSERT(Exchange == NULL);
 
-done:
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        IoQueueWorkItem(Fdo->DevicePowerWorkItem,
+                        FdoSystemPowerDownWorker,
+                        DelayedWorkQueue,
+                        Fdo);
+    } else {
+        __FdoSetSystemPowerState(Fdo, SystemState);
 
-    return status;
+        IoCopyCurrentIrpStackLocationToNext(Irp);
+        IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    }
 }
 
 static FORCEINLINE NTSTATUS
@@ -2383,33 +2603,38 @@ __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);
+    ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo));
 
-    Info("%s: %s -> %s\n",
-         __FdoGetName(Fdo),
-         PowerSystemStateName(__FdoGetSystemPowerState(Fdo)),
-         PowerSystemStateName(SystemState));
+    PowerState.DeviceState = 
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
 
-    if (SystemState >= PowerSystemHibernate &&
-        __FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) {
-        __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
-        FdoS3ToS4(Fdo);
+    if (SystemState >= PowerSystemShutdown) {
+        IoCopyCurrentIrpStackLocationToNext(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    } else {
+        status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+                                   IRP_MN_SET_POWER,
+                                   PowerState,
+                                   FdoRequestSetDevicePowerDownComplete,
+                                   Irp,
+                                   NULL);
+        if (!NT_SUCCESS(status))
+            goto fail1;
     }
 
-    __FdoSetSystemPowerState(Fdo, SystemState);
+    return status;
 
-    IoSkipCurrentIrpStackLocation(Irp);
-    status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+fail1:
+    Error("fail1 - but continue IRP processing. (%08x)\n", status);
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
 
     return status;
 }
@@ -2429,29 +2654,32 @@ __FdoSetSystemPower(
     SystemState = StackLocation->Parameters.Power.State.SystemState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("====> (%s:%s)\n",
-          PowerSystemStateName(SystemState), 
-          PowerActionName(PowerAction));
+    IoMarkIrpPending(Irp);
 
-    ASSERT3U(PowerAction, <, PowerActionShutdown);
+    Trace("%s: ====> (%s:%s)\n",
+          __FdoGetName(Fdo),
+          PowerSystemStateName(SystemState),
+          PowerActionName(PowerAction));
 
     if (SystemState == __FdoGetSystemPowerState(Fdo)) {
-        IoSkipCurrentIrpStackLocation(Irp);
+        IoCopyCurrentIrpStackLocationToNext(Irp);
         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), 
+    Trace("%s: <==== (%s:%s)(%08x)\n",
+          __FdoGetName(Fdo),
+          PowerSystemStateName(SystemState),
           PowerActionName(PowerAction),
           status);
-    return status;
+
+    return STATUS_PENDING;
 }
 
 static FORCEINLINE NTSTATUS
@@ -2467,12 +2695,10 @@ __FdoQueryDevicePowerUp(
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
 
-    ASSERT3U(DeviceState, <,  __FdoGetDevicePowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo));
 
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    IoSkipCurrentIrpStackLocation(Irp);
+    status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
 
     return status;
 }
@@ -2490,7 +2716,7 @@ __FdoQueryDevicePowerDown(
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
 
-    ASSERT3U(DeviceState, >,  __FdoGetDevicePowerState(Fdo));
+    ASSERT3U(DeviceState, >, __FdoGetDevicePowerState(Fdo));
 
     IoSkipCurrentIrpStackLocation(Irp);
     status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
@@ -2513,12 +2739,11 @@ __FdoQueryDevicePower(
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("====> (%s:%s)\n",
-          PowerDeviceStateName(DeviceState), 
+    Trace("%s: ====> (%s:%s)\n",
+          __FdoGetName(Fdo),
+          PowerDeviceStateName(DeviceState),
           PowerActionName(PowerAction));
 
-    ASSERT3U(PowerAction, <, PowerActionShutdown);
-
     if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
         IoSkipCurrentIrpStackLocation(Irp);
         status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
@@ -2531,8 +2756,9 @@ __FdoQueryDevicePower(
              __FdoQueryDevicePowerDown(Fdo, Irp);
 
 done:
-    Trace("<==== (%s:%s)(%08x)\n",
-          PowerDeviceStateName(DeviceState), 
+    Trace("%s: <==== (%s:%s)(%08x)\n",
+          __FdoGetName(Fdo),
+          PowerDeviceStateName(DeviceState),
           PowerActionName(PowerAction),
           status);
     return status;
@@ -2540,8 +2766,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 +2775,55 @@ __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);
+    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);
+    return STATUS_MORE_PROCESSING_REQUIRED;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    Irp->IoStatus.Status = status;
+
+    return STATUS_CONTINUE_COMPLETION;
 }
 
 static FORCEINLINE NTSTATUS
@@ -2598,30 +2832,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));
+    ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo));
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
+    IoMarkIrpPending(Irp);
+    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);
+    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 +2897,7 @@ __FdoQuerySystemPowerDown(
 {
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    DEVICE_POWER_STATE  DeviceState;
+    POWER_STATE         PowerState;
     NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
@@ -2640,12 +2905,26 @@ __FdoQuerySystemPowerDown(
 
     ASSERT3U(SystemState, >,  __FdoGetSystemPowerState(Fdo));
 
-    DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+    PowerState.DeviceState = 
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+
+    status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+                               IRP_MN_QUERY_POWER,
+                               PowerState,
+                               FdoRequestQueryDevicePowerDownComplete,
+                               Irp,
+                               NULL);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    IoMarkIrpPending(Irp);
 
-    FdoRequestQueryDevicePower(Fdo, DeviceState);
+    return STATUS_PENDING;
 
-    IoSkipCurrentIrpStackLocation(Irp);
-    status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
     return status;
 }
@@ -2665,12 +2944,11 @@ __FdoQuerySystemPower(
     SystemState = StackLocation->Parameters.Power.State.SystemState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("====> (%s:%s)\n",
-          PowerSystemStateName(SystemState), 
+    Trace("%s: ====> (%s:%s)\n",
+          __FdoGetName(Fdo),
+          PowerSystemStateName(SystemState),
           PowerActionName(PowerAction));
 
-    ASSERT3U(PowerAction, <, PowerActionShutdown);
-
     if (SystemState == __FdoGetSystemPowerState(Fdo)) {
         IoSkipCurrentIrpStackLocation(Irp);
         status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
@@ -2683,184 +2961,93 @@ __FdoQuerySystemPower(
              __FdoQuerySystemPowerDown(Fdo, Irp);
 
 done:
-    Trace("<==== (%s:%s)(%08x)\n",
-          PowerSystemStateName(SystemState), 
+    Trace("%s: <==== (%s:%s)(%08x)\n",
+          __FdoGetName(Fdo),
+          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 NTSTATUS
 FdoDispatchPower(
-    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 +3056,6 @@ FdoDispatchPower(
         break;
     }
 
-done:
     return status;
 }
 
@@ -3063,12 +3249,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 +3412,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 +3495,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.c
index 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;
-- 
2.41.0.windows.3




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.