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

[PATCH] [RFQ] Asynchronous power handling.


  • To: <win-pv-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Martin Harvey <Martin.Harvey@xxxxxxxxxx>
  • Date: Tue, 8 Nov 2022 11:51:55 +0000
  • Authentication-results: esa5.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none
  • Cc: Martin Harvey <Martin.Harvey@xxxxxxxxxx>, Martin Harvey <martin.harvey@xxxxxxxxxx>
  • Delivery-date: Tue, 08 Nov 2022 11:52:38 +0000
  • Ironport-data: A9a23:gx7tta+rD7C4lRiITzMhDrUD2H6TJUtcMsCJ2f8bNWPcYEJGY0x3z WoWWDuBaPzfamv8e4slYIvjoB8CsMODy4A1HVZspXs8E34SpcT7XtnIdU2Y0wF+jCHgZBk+s 5hBMImowOQcFCK0SsKFa+C5xZVE/fjUAOG6UKucYHsZqTZMEE8JkQhkl/MynrlmiN24BxLlk d7pqojUNUTNNwRcawr40Ire7kIx1BjOkGlA5AZnPKgb5Aa2e0Q9V/rzG4ngdxMUfaEMdgKKb 76r5K20+Grf4yAsBruN+losWhRXKlJ6FVHmZkt+A8BOsDAbzsAB+v9T2M4nQVVWk120c+VZk 72hg3ASpTABZcUgkMxFO/VR/roX0aduoNcrKlDn2SCfItGvn9IBDJyCAWlvVbD09NqbDkke/ O4qOWs3NSyDgszt+6+kYPFm3OMKeZyD0IM34hmMzBncBPciB5vCX7/L9ZlT2zJYasJmRKiEI ZBDMHw2MUqGM0Yn1lQ/UfrSmM+tj2PjcjseqFuPu6cmy2PS0BZwwP7mN9+9ltmiFZ4JwxfF+ D6uE2LRMkA8adC58hq/wGvvvMjvsgrySYMsC+jtnhJtqALKnTFCYPEMbnOkoP/8klD7V99BJ kg8/is1sbN05EGtVsP6XRCzvDiDpBF0ZjZLO7RkskfXkPOSulvHQDhfJtJcVDA4nJ8/Vw47j WXSo9PsK2dUraK/UXjH0Z7B+FteJhMpBWMFYCYFSy4M7N/ivJw/g3rzczpzLEKmpoarQG+tm lhmuAB73uxO1pBTi81X6Hid21qRSo71ohnZD+k9dkas9UtHaYGsfOREAnCLvK8bfO51orRs1 UXoevRyDshUU/lhdwTXGo3h+Y1FAN7UWAAweXY1Q/EcG82FohZOvel4uVmS3ntBPMceYiPOa 0TOow5X75I7FCL0M/AnP9zoU5xwk/iI+THZuhf8N4QmX3SMXFXfoHEGibC4gwgBb3TAYYlgY MzGIK5A/F4RCLh9zSreegvu+eZD+83/rEuNLa3GI+OPiufDNSPMEexZbjNjrIkRtcu5nekcy P4HX+Pi9vmVeLCWjvX/mWLLEW03EA==
  • Ironport-hdrordr: A9a23:9JM3waxMU7IxHWflOs1KKrPwIL1zdoMgy1knxilNoRw8SKKlfq eV7ZAmPH7P+VAssR4b+exoVJPtfZq+z+8R3WByB8bAYOCOggLBR+sO0WKL+UyGJ8SUzI9gPM lbHJSWcOeAb2RHsQ==
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>

This patch submitted for comment as part of recent efforts to improve
reliability and performance in the windows PV drivers, particularly
in the hibernate and shutdown testcases under driver verifier.

This patch is just one sample (for xenbus). We also have patches
for all the other xen* windows drivers.

Internal test results indicate that this code removes at least one
failure case on the shutdown path, and also demonstrates that an
existing interittent hibernate bug is not due to the PV driver stack.

We are performing long-term soak testing of this branch in parallel
with mainstream development to check that it solves (or ameliorates,
or aids investigation) into intermittent test failures.

We hope to provide full WHQL test results, and statistical failure
rates for this change in the coming months, as well as an analysis
of any other bugs or problems uncovered.

If this change turns out to be significantly better than the current
codebase, then we expect it will be possible to break-down this
patch into small pieces (by file or by device object) for easier
merging and integration.

Signed-off-by: Martin Harvey <martin.harvey@xxxxxxxxxx>
---
 src/xenbus/fdo.c   | 1051 +++++++++++++++++++++++++++++---------------
 src/xenbus/pdo.c   |  302 ++++++-------
 src/xenbus/store.c |    6 +-
 src/xenbus/types.h |    5 +
 src/xenfilt/fdo.c  |  600 +++++++------------------
 src/xenfilt/pdo.c  |  611 +++++++------------------
 6 files changed, 1166 insertions(+), 1409 deletions(-)

diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index d08c518..9501c31 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -63,6 +63,7 @@
 #include "dbg_print.h"
 #include "assert.h"
 #include "util.h"
+#include "types.h"
 
 #define XENBUS_FDO_TAG 'ODF'
 
@@ -106,11 +107,6 @@ struct _XENBUS_FDO {
     ULONG                           Usage[DeviceUsageTypeDumpFile + 1];
     BOOLEAN                         NotDisableable;
 
-    PXENBUS_THREAD                  SystemPowerThread;
-    PIRP                            SystemPowerIrp;
-    PXENBUS_THREAD                  DevicePowerThread;
-    PIRP                            DevicePowerIrp;
-
     CHAR                            VendorName[MAXNAMELEN];
 
     MUTEX                           Mutex;
@@ -168,6 +164,11 @@ struct _XENBUS_FDO {
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
     BOOLEAN                         ConsoleAcquired;
     PLOG_DISPOSITION                LogDisposition;
+
+    PIO_WORKITEM                     FdoSPowerWorkItem;
+    XENBUS_POWER_WORKITEM_CONTEXT FdoSPowerContext;
+    PIO_WORKITEM                     FdoDPowerWorkItem;
+    XENBUS_POWER_WORKITEM_CONTEXT FdoDPowerContext;
 };
 
 static FORCEINLINE PVOID
@@ -4585,6 +4586,9 @@ FdoQueryCapabilities(
         DEVICE_POWER_STATE  DevicePowerState;
 
         DevicePowerState = 
Fdo->LowerDeviceCapabilities.DeviceState[SystemPowerState];
+        Trace("PowerCaps: SystemState: %s (%u), best device power: %s (%u)\n",
+            SystemPowerStateName(SystemPowerState), SystemPowerState,
+            DevicePowerStateName(DevicePowerState), DevicePowerState);
     }
 
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -4775,42 +4779,142 @@ FdoDispatchPnp(
     return status;
 }
 
+VOID _FdoD3toD0PowerWorker(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PVOID Context
+  )
+{
+    PXENBUS_POWER_WORKITEM_CONTEXT PowerContext = 
(PXENBUS_POWER_WORKITEM_CONTEXT)Context;
+    PXENBUS_FDO     Fdo = (PXENBUS_FDO) PowerContext->FdoOrPdo;
+    PIRP              Irp;
+    NTSTATUS          status;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Irp = InterlockedExchangePointer(&PowerContext->Irp, NULL);
+    ASSERT(Irp != NULL);
+
+    status = FdoD3ToD0(Fdo);
+    if (!NT_SUCCESS(status))
+        Error("fail1 - but continue IRP processing. (%08x)\n", status);
+
+    /* Cannot change Irp->IoStatus */
+    /* Continue completion chain */
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+VOID FdoD3toD0PowerWorker(
+    IN PXENBUS_FDO     Fdo,
+    IN PIRP              Irp
+)
+{
+    PVOID Exchange;
+
+    ASSERT(Fdo->FdoDPowerContext.FdoOrPdo == Fdo);
+    Exchange = InterlockedExchangePointer(&Fdo->FdoDPowerContext.Irp, Irp);
+    ASSERT(Exchange == NULL);
+
+    IoQueueWorkItem(Fdo->FdoDPowerWorkItem,
+                    _FdoD3toD0PowerWorker,
+                    DelayedWorkQueue,
+                    &Fdo->FdoDPowerContext);
+}
+
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
+static NTSTATUS
+FdoCompleteSetDevicePowerUp(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
+    IN  PVOID           Context
+    )
+{
+    PXENBUS_FDO     Fdo = (PXENBUS_FDO) Context;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    DEVICE_POWER_STATE DeviceState = 
StackLocation->Parameters.Power.State.DeviceState;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    /* Already marked pending by us */
+    Info("%s -> %s\n",
+         DevicePowerStateName(__FdoGetDevicePowerState(Fdo)),
+         DevicePowerStateName(DeviceState));
+
+    /* Don't worry about IRP IoStatus */
+    ASSERT3U(DeviceState, ==, PowerDeviceD0);
+    FdoD3toD0PowerWorker(Fdo, Irp);
+
+    /* Stop completion chain in all circumstances. */
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
 static NTSTATUS
-FdoSetDevicePowerUp(
+FdoDispatchSetDevicePowerUp(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
     DEVICE_POWER_STATE  DeviceState;
-    NTSTATUS            status;
+
+    Trace("====>\n");
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
 
     ASSERT3U(DeviceState, <,  __FdoGetDevicePowerState(Fdo));
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
+    IoMarkIrpPending(Irp);
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           FdoCompleteSetDevicePowerUp,
+                           Fdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    return STATUS_PENDING;
+}
 
-    Info("%s: %s -> %s\n",
-         __FdoGetName(Fdo),
-         DevicePowerStateName(__FdoGetDevicePowerState(Fdo)),
-         DevicePowerStateName(DeviceState));
+VOID _FdoD0toD3PowerWorker(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PVOID Context
+  )
+{
+    PXENBUS_POWER_WORKITEM_CONTEXT PowerContext = 
(PXENBUS_POWER_WORKITEM_CONTEXT)Context;
+    PXENBUS_FDO     Fdo = (PXENBUS_FDO) PowerContext->FdoOrPdo;
+    PIRP              Irp;
 
-    ASSERT3U(DeviceState, ==, PowerDeviceD0);
-    status = FdoD3ToD0(Fdo);
-    ASSERT(NT_SUCCESS(status));
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-done:
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    Irp = InterlockedExchangePointer(&PowerContext->Irp, NULL);
+    ASSERT(Irp != NULL);
 
-    return status;
+    FdoD0ToD3(Fdo);
+    /* We are on dispatch path here, irp pended. */
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
+}
+
+VOID FdoD0ToD3PowerWorker(
+    IN PXENBUS_FDO     Fdo,
+    IN PIRP              Irp
+)
+{
+    PVOID Exchange;
+
+    ASSERT(Fdo->FdoDPowerContext.FdoOrPdo == Fdo);
+    Exchange = InterlockedExchangePointer(&Fdo->FdoDPowerContext.Irp, Irp);
+    ASSERT(Exchange == NULL);
+
+    IoQueueWorkItem(Fdo->FdoDPowerWorkItem,
+                    _FdoD0toD3PowerWorker,
+                    DelayedWorkQueue,
+                    &Fdo->FdoDPowerContext);
 }
 
 static NTSTATUS
-FdoSetDevicePowerDown(
+FdoDispatchSetDevicePowerDown(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
@@ -4831,17 +4935,22 @@ FdoSetDevicePowerDown(
 
     ASSERT3U(DeviceState, ==, PowerDeviceD3);
 
-    if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0)
-        FdoD0ToD3(Fdo);
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    /* All handled in dispatch, no extra error handling */
+    if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0) {
+        IoMarkIrpPending(Irp);
+        FdoD0ToD3PowerWorker(Fdo, Irp);
+        status = STATUS_PENDING;
+    } else {
+        /* Not marked pending, can skip */
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    }
 
     return status;
 }
 
 static NTSTATUS
-FdoSetDevicePower(
+FdoDispatchSetDevicePower(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
@@ -4859,18 +4968,16 @@ FdoSetDevicePower(
           DevicePowerStateName(DeviceState), 
           PowerActionName(PowerAction));
 
-    ASSERT3U(PowerAction, <,  PowerActionShutdown);
-
     if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
 
         goto done;
     }
 
     status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ?
-             FdoSetDevicePowerUp(Fdo, Irp) :
-             FdoSetDevicePowerDown(Fdo, Irp);
+             FdoDispatchSetDevicePowerUp(Fdo, Irp) :
+             FdoDispatchSetDevicePowerDown(Fdo, Irp);
 
 done:
     Trace("<==== (%s:%s)(%08x)\n",
@@ -4880,10 +4987,34 @@ done:
     return status;
 }
 
+static NTSTATUS
+FdoRequestSetDevicePower(
+    IN  PXENBUS_FDO               Fdo,
+    IN  DEVICE_POWER_STATE          DeviceState,
+    IN  PREQUEST_POWER_COMPLETE     CompletionFunction,
+    IN  PVOID                       Context
+    )
+{
+    POWER_STATE             PowerState;
+    NTSTATUS                status;
+
+    Trace("%s\n", DevicePowerStateName(DeviceState));
+
+    PowerState.DeviceState = DeviceState;
+
+    status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+                               IRP_MN_SET_POWER,
+                               PowerState,
+                               CompletionFunction,
+                               Context,
+                               NULL);
+    return status;
+}
+
 __drv_functionClass(REQUEST_POWER_COMPLETE)
 __drv_sameIRQL
 VOID
-FdoRequestSetDevicePowerCompletion(
+FdoCompleteSetSystemPowerUp2(
     IN  PDEVICE_OBJECT      DeviceObject,
     IN  UCHAR               MinorFunction,
     IN  POWER_STATE         PowerState,
@@ -4891,112 +5022,238 @@ FdoRequestSetDevicePowerCompletion(
     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));
+    /* Although can change Irp->IoStatus for pended IRP, drivers should not 
fail this. */
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
 
-    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+static NTSTATUS
+FdoCompleteSetSystemPowerUpTail(
+    IN PXENBUS_FDO     Fdo,
+    IN PIRP              Irp
+)
+{
+    PIO_STACK_LOCATION  StackLocation = IoGetCurrentIrpStackLocation(Irp);;
+    SYSTEM_POWER_STATE  SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+    DEVICE_POWER_STATE  DeviceState;
+    /* This executes in two contexts:
+       1. When we are in the completion routine FdoCompleteSetSystemPowerUp
+       2. When we at the end of the worker routine FdoS4ToS3PowerWorker
+    */
+
+    Info("%s -> %s\n",
+         SystemPowerStateName(__FdoGetSystemPowerState(Fdo)),
+         SystemPowerStateName(SystemState));
+
+    __FdoSetSystemPowerState(Fdo, SystemState);
+
+    DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+    return FdoRequestSetDevicePower(Fdo, DeviceState, 
FdoCompleteSetSystemPowerUp2, Irp);
 }
 
-__drv_requiresIRQL(PASSIVE_LEVEL)
-static VOID
-FdoRequestSetDevicePower(
-    IN  PXENBUS_FDO         Fdo,
-    IN  DEVICE_POWER_STATE  DeviceState
-    )
+VOID _FdoS4ToS3PowerWorker(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PVOID Context
+  )
 {
-    POWER_STATE             PowerState;
-    KEVENT                  Event;
-    NTSTATUS                status;
+    PXENBUS_POWER_WORKITEM_CONTEXT PowerContext = 
(PXENBUS_POWER_WORKITEM_CONTEXT)Context;
+    PXENBUS_FDO     Fdo = (PXENBUS_FDO) PowerContext->FdoOrPdo;
+    PIRP              Irp;
+    NTSTATUS          status;
 
-    Trace("%s\n", DevicePowerStateName(DeviceState));
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    Irp = InterlockedExchangePointer(&PowerContext->Irp, NULL);
+    ASSERT(Irp != NULL);
 
-    PowerState.DeviceState = DeviceState;
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    __FdoSetSystemPowerState(Fdo, PowerSystemHibernate); /* Meet preconds for 
S4 to S3 */
+    FdoS4ToS3(Fdo);
+    status = FdoCompleteSetSystemPowerUpTail(Fdo, Irp); /* And set final 
system state, S3 or higher */
 
-    status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
-                               IRP_MN_SET_POWER,
-                               PowerState,
-                               FdoRequestSetDevicePowerCompletion,
-                               &Event,
-                               NULL);
-    ASSERT(NT_SUCCESS(status));
+    /* Whatever happens, we have stopped completion processing for SIrp,
+      to restart SIrp processing, call IoCompleteRequest. */
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    (VOID) KeWaitForSingleObject(&Event,
-                                 Executive,
-                                 KernelMode,
-                                 FALSE,
-                                 NULL);
+    return; /* FdoCompleteSetSystemPowerUp2 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);
+}
+
+VOID FdoS4ToS3PowerWorker(
+    IN PXENBUS_FDO     Fdo,
+    IN PIRP              Irp
+)
+{
+    PVOID Exchange;
+
+    ASSERT(Fdo->FdoSPowerContext.FdoOrPdo == Fdo);
+    Exchange = InterlockedExchangePointer(&Fdo->FdoSPowerContext.Irp, Irp);
+    ASSERT(Exchange == NULL);
+
+    IoQueueWorkItem(Fdo->FdoDPowerWorkItem,
+                    _FdoS4ToS3PowerWorker,
+                    DelayedWorkQueue,
+                    &Fdo->FdoSPowerContext);
 }
 
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
 static NTSTATUS
-FdoSetSystemPowerUp(
-    IN  PXENBUS_FDO     Fdo,
-    IN  PIRP            Irp
+FdoCompleteSetSystemPowerUp(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
+    IN  PVOID           Context
     )
 {
-
+    PXENBUS_FDO     Fdo = (PXENBUS_FDO) Context;
     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));
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
+    /* IRP marked as pending on dispatch path, no need to check pending 
returned */
 
-    Info("%s: %s -> %s\n",
-         __FdoGetName(Fdo),
-         SystemPowerStateName(__FdoGetSystemPowerState(Fdo)),
-         SystemPowerStateName(SystemState));
+    /* Don't worry about IRP IoStatus */
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    BUG_ON(StackLocation->DeviceObject != Fdo->Dx->DeviceObject);
+    SystemState = StackLocation->Parameters.Power.State.SystemState;
 
     if (SystemState < PowerSystemHibernate &&
         __FdoGetSystemPowerState(Fdo) >= PowerSystemHibernate) {
-        __FdoSetSystemPowerState(Fdo, PowerSystemHibernate);
-        FdoS4ToS3(Fdo);
+        FdoS4ToS3PowerWorker(Fdo, Irp);
+        goto done; /* Stop completion routine for the moment... */
     }
 
-    __FdoSetSystemPowerState(Fdo, SystemState);
+    status = FdoCompleteSetSystemPowerUpTail(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
-    FdoRequestSetDevicePower(Fdo, DeviceState);
+    goto done;
 
-done:
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+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;
 
-    return status;
+done:
+    /* Will later complete the IRP (which is marked pending, in worker or 2nd 
level comp routine.)*/
+        return STATUS_MORE_PROCESSING_REQUIRED;
 }
 
-static NTSTATUS
-FdoSetSystemPowerDown(
+static VOID
+FdoDispatchSetSystemPowerUp(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    DEVICE_POWER_STATE  DeviceState;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    BUG_ON(StackLocation->DeviceObject != Fdo->Dx->DeviceObject);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
 
-    ASSERT3U(SystemState, >,  __FdoGetSystemPowerState(Fdo));
+    ASSERT3U(SystemState, <,  __FdoGetSystemPowerState(Fdo));
 
-    DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+    /* IRP already pended, and we want to complete it *after* completion 
routine. */
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           FdoCompleteSetSystemPowerUp,
+                           Fdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
+}
+
+VOID
+FdoDispatchSetSystemPowerDown2Tail(
+    IN PXENBUS_FDO     Fdo,
+    IN PIRP              Irp
+)
+{
+    PIO_STACK_LOCATION  StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    SYSTEM_POWER_STATE  SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+
+    __FdoSetSystemPowerState(Fdo, SystemState);
+}
+
+VOID _FdoS3ToS4PowerWorker(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PVOID Context
+  )
+{
+    PXENBUS_POWER_WORKITEM_CONTEXT PowerContext = 
(PXENBUS_POWER_WORKITEM_CONTEXT)Context;
+    PXENBUS_FDO     Fdo = (PXENBUS_FDO) PowerContext->FdoOrPdo;
+    PIRP              Irp;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Irp = InterlockedExchangePointer(&PowerContext->Irp, NULL);
+    ASSERT(Irp != NULL);
+
+    /* Meet preconditions for S3 to S4 */
+    __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
+    FdoS3ToS4(Fdo);
+    FdoDispatchSetSystemPowerDown2Tail(Fdo, Irp);
+
+    IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
+}
+
+VOID FdoS3ToS4PowerWorker(
+    IN PXENBUS_FDO     Fdo,
+    IN PIRP              Irp
+)
+{
+    PVOID Exchange;
+
+    ASSERT(Fdo->FdoSPowerContext.FdoOrPdo == Fdo);
+    Exchange = InterlockedExchangePointer(&Fdo->FdoSPowerContext.Irp, Irp);
+    ASSERT(Exchange == NULL);
+
+    IoQueueWorkItem(Fdo->FdoDPowerWorkItem,
+                    _FdoS3ToS4PowerWorker,
+                    DelayedWorkQueue,
+                    &Fdo->FdoSPowerContext);
+}
+
+__drv_functionClass(REQUEST_POWER_COMPLETE)
+__drv_sameIRQL
+VOID
+FdoDispatchSetSystemPowerDown2(
+    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;
+    PXENBUS_DX        Dx = (PXENBUS_DX)UpperDeviceObject->DeviceExtension;
+    PXENBUS_FDO       Fdo = Dx->Fdo;
+    SYSTEM_POWER_STATE  SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(MinorFunction);
+    UNREFERENCED_PARAMETER(PowerState);
 
-    FdoRequestSetDevicePower(Fdo, DeviceState);
+    if (!NT_SUCCESS(IoStatus->Status)) {
+        Error("fail1 - but continue IRP processing. (%08x)\n", 
IoStatus->Status);
+    }
 
     Info("%s: %s -> %s\n",
          __FdoGetName(Fdo),
@@ -5005,60 +5262,110 @@ FdoSetSystemPowerDown(
 
     if (SystemState >= PowerSystemHibernate &&
         __FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) {
-        __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
-        FdoS3ToS4(Fdo);
+        FdoS3ToS4PowerWorker(Fdo, Irp);
+        goto done;
     }
 
-    __FdoSetSystemPowerState(Fdo, SystemState);
+    FdoDispatchSetSystemPowerDown2Tail(Fdo, Irp);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    goto calldown;
 
-    return status;
+calldown:
+    IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    return;
+
+done:
+    ;
 }
 
-static NTSTATUS
-FdoSetSystemPower(
+
+static VOID
+FdoDispatchSetSystemPowerDown(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    POWER_ACTION        PowerAction;
+    DEVICE_POWER_STATE  DeviceState;
     NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    BUG_ON(StackLocation->DeviceObject != Fdo->Dx->DeviceObject);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
-
-    Trace("====> (%s:%s)\n",
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction));
 
-    ASSERT3U(PowerAction, <,  PowerActionShutdown);
+    ASSERT3U(SystemState, >,  __FdoGetSystemPowerState(Fdo));
 
-    if (SystemState == __FdoGetSystemPowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
 
+    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. */
         goto done;
     }
 
-    status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?
-             FdoSetSystemPowerUp(Fdo, Irp) :
-             FdoSetSystemPowerDown(Fdo, Irp);
+    status = FdoRequestSetDevicePower(Fdo, DeviceState, 
FdoDispatchSetSystemPowerDown2, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
+    /* IRP already marked pending - nothing more to do if awaiting callback. */
+    return;
+
+fail1:
+    /* In theory could change IRP status, but are not supposed to fail this 
IRP. */
+    Error("fail1 - but continue IRP processing. (%08x)\n", status);
 done:
-    Trace("<==== (%s:%s)(%08x)\n",
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction),
-          status);
-    return status;
+    IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
 }
 
 static NTSTATUS
-FdoQueryDevicePowerUp(
+FdoDispatchSetSystemPower(
+    IN  PXENBUS_FDO     Fdo,
+    IN  PIRP            Irp
+    )
+{
+    PIO_STACK_LOCATION  StackLocation;
+    SYSTEM_POWER_STATE  SystemState;
+    POWER_ACTION        PowerAction;
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    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",
+          SystemPowerStateName(SystemState),
+          PowerActionName(PowerAction));
+
+    if (SystemState == __FdoGetSystemPowerState(Fdo)) {
+        IoCopyCurrentIrpStackLocationToNext(Irp); /* Pended, copy not skip */
+        IoCallDriver(Fdo->LowerDeviceObject, Irp);
+        goto done;
+    }
+
+    if (SystemState < __FdoGetSystemPowerState(Fdo)) {
+        FdoDispatchSetSystemPowerUp(Fdo, Irp);
+    } else {
+        FdoDispatchSetSystemPowerDown(Fdo, Irp);
+    }
+
+done:
+    Trace("<==== (%s:%s)\n",
+          SystemPowerStateName(SystemState),
+          PowerActionName(PowerAction));
+
+    return STATUS_PENDING;
+}
+
+
+static NTSTATUS
+FdoDispatchQueryDevicePowerUp(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
@@ -5072,15 +5379,15 @@ FdoQueryDevicePowerUp(
 
     ASSERT3U(DeviceState, <,  __FdoGetDevicePowerState(Fdo));
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-
-    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;
 }
 
 static NTSTATUS
-FdoQueryDevicePowerDown(
+FdoDispatchQueryDevicePowerDown(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
@@ -5094,14 +5401,15 @@ FdoQueryDevicePowerDown(
 
     ASSERT3U(DeviceState, >,  __FdoGetDevicePowerState(Fdo));
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    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;
 }
 
 static NTSTATUS
-FdoQueryDevicePower(
+FdoDispatchQueryDevicePower(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
@@ -5119,18 +5427,16 @@ FdoQueryDevicePower(
           DevicePowerStateName(DeviceState), 
           PowerActionName(PowerAction));
 
-    ASSERT3U(PowerAction, <,  PowerActionShutdown);
-
     if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
 
         goto done;
     }
 
     status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ?
-             FdoQueryDevicePowerUp(Fdo, Irp) :
-             FdoQueryDevicePowerDown(Fdo, Irp);
+             FdoDispatchQueryDevicePowerUp(Fdo, Irp) :
+             FdoDispatchQueryDevicePowerDown(Fdo, Irp);
 
 done:
     Trace("<==== (%s:%s)(%08x)\n",
@@ -5140,10 +5446,35 @@ done:
     return status;
 }
 
+
+static NTSTATUS
+FdoRequestQueryDevicePower(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  DEVICE_POWER_STATE          DeviceState,
+    IN  PREQUEST_POWER_COMPLETE     CompletionFunction,
+    IN  PVOID                       Context
+    )
+{
+    POWER_STATE             PowerState;
+    NTSTATUS                status;
+
+    Trace("%s\n", DevicePowerStateName(DeviceState));
+
+    PowerState.DeviceState = DeviceState;
+
+    status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+                               IRP_MN_QUERY_POWER,
+                               PowerState,
+                               CompletionFunction,
+                               Context,
+                               NULL);
+    return status;
+}
+
 __drv_functionClass(REQUEST_POWER_COMPLETE)
 __drv_sameIRQL
 VOID
-FdoRequestQueryDevicePowerCompletion(
+FdoCompleteQuerySystemPowerUp2(
     IN  PDEVICE_OBJECT      DeviceObject,
     IN  UCHAR               MinorFunction,
     IN  POWER_STATE         PowerState,
@@ -5151,83 +5482,121 @@ FdoRequestQueryDevicePowerCompletion(
     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));
-
-    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+    if (!NT_SUCCESS(IoStatus->Status))
+        Irp->IoStatus.Status = IoStatus->Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 }
 
-__drv_requiresIRQL(PASSIVE_LEVEL)
-static VOID
-FdoRequestQueryDevicePower(
-    IN  PXENBUS_FDO         Fdo,
-    IN  DEVICE_POWER_STATE  DeviceState
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
+static NTSTATUS
+FdoCompleteQuerySystemPowerUp(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
+    IN  PVOID           Context
     )
 {
-    POWER_STATE             PowerState;
-    KEVENT                  Event;
-    NTSTATUS                status;
+    PXENBUS_FDO     Fdo = (PXENBUS_FDO) Context;
+    PIO_STACK_LOCATION  StackLocation;
+    SYSTEM_POWER_STATE  SystemState;
+    DEVICE_POWER_STATE  DeviceState;
+    NTSTATUS            status;
 
-    Trace("%s\n", DevicePowerStateName(DeviceState));
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    /* IRP marked as pending on dispatch path. */
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    BUG_ON(StackLocation->DeviceObject != Fdo->Dx->DeviceObject);
+    SystemState = StackLocation->Parameters.Power.State.SystemState;
+    DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+    status = FdoRequestQueryDevicePower(Fdo, DeviceState, 
FdoCompleteQuerySystemPowerUp2, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    PowerState.DeviceState = DeviceState;
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    goto done;
 
-    status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
-                               IRP_MN_QUERY_POWER,
-                               PowerState,
-                               FdoRequestQueryDevicePowerCompletion,
-                               &Event,
-                               NULL);
-    ASSERT(NT_SUCCESS(status));
+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;
 
-    (VOID) KeWaitForSingleObject(&Event,
-                                 Executive,
-                                 KernelMode,
-                                 FALSE,
-                                 NULL);
+done:
+    /* Will later complete the IRP (which is marked pending, in 2nd level comp 
routine.)*/
+        return STATUS_MORE_PROCESSING_REQUIRED;
 }
 
 static NTSTATUS
-FdoQuerySystemPowerUp(
+FdoDispatchQuerySystemPowerUp(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
-
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    DEVICE_POWER_STATE  DeviceState;
     NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    BUG_ON(StackLocation->DeviceObject != Fdo->Dx->DeviceObject);
     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,
+                           FdoCompleteQuerySystemPowerUp,
+                           Fdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+    status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    return STATUS_PENDING;
+}
 
-    DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+VOID
+FdoDispatchQuerySystemPowerDown2(
+    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;
+    PXENBUS_DX          Dx = (PXENBUS_DX)UpperDeviceObject->DeviceExtension;
+    PXENBUS_FDO         Fdo = Dx->Fdo;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(MinorFunction);
+    UNREFERENCED_PARAMETER(PowerState);
 
-    FdoRequestQueryDevicePower(Fdo, DeviceState);
+    if (!NT_SUCCESS(IoStatus->Status))
+        goto fail1;
 
-done:
+    IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended. */
+    IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    goto done;
+
+fail1:
+    Error("fail1 (%08x)\n", IoStatus->Status);
+    Irp->IoStatus.Status = IoStatus->Status;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-    return status;
+done:
+    ;
 }
 
 static NTSTATUS
-FdoQuerySystemPowerDown(
+FdoDispatchQuerySystemPowerDown(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
@@ -5238,22 +5607,32 @@ FdoQuerySystemPowerDown(
     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];
 
-    FdoRequestQueryDevicePower(Fdo, DeviceState);
+    status = FdoRequestQueryDevicePower(Fdo, DeviceState, 
FdoDispatchQuerySystemPowerDown2, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+        IoMarkIrpPending(Irp);
+        status = STATUS_PENDING;
+    goto done;
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+fail1:
+    Error("fail1 (%08x)\n", status);
+        Irp->IoStatus.Status = status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
+done:
     return status;
 }
 
 static NTSTATUS
-FdoQuerySystemPower(
+FdoDispatchQuerySystemPower(
     IN  PXENBUS_FDO     Fdo,
     IN  PIRP            Irp
     )
@@ -5271,18 +5650,15 @@ FdoQuerySystemPower(
           SystemPowerStateName(SystemState), 
           PowerActionName(PowerAction));
 
-    ASSERT3U(PowerAction, <,  PowerActionShutdown);
-
     if (SystemState == __FdoGetSystemPowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
         goto done;
     }
 
     status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?
-             FdoQuerySystemPowerUp(Fdo, Irp) :
-             FdoQuerySystemPowerDown(Fdo, Irp);
+             FdoDispatchQuerySystemPowerUp(Fdo, Irp) :
+             FdoDispatchQuerySystemPowerDown(Fdo, Irp);
 
 done:
     Trace("<==== (%s:%s)(%08x)\n",
@@ -5294,117 +5670,57 @@ done:
 }
 
 static NTSTATUS
-FdoDevicePower(
-    IN  PXENBUS_THREAD  Self,
-    IN  PVOID           Context
+FdoDispatchDevicePower(
+    IN  PXENBUS_FDO  Fdo,
+    IN  PIRP         Irp
     )
 {
-    PXENBUS_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();
-
-        StackLocation = IoGetCurrentIrpStackLocation(Irp);
-        MinorFunction = StackLocation->MinorFunction;
+        NTSTATUS status;
+        PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
 
         switch (StackLocation->MinorFunction) {
         case IRP_MN_SET_POWER:
-            (VOID) FdoSetDevicePower(Fdo, Irp);
+            status = FdoDispatchSetDevicePower(Fdo, Irp);
             break;
 
         case IRP_MN_QUERY_POWER:
-            (VOID) FdoQueryDevicePower(Fdo, Irp);
+            status = FdoDispatchQueryDevicePower(Fdo, Irp);
             break;
 
         default:
             ASSERT(FALSE);
+            IoSkipCurrentIrpStackLocation(Irp);
+            status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
             break;
         }
-    }
-
-    return STATUS_SUCCESS;
+        return status;
 }
 
 static NTSTATUS
-FdoSystemPower(
-    IN  PXENBUS_THREAD  Self,
-    IN  PVOID           Context
+FdoDispatchSystemPower(
+    IN  PXENBUS_FDO  Fdo,
+    IN  PIRP         Irp
     )
 {
-    PXENBUS_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);
-        }
+    NTSTATUS status;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
 
-        if (ThreadIsAlerted(Self))
-            break;
-
-        Irp = Fdo->SystemPowerIrp;
-
-        if (Irp == NULL)
-            continue;
-
-        Fdo->SystemPowerIrp = NULL;
-        KeMemoryBarrier();
-
-        StackLocation = IoGetCurrentIrpStackLocation(Irp);
-        MinorFunction = StackLocation->MinorFunction;
-
-        switch (StackLocation->MinorFunction) {
-        case IRP_MN_SET_POWER:
-            (VOID) FdoSetSystemPower(Fdo, Irp);
-            break;
+    switch (StackLocation->MinorFunction) {
+    case IRP_MN_SET_POWER:
+        status = FdoDispatchSetSystemPower(Fdo, Irp);
+        break;
 
-        case IRP_MN_QUERY_POWER:
-            (VOID) FdoQuerySystemPower(Fdo, Irp);
-            break;
+    case IRP_MN_QUERY_POWER:
+        status = FdoDispatchQuerySystemPower(Fdo, Irp);
+        break;
 
-        default:
-            ASSERT(FALSE);
-            break;
-        }
+    default:
+        ASSERT(FALSE);
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+        break;
     }
-
-    return STATUS_SUCCESS;
+    return status;
 }
 
 static NTSTATUS
@@ -5433,36 +5749,13 @@ FdoDispatchPower(
     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 = FdoDispatchDevicePower(Fdo, Irp);
         break;
 
     case SystemPowerState:
-        IoMarkIrpPending(Irp);
-
-        ASSERT3P(Fdo->SystemPowerIrp, ==, NULL);
-        Fdo->SystemPowerIrp = Irp;
-        KeMemoryBarrier();
-
-        ThreadWake(Fdo->SystemPowerThread);
-
-        status = STATUS_PENDING;
+        status = FdoDispatchSystemPower(Fdo, Irp);
         break;
 
     default:
@@ -5475,6 +5768,7 @@ done:
     return status;
 }
 
+
 static NTSTATUS
 FdoDispatchDefault(
     IN  PXENBUS_FDO Fdo,
@@ -5822,87 +6116,79 @@ FdoCreate(
     Fdo->LowerDeviceObject = IoAttachDeviceToDeviceStack(FunctionDeviceObject,
                                                          PhysicalDeviceObject);
 
-    status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    status = ThreadCreate(FdoDevicePower, Fdo, &Fdo->DevicePowerThread);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
     status = FdoAcquireLowerBusInterface(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail3;
 
     if (FdoGetBusData(Fdo,
                       PCI_WHICHSPACE_CONFIG,
                       &Header,
                       0,
                       sizeof (PCI_COMMON_HEADER)) == 0)
-        goto fail6;
+        goto fail4;
 
     status = __FdoSetVendorName(Fdo,
                                 Header.VendorID,
                                 Header.DeviceID);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail5;
 
     __FdoSetName(Fdo);
 
     status = FdoSetActive(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail6;
 
     if (!__FdoIsActive(Fdo))
         goto done;
 
     status = __FdoAllocateBuffer(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail7;
 
     status = DebugInitialize(Fdo, &Fdo->DebugContext);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail8;
 
     status = SuspendInitialize(Fdo, &Fdo->SuspendContext);
     if (!NT_SUCCESS(status))
-        goto fail11;
+        goto fail9;
 
     status = SharedInfoInitialize(Fdo, &Fdo->SharedInfoContext);
     if (!NT_SUCCESS(status))
-        goto fail12;
+        goto fail10;
 
     status = EvtchnInitialize(Fdo, &Fdo->EvtchnContext);
     if (!NT_SUCCESS(status))
-        goto fail13;
+        goto fail11;
 
     status = RangeSetInitialize(Fdo, &Fdo->RangeSetContext);
     if (!NT_SUCCESS(status))
-        goto fail14;
+        goto fail12;
 
     status = CacheInitialize(Fdo, &Fdo->CacheContext);
     if (!NT_SUCCESS(status))
-        goto fail15;
+        goto fail13;
 
     status = GnttabInitialize(Fdo, &Fdo->GnttabContext);
     if (!NT_SUCCESS(status))
-        goto fail16;
+        goto fail14;
 
     status = StoreInitialize(Fdo, &Fdo->StoreContext);
     if (!NT_SUCCESS(status))
-        goto fail17;
+        goto fail15;
 
     status = ConsoleInitialize(Fdo, &Fdo->ConsoleContext);
     if (!NT_SUCCESS(status))
-        goto fail18;
+        goto fail16;
 
     status = UnplugInitialize(Fdo, &Fdo->UnplugContext);
     if (!NT_SUCCESS(status))
-        goto fail19;
+        goto fail17;
 
     status = FdoBalloonInitialize(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail20;
+        goto fail18;
 
     status = DebugGetInterface(__FdoGetDebugContext(Fdo),
                                XENBUS_DEBUG_INTERFACE_VERSION_MAX,
@@ -5952,6 +6238,20 @@ FdoCreate(
                                  sizeof (Fdo->BalloonInterface));
     ASSERT(NT_SUCCESS(status));
 
+    Fdo->FdoSPowerWorkItem = IoAllocateWorkItem(FunctionDeviceObject);
+    if (Fdo->FdoSPowerWorkItem == NULL)
+        goto fail19;
+
+    Fdo->FdoSPowerContext.FdoOrPdo = Fdo;
+    Fdo->FdoSPowerContext.Irp = NULL;
+
+    Fdo->FdoDPowerWorkItem = IoAllocateWorkItem(FunctionDeviceObject);
+    if (Fdo->FdoDPowerWorkItem == NULL)
+        goto fail20;
+
+    Fdo->FdoDPowerContext.FdoOrPdo = Fdo;
+    Fdo->FdoDPowerContext.Irp = NULL;
+
 done:
     InitializeMutex(&Fdo->Mutex);
     InitializeListHead(&Fdo->List);
@@ -5975,105 +6275,122 @@ done:
 
 fail20:
     Error("fail20\n");
-
-    UnplugTeardown(Fdo->UnplugContext);
-    Fdo->UnplugContext = NULL;
+    IoFreeWorkItem(Fdo->FdoSPowerWorkItem);
+    Fdo->FdoSPowerWorkItem = NULL;
+    RtlZeroMemory(&Fdo->FdoSPowerContext, sizeof(Fdo->FdoSPowerContext));
 
 fail19:
     Error("fail19\n");
+    RtlZeroMemory(&Fdo->BalloonInterface,
+                    sizeof (XENBUS_BALLOON_INTERFACE));
 
-    ConsoleTeardown(Fdo->ConsoleContext);
-    Fdo->ConsoleContext = NULL;
+    RtlZeroMemory(&Fdo->ConsoleInterface,
+                    sizeof (XENBUS_CONSOLE_INTERFACE));
+
+    RtlZeroMemory(&Fdo->StoreInterface,
+                    sizeof (XENBUS_STORE_INTERFACE));
+
+    RtlZeroMemory(&Fdo->RangeSetInterface,
+                    sizeof (XENBUS_RANGE_SET_INTERFACE));
+
+    RtlZeroMemory(&Fdo->EvtchnInterface,
+                    sizeof (XENBUS_EVTCHN_INTERFACE));
+
+    RtlZeroMemory(&Fdo->SuspendInterface,
+                    sizeof (XENBUS_SUSPEND_INTERFACE));
+
+    RtlZeroMemory(&Fdo->DebugInterface,
+                    sizeof (XENBUS_DEBUG_INTERFACE));
+
+    FdoBalloonTeardown(Fdo);
 
 fail18:
     Error("fail18\n");
 
-    StoreTeardown(Fdo->StoreContext);
-    Fdo->StoreContext = NULL;
+    UnplugTeardown(Fdo->UnplugContext);
+    Fdo->UnplugContext = NULL;
 
 fail17:
     Error("fail17\n");
 
-    GnttabTeardown(Fdo->GnttabContext);
-    Fdo->GnttabContext = NULL;
+    ConsoleTeardown(Fdo->ConsoleContext);
+    Fdo->ConsoleContext = NULL;
 
 fail16:
     Error("fail16\n");
 
-    CacheTeardown(Fdo->CacheContext);
-    Fdo->CacheContext = NULL;
+    StoreTeardown(Fdo->StoreContext);
+    Fdo->StoreContext = NULL;
 
 fail15:
     Error("fail15\n");
 
-    RangeSetTeardown(Fdo->RangeSetContext);
-    Fdo->RangeSetContext = NULL;
+    GnttabTeardown(Fdo->GnttabContext);
+    Fdo->GnttabContext = NULL;
 
 fail14:
     Error("fail14\n");
 
-    EvtchnTeardown(Fdo->EvtchnContext);
-    Fdo->EvtchnContext = NULL;
+    CacheTeardown(Fdo->CacheContext);
+    Fdo->CacheContext = NULL;
 
 fail13:
     Error("fail13\n");
 
-    SharedInfoTeardown(Fdo->SharedInfoContext);
-    Fdo->SharedInfoContext = NULL;
+    RangeSetTeardown(Fdo->RangeSetContext);
+    Fdo->RangeSetContext = NULL;
 
 fail12:
     Error("fail12\n");
 
-    SuspendTeardown(Fdo->SuspendContext);
-    Fdo->SuspendContext = NULL;
+    EvtchnTeardown(Fdo->EvtchnContext);
+    Fdo->EvtchnContext = NULL;
 
 fail11:
     Error("fail11\n");
 
-    DebugTeardown(Fdo->DebugContext);
-    Fdo->DebugContext = NULL;
+    SharedInfoTeardown(Fdo->SharedInfoContext);
+    Fdo->SharedInfoContext = NULL;
 
 fail10:
     Error("fail10\n");
 
-    __FdoFreeBuffer(Fdo);
+    SuspendTeardown(Fdo->SuspendContext);
+    Fdo->SuspendContext = NULL;
 
 fail9:
     Error("fail9\n");
 
-    //
-    // We don't want to call DriverClearActive() so just
-    // clear the FDO flag.
-    //
-    Fdo->Active = FALSE;
+    DebugTeardown(Fdo->DebugContext);
+    Fdo->DebugContext = NULL;
 
 fail8:
     Error("fail8\n");
 
-    RtlZeroMemory(Fdo->VendorName, MAXNAMELEN);
+    __FdoFreeBuffer(Fdo);
 
 fail7:
     Error("fail7\n");
 
+    //
+    // We don't want to call DriverClearActive() so just
+    // clear the FDO flag.
+    //
+    Fdo->Active = FALSE;
+
 fail6:
     Error("fail6\n");
 
-    FdoReleaseLowerBusInterface(Fdo);
+    RtlZeroMemory(Fdo->VendorName, MAXNAMELEN);
 
 fail5:
     Error("fail5\n");
 
-    ThreadAlert(Fdo->DevicePowerThread);
-    ThreadJoin(Fdo->DevicePowerThread);
-    Fdo->DevicePowerThread = NULL;
-    
 fail4:
     Error("fail4\n");
 
-    ThreadAlert(Fdo->SystemPowerThread);
-    ThreadJoin(Fdo->SystemPowerThread);
-    Fdo->SystemPowerThread = NULL;
-    
+    FdoReleaseLowerBusInterface(Fdo);
+
 fail3:
     Error("fail3\n");
 
@@ -6125,6 +6442,16 @@ FdoDestroy(
     RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
     RtlZeroMemory(&Fdo->Mutex, sizeof (MUTEX));
 
+    IoFreeWorkItem(Fdo->FdoSPowerWorkItem);
+    ASSERT(Fdo->FdoSPowerContext.Irp == NULL);
+    IoFreeWorkItem(Fdo->FdoDPowerWorkItem);
+    ASSERT(Fdo->FdoDPowerContext.Irp == NULL);
+
+    RtlZeroMemory(&Fdo->FdoSPowerWorkItem, sizeof(Fdo->FdoSPowerWorkItem));
+    RtlZeroMemory(&Fdo->FdoDPowerWorkItem, sizeof(Fdo->FdoDPowerWorkItem));
+    RtlZeroMemory(&Fdo->FdoSPowerContext, sizeof(Fdo->FdoSPowerContext));
+    RtlZeroMemory(&Fdo->FdoDPowerContext, sizeof(Fdo->FdoDPowerContext));
+
     if (__FdoIsActive(Fdo)) {
         RtlZeroMemory(&Fdo->BalloonInterface,
                       sizeof (XENBUS_BALLOON_INTERFACE));
@@ -6188,14 +6515,6 @@ FdoDestroy(
 
     FdoReleaseLowerBusInterface(Fdo);
 
-    ThreadAlert(Fdo->DevicePowerThread);
-    ThreadJoin(Fdo->DevicePowerThread);
-    Fdo->DevicePowerThread = NULL;
-
-    ThreadAlert(Fdo->SystemPowerThread);
-    ThreadJoin(Fdo->SystemPowerThread);
-    Fdo->SystemPowerThread = NULL;
-
     IoDetachDevice(Fdo->LowerDeviceObject);
 
     RtlZeroMemory(&Fdo->LowerDeviceCapabilities, sizeof (DEVICE_CAPABILITIES));
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index efd29dc..1ae2f07 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -49,6 +49,7 @@
 #include "util.h"
 #include "version.h"
 #include "revision.h"
+#include "types.h"
 
 #define PDO_TAG 'ODP'
 
@@ -57,11 +58,6 @@
 struct _XENBUS_PDO {
     PXENBUS_DX                  Dx;
 
-    PXENBUS_THREAD              SystemPowerThread;
-    PIRP                        SystemPowerIrp;
-    PXENBUS_THREAD              DevicePowerThread;
-    PIRP                        DevicePowerIrp;
-
     PXENBUS_FDO                 Fdo;
     BOOLEAN                     Missing;
     const CHAR                  *Reason;
@@ -73,6 +69,11 @@ struct _XENBUS_PDO {
 
     XENBUS_SUSPEND_INTERFACE    SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK    SuspendCallbackLate;
+
+    PIO_WORKITEM                  PdoSPowerWorkItem;
+    XENBUS_POWER_WORKITEM_CONTEXT PdoSPowerContext;
+    PIO_WORKITEM                  PdoDPowerWorkItem;
+    XENBUS_POWER_WORKITEM_CONTEXT PdoDPowerContext;
 };
 
 static FORCEINLINE PVOID
@@ -1700,26 +1701,29 @@ PdoDispatchPnp(
     return status;
 }
 
-static NTSTATUS
-PdoSetDevicePower(
-    IN  PXENBUS_PDO     Pdo,
-    IN  PIRP            Irp
-    )
+VOID _PdoDStatePowerWorker(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PVOID Context
+  )
 {
+    PXENBUS_POWER_WORKITEM_CONTEXT PowerContext = 
(PXENBUS_POWER_WORKITEM_CONTEXT)Context;
+    PXENBUS_PDO         Pdo = (PXENBUS_PDO) PowerContext->FdoOrPdo;
+    PIRP                Irp;
+    NTSTATUS            status;
     PIO_STACK_LOCATION  StackLocation;
     DEVICE_POWER_STATE  DeviceState;
     POWER_ACTION        PowerAction;
 
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Irp = InterlockedExchangePointer(&PowerContext->Irp, NULL);
+    ASSERT(Irp != NULL);
+
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("====> (%s:%s)\n",
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction));
-
-    ASSERT3U(PowerAction, <, PowerActionShutdown);
-
+    status = STATUS_SUCCESS;
     if (__PdoGetDevicePowerState(Pdo) > DeviceState) {
         Trace("%s: POWERING UP: %s -> %s\n",
               __PdoGetName(Pdo),
@@ -1727,7 +1731,7 @@ PdoSetDevicePower(
               DevicePowerStateName(DeviceState));
 
         ASSERT3U(DeviceState, ==, PowerDeviceD0);
-        PdoD3ToD0(Pdo);
+        status = PdoD3ToD0(Pdo);
     } else if (__PdoGetDevicePowerState(Pdo) < DeviceState) {
         Trace("%s: POWERING DOWN: %s -> %s\n",
               __PdoGetName(Pdo),
@@ -1738,76 +1742,81 @@ PdoSetDevicePower(
         PdoD0ToD3(Pdo);
     }
 
+    if(NT_SUCCESS(status))
+        goto done;
+
+    Error("fail1 (%08x)\n", status);
+    /* TODO - Consider cycling device power at some later point?
+       Need PPO to retry SIRP -> DIRP */
+
+done:
+    /* Cannot fail the IRP at this point, keep going. */
     Irp->IoStatus.Status = STATUS_SUCCESS;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
     Trace("<==== (%s:%s)\n",
           DevicePowerStateName(DeviceState), 
           PowerActionName(PowerAction));
-
-    return STATUS_SUCCESS;
 }
 
-static NTSTATUS
-PdoDevicePower(
-    IN  PXENBUS_THREAD  Self,
-    IN  PVOID           Context
-    )
+VOID PdoDStatePowerWorker(
+    IN PXENBUS_PDO       Pdo,
+    IN PIRP              Irp
+)
 {
-    PXENBUS_PDO         Pdo = Context;
-    PKEVENT             Event;
-
-    Event = ThreadGetEvent(Self);
-
-    for (;;) {
-        PIRP    Irp;
-
-        if (Pdo->DevicePowerIrp == NULL) {
-            (VOID) KeWaitForSingleObject(Event,
-                                         Executive,
-                                         KernelMode,
-                                         FALSE,
-                                         NULL);
-            KeClearEvent(Event);
-        }
-
-        if (ThreadIsAlerted(Self))
-            break;
-
-        Irp = Pdo->DevicePowerIrp;
+    PVOID Exchange;
 
-        if (Irp == NULL)
-            continue;
+    ASSERT(Pdo->PdoDPowerContext.FdoOrPdo == Pdo);
+    Exchange = InterlockedExchangePointer(&Pdo->PdoDPowerContext.Irp, Irp);
+    ASSERT(Exchange == NULL);
 
-        Pdo->DevicePowerIrp = NULL;
-        KeMemoryBarrier();
-
-        (VOID) PdoSetDevicePower(Pdo, Irp);
-    }
-
-    return STATUS_SUCCESS;
+    IoQueueWorkItem(Pdo->PdoDPowerWorkItem,
+                    _PdoDStatePowerWorker,
+                    DelayedWorkQueue,
+                    &Pdo->PdoDPowerContext);
 }
 
 static NTSTATUS
-PdoSetSystemPower(
+PdoDispatchSetDevicePower(
     IN  PXENBUS_PDO     Pdo,
     IN  PIRP            Irp
     )
 {
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    DEVICE_POWER_STATE DeviceState = 
StackLocation->Parameters.Power.State.DeviceState;
+    POWER_ACTION PowerAction = StackLocation->Parameters.Power.ShutdownType;
+
+    Trace("====> (%s:%s)\n",
+          DevicePowerStateName(DeviceState),
+          PowerActionName(PowerAction));
+
+    IoMarkIrpPending(Irp);
+    PdoDStatePowerWorker(Pdo, Irp);
+    return STATUS_PENDING;
+}
+
+
+VOID _PdoSStatePowerWorker(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PVOID Context
+  )
+{
+    PXENBUS_POWER_WORKITEM_CONTEXT PowerContext = 
(PXENBUS_POWER_WORKITEM_CONTEXT)Context;
+    PXENBUS_PDO         Pdo = (PXENBUS_PDO) PowerContext->FdoOrPdo;
+    PIRP                Irp;
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
     POWER_ACTION        PowerAction;
 
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Irp = InterlockedExchangePointer(&PowerContext->Irp, NULL);
+    ASSERT(Irp != NULL);
+
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("====> (%s:%s)\n",
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction));
-
-    ASSERT3U(PowerAction, <, PowerActionShutdown);
-
     if (__PdoGetSystemPowerState(Pdo) > SystemState) {
         if (SystemState < PowerSystemHibernate &&
             __PdoGetSystemPowerState(Pdo) >= PowerSystemHibernate) {
@@ -1841,52 +1850,50 @@ PdoSetSystemPower(
     Trace("<==== (%s:%s)\n",
           SystemPowerStateName(SystemState), 
           PowerActionName(PowerAction));
-
-    return STATUS_SUCCESS;
 }
 
-static NTSTATUS
-PdoSystemPower(
-    IN  PXENBUS_THREAD  Self,
-    IN  PVOID           Context
-    )
+VOID PdoSStatePowerWorker(
+    IN PXENBUS_PDO       Pdo,
+    IN PIRP              Irp
+)
 {
-    PXENBUS_PDO         Pdo = Context;
-    PKEVENT             Event;
-
-    Event = ThreadGetEvent(Self);
+    PVOID Exchange;
 
-    for (;;) {
-        PIRP    Irp;
+    ASSERT(Pdo->PdoSPowerContext.FdoOrPdo == Pdo);
+    Exchange = InterlockedExchangePointer(&Pdo->PdoSPowerContext.Irp, Irp);
+    ASSERT(Exchange == NULL);
 
-        if (Pdo->SystemPowerIrp == NULL) {
-            (VOID) KeWaitForSingleObject(Event,
-                                         Executive,
-                                         KernelMode,
-                                         FALSE,
-                                         NULL);
-            KeClearEvent(Event);
-        }
-
-        if (ThreadIsAlerted(Self))
-            break;
-
-        Irp = Pdo->SystemPowerIrp;
+    IoQueueWorkItem(Pdo->PdoSPowerWorkItem,
+                    _PdoSStatePowerWorker,
+                    DelayedWorkQueue,
+                    &Pdo->PdoSPowerContext);
+}
 
-        if (Irp == NULL)
-            continue;
+static NTSTATUS
+PdoDispatchSetSystemPower(
+    IN  PXENBUS_PDO     Pdo,
+    IN  PIRP            Irp
+    )
+{
+    PIO_STACK_LOCATION  StackLocation;
+    SYSTEM_POWER_STATE  SystemState;
+    POWER_ACTION        PowerAction;
 
-        Pdo->SystemPowerIrp = NULL;
-        KeMemoryBarrier();
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    SystemState = StackLocation->Parameters.Power.State.SystemState;
+    PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-        (VOID) PdoSetSystemPower(Pdo, Irp);
-    }
+    Trace("====> (%s:%s)\n",
+          SystemPowerStateName(SystemState),
+          PowerActionName(PowerAction));
 
-    return STATUS_SUCCESS;
+    IoMarkIrpPending(Irp);
+    PdoSStatePowerWorker(Pdo, Irp);
+    return STATUS_PENDING;
 }
 
 static NTSTATUS
-PdoSetPower(
+PdoDispatchSetPower(
     IN  PXENBUS_PDO     Pdo,
     IN  PIRP            Irp
     )
@@ -1900,38 +1907,13 @@ PdoSetPower(
     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 = PdoDispatchSetDevicePower(Pdo, Irp);
         break;
 
     case SystemPowerState:
-        IoMarkIrpPending(Irp);
-
-        ASSERT3P(Pdo->SystemPowerIrp, ==, NULL);
-        Pdo->SystemPowerIrp = Irp;
-        KeMemoryBarrier();
-
-        ThreadWake(Pdo->SystemPowerThread);
-
-        status = STATUS_PENDING;
+        status = PdoDispatchSetSystemPower(Pdo, Irp);
         break;
 
     default:
@@ -1940,26 +1922,20 @@ PdoSetPower(
         break;
     }
 
-done:
     return status;
 }
 
 static NTSTATUS
-PdoQueryPower(
+PdoDispatchQueryPower(
     IN  PXENBUS_PDO Pdo,
     IN  PIRP        Irp
     )
 {
-    NTSTATUS        status;
-
     UNREFERENCED_PARAMETER(Pdo);
 
-    status = STATUS_SUCCESS;
-
-    Irp->IoStatus.Status = status;
+    Irp->IoStatus.Status = STATUS_SUCCESS;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
+    return STATUS_SUCCESS;
 }
 
 static NTSTATUS
@@ -1977,14 +1953,15 @@ PdoDispatchPower(
 
     switch (StackLocation->MinorFunction) {
     case IRP_MN_SET_POWER:
-        status = PdoSetPower(Pdo, Irp);
+        status = PdoDispatchSetPower(Pdo, Irp);
         break;
 
     case IRP_MN_QUERY_POWER:
-        status = PdoQueryPower(Pdo, Irp);
+        status = PdoDispatchQueryPower(Pdo, Irp);
         break;
 
     default:
+        /* TODO - Always complete with status success?? */
         status = Irp->IoStatus.Status;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         break;
@@ -2098,21 +2075,13 @@ PdoCreate(
     Pdo->Dx = Dx;
     Pdo->Fdo = Fdo;
 
-    status = ThreadCreate(PdoSystemPower, Pdo, &Pdo->SystemPowerThread);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    status = ThreadCreate(PdoDevicePower, Pdo, &Pdo->DevicePowerThread);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
     __PdoSetName(Pdo, Name);
     __PdoSetRemovable(Pdo);
     __PdoSetEjectable(Pdo);
 
     status = BusInitialize(Pdo, &Pdo->BusInterface);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail3;
 
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
@@ -2127,6 +2096,20 @@ PdoCreate(
 
     PdoDumpRevisions(Pdo);
 
+    Pdo->PdoSPowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject);
+    if (Pdo->PdoSPowerWorkItem == NULL)
+        goto fail4;
+
+    Pdo->PdoSPowerContext.FdoOrPdo = Pdo;
+    Pdo->PdoSPowerContext.Irp = NULL;
+
+    Pdo->PdoDPowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject);
+    if (Pdo->PdoDPowerWorkItem == NULL)
+        goto fail5;
+
+    Pdo->PdoDPowerContext.FdoOrPdo = Pdo;
+    Pdo->PdoDPowerContext.Irp = NULL;
+
     Dx->Pdo = Pdo;
     PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
 
@@ -2137,23 +2120,21 @@ PdoCreate(
 fail5:
     Error("fail5\n");
 
-    Pdo->Ejectable = FALSE;
-    Pdo->Removable = FALSE;
-
-    ThreadAlert(Pdo->DevicePowerThread);
-    ThreadJoin(Pdo->DevicePowerThread);
-    Pdo->DevicePowerThread = NULL;
+    IoFreeWorkItem(Pdo->PdoSPowerWorkItem);
+    Pdo->PdoSPowerWorkItem = NULL;
+    RtlZeroMemory(&Pdo->PdoSPowerContext, sizeof(Pdo->PdoSPowerContext));
 
 fail4:
     Error("fail4\n");
 
-    ThreadAlert(Pdo->SystemPowerThread);
-    ThreadJoin(Pdo->SystemPowerThread);
-    Pdo->SystemPowerThread = NULL;
+    RtlZeroMemory(&Pdo->SuspendInterface,
+                  sizeof (XENBUS_SUSPEND_INTERFACE));
 
 fail3:
     Error("fail3\n");
 
+    Pdo->Ejectable = FALSE;
+    Pdo->Removable = FALSE;
     Pdo->Fdo = NULL;
     Pdo->Dx = NULL;
 
@@ -2187,6 +2168,16 @@ PdoDestroy(
 
     FdoRemovePhysicalDeviceObject(Fdo, Pdo);
 
+    IoFreeWorkItem(Pdo->PdoSPowerWorkItem);
+    ASSERT(Pdo->PdoSPowerContext.Irp == NULL);
+    IoFreeWorkItem(Pdo->PdoDPowerWorkItem);
+    ASSERT(Pdo->PdoDPowerContext.Irp == NULL);
+
+    RtlZeroMemory(&Pdo->PdoSPowerWorkItem, sizeof(Pdo->PdoSPowerWorkItem));
+    RtlZeroMemory(&Pdo->PdoDPowerWorkItem, sizeof(Pdo->PdoDPowerWorkItem));
+    RtlZeroMemory(&Pdo->PdoSPowerContext, sizeof(Pdo->PdoSPowerContext));
+    RtlZeroMemory(&Pdo->PdoDPowerContext, sizeof(Pdo->PdoDPowerContext));
+
     Info("%p (%s) (%s)\n",
          PhysicalDeviceObject,
          __PdoGetName(Pdo),
@@ -2202,15 +2193,6 @@ PdoDestroy(
 
     Pdo->Ejectable = FALSE;
     Pdo->Removable = FALSE;
-
-    ThreadAlert(Pdo->DevicePowerThread);
-    ThreadJoin(Pdo->DevicePowerThread);
-    Pdo->DevicePowerThread = NULL;
-    
-    ThreadAlert(Pdo->SystemPowerThread);
-    ThreadJoin(Pdo->SystemPowerThread);
-    Pdo->SystemPowerThread = NULL;
-
     Pdo->Fdo = NULL;
     Pdo->Dx = NULL;
 
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 5ffea1f..cf31e3b 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -40,9 +40,13 @@
 #include "thread.h"
 #include "fdo.h"
 #include "dbg_print.h"
-#include "assert.h"
 #include "util.h"
 
+//Temp workaround for CA-371783 testing checked builds.
+#undef ASSERT
+#define ASSERT(x) ((void)0)
+
+
 extern ULONG
 NTAPI
 RtlRandomEx (
diff --git a/src/xenbus/types.h b/src/xenbus/types.h
index 0f08627..8f84860 100644
--- a/src/xenbus/types.h
+++ b/src/xenbus/types.h
@@ -50,4 +50,9 @@ typedef enum _DEVICE_PNP_STATE {
     Deleted
 } DEVICE_PNP_STATE, *PDEVICE_PNP_STATE;
 
+typedef struct _XENBUS_POWER_WORKITEM_CONTEXT {
+    PVOID                           FdoOrPdo;
+    PIRP                            Irp;
+} XENBUS_POWER_WORKITEM_CONTEXT, *PXENBUS_POWER_WORKITEM_CONTEXT;
+
 #endif  // _XENBUS_TYPES_H
diff --git a/src/xenfilt/fdo.c b/src/xenfilt/fdo.c
index 63fa7b3..1e4affa 100644
--- a/src/xenfilt/fdo.c
+++ b/src/xenfilt/fdo.c
@@ -59,11 +59,6 @@ struct _XENFILT_FDO {
     PDEVICE_OBJECT                  PhysicalDeviceObject;
     CHAR                            Name[MAXNAMELEN];
 
-    PXENFILT_THREAD                 SystemPowerThread;
-    PIRP                            SystemPowerIrp;
-    PXENFILT_THREAD                 DevicePowerThread;
-    PIRP                            DevicePowerIrp;
-
     MUTEX                           Mutex;
     LIST_ENTRY                      List;
     ULONG                           References;
@@ -1077,81 +1072,82 @@ fail1:
     return status;
 }
 
+
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
 static NTSTATUS
-FdoSetDevicePowerUp(
-    IN  PXENFILT_FDO    Fdo,
-    IN  PIRP            Irp
+FdoCompleteSetDevicePowerUp(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
+    IN  PVOID           Context
     )
 {
+    PXENFILT_FDO     Fdo = (PXENFILT_FDO) Context;
     PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
     POWER_STATE         PowerState;
-    NTSTATUS            status;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-
-    ASSERT3U(DeviceState, <,  __FdoGetDevicePowerState(Fdo));
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    PowerState = StackLocation->Parameters.Power.State;
 
-    Trace("%s: %s -> %s\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(__FdoGetDevicePowerState(Fdo)),
-          DevicePowerStateName(DeviceState));
+    if (Irp->PendingReturned) {
+        IoMarkIrpPending(Irp);
+    }
 
-    PowerState.DeviceState = DeviceState;
+    __FdoSetDevicePowerState(Fdo, PowerState.DeviceState);
     PoSetPowerState(Fdo->Dx->DeviceObject,
                     DevicePowerState,
                     PowerState);
 
-    __FdoSetDevicePowerState(Fdo, DeviceState);
+    return STATUS_CONTINUE_COMPLETION;
+}
 
-done:
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+static FORCEINLINE NTSTATUS
+FdoDispatchSetDevicePowerUp(
+    IN  PXENFILT_FDO     Fdo,
+    IN  PIRP            Irp
+    )
+{
+    PIO_STACK_LOCATION  StackLocation;
 
-    return status;
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           FdoCompleteSetDevicePowerUp,
+                           Fdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+    return IoCallDriver(Fdo->LowerDeviceObject, Irp);
 }
 
-static NTSTATUS
-FdoSetDevicePowerDown(
-    IN  PXENFILT_FDO    Fdo,
+static FORCEINLINE NTSTATUS
+FdoDispatchSetDevicePowerDown(
+    IN  PXENFILT_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
     POWER_STATE         PowerState;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
+    PowerState = StackLocation->Parameters.Power.State;
 
-    ASSERT3U(DeviceState, >,  __FdoGetDevicePowerState(Fdo));
-
-    Trace("%s: %s -> %s\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(__FdoGetDevicePowerState(Fdo)),
-          DevicePowerStateName(DeviceState));
-
-    PowerState.DeviceState = DeviceState;
+    __FdoSetDevicePowerState(Fdo, PowerState.DeviceState);
     PoSetPowerState(Fdo->Dx->DeviceObject,
                     DevicePowerState,
                     PowerState);
 
-    __FdoSetDevicePowerState(Fdo, DeviceState);
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
+    IoSkipCurrentIrpStackLocation(Irp);
+    return IoCallDriver(Fdo->LowerDeviceObject, Irp);
 }
 
-static NTSTATUS
-FdoSetDevicePower(
-    IN  PXENFILT_FDO    Fdo,
+/* IRQL argnostic code, just mark power states.*/
+static FORCEINLINE NTSTATUS
+FdoDispatchSetDevicePower(
+    IN  PXENFILT_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
@@ -1164,419 +1160,220 @@ FdoSetDevicePower(
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("%s: ====> (%s:%s)\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(DeviceState), 
+    /* See if we can get away without pending the IRP in a filter
+       driver. */
+
+    Trace("====> (%s:%s)\n",
+          DevicePowerStateName(DeviceState),
           PowerActionName(PowerAction));
 
-    if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
+    if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
         goto done;
     }
 
-    status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ?
-             FdoSetDevicePowerUp(Fdo, Irp) :
-             FdoSetDevicePowerDown(Fdo, Irp);
+    if (DeviceState < __FdoGetDevicePowerState(Fdo)) {
+        status = FdoDispatchSetDevicePowerUp(Fdo, Irp);
+    } else {
+        status = FdoDispatchSetDevicePowerDown(Fdo, Irp);
+    }
 
 done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction),
-          status);
+    Trace("<==== (%s:%s)\n",
+          DevicePowerStateName(DeviceState),
+          PowerActionName(PowerAction));
+
     return status;
 }
 
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
 static NTSTATUS
-FdoSetSystemPowerUp(
-    IN  PXENFILT_FDO    Fdo,
-    IN  PIRP            Irp
+FdoCompleteSetSystemPowerUp(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
+    IN  PVOID           Context
     )
 {
+    PXENFILT_FDO     Fdo = (PXENFILT_FDO) Context;
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
 
-    ASSERT3U(SystemState, <,  __FdoGetSystemPowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
-
-    Trace("%s: %s -> %s\n",
-          __FdoGetName(Fdo),
-          SystemPowerStateName(__FdoGetSystemPowerState(Fdo)),
-          SystemPowerStateName(SystemState));
+    if (Irp->PendingReturned) {
+        IoMarkIrpPending(Irp);
+    }
 
     __FdoSetSystemPowerState(Fdo, SystemState);
 
-done:
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
+    return STATUS_CONTINUE_COMPLETION;
 }
 
-static NTSTATUS
-FdoSetSystemPowerDown(
+static FORCEINLINE NTSTATUS
+FdoDispatchSetSystemPowerUp(
     IN  PXENFILT_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-
-    ASSERT3U(SystemState, >,  __FdoGetSystemPowerState(Fdo));
-
-    Trace("%s: %s -> %s\n",
-          __FdoGetName(Fdo),
-          SystemPowerStateName(__FdoGetSystemPowerState(Fdo)),
-          SystemPowerStateName(SystemState));
-
-    __FdoSetSystemPowerState(Fdo, SystemState);
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-    return status;
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           FdoCompleteSetSystemPowerUp,
+                           Fdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+    return IoCallDriver(Fdo->LowerDeviceObject, Irp);
 }
 
-static NTSTATUS
-FdoSetSystemPower(
-    IN  PXENFILT_FDO    Fdo,
+static FORCEINLINE NTSTATUS
+FdoDispatchSetSystemPowerDown(
+    IN  PXENFILT_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
-
-    Trace("%s: ====> (%s:%s)\n",
-          __FdoGetName(Fdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction));
-
-    if (SystemState == __FdoGetSystemPowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-        goto done;
-    }
 
-    status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?
-             FdoSetSystemPowerUp(Fdo, Irp) :
-             FdoSetSystemPowerDown(Fdo, Irp);
-
-done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __FdoGetName(Fdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction),
-          status);
-    return status;
-}
-
-static NTSTATUS
-FdoQueryDevicePowerUp(
-    IN  PXENFILT_FDO    Fdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-
-    ASSERT3U(DeviceState, <,  __FdoGetDevicePowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-FdoQueryDevicePowerDown(
-    IN  PXENFILT_FDO    Fdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-
-    ASSERT3U(DeviceState, >,  __FdoGetDevicePowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    __FdoSetSystemPowerState(Fdo, SystemState);
 
-    return status;
+    IoSkipCurrentIrpStackLocation(Irp);
+    return IoCallDriver(Fdo->LowerDeviceObject, Irp);
 }
 
-static NTSTATUS
-FdoQueryDevicePower(
-    IN  PXENFILT_FDO    Fdo,
+/* IRQL argnostic code, just mark power states.*/
+static FORCEINLINE NTSTATUS
+FdoDispatchSetSystemPower(
+    IN  PXENFILT_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
+    SYSTEM_POWER_STATE  SystemState;
     POWER_ACTION        PowerAction;
     NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
+    SystemState = StackLocation->Parameters.Power.State.SystemState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("%s: ====> (%s:%s)\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction));
+    /* See if we can get away without pending the IRP in a filter
+       driver. */
 
-    if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    Trace("====> (%s:%s)\n",
+          SystemPowerStateName(SystemState),
+          PowerActionName(PowerAction));
 
+    if (SystemState == __FdoGetSystemPowerState(Fdo)) {
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
         goto done;
     }
 
-    status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ?
-             FdoQueryDevicePowerUp(Fdo, Irp) :
-             FdoQueryDevicePowerDown(Fdo, Irp);
+    if (SystemState < __FdoGetSystemPowerState(Fdo)) {
+        status = FdoDispatchSetSystemPowerUp(Fdo, Irp);
+    } else {
+        status = FdoDispatchSetSystemPowerDown(Fdo, Irp);
+    }
 
 done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction),
-          status);
+    Trace("<==== (%s:%s)\n",
+          SystemPowerStateName(SystemState),
+          PowerActionName(PowerAction));
+
     return status;
 }
 
-static NTSTATUS
-FdoQuerySystemPowerUp(
+static FORCEINLINE NTSTATUS
+FdoDispatchQueryPower(
     IN  PXENFILT_FDO     Fdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
 
-    ASSERT3U(SystemState, <,  __FdoGetSystemPowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
+    /* Queries we will just pass thru, regardless of what they are.
+       Don't need to pend or set any completion routines. */
+    IoSkipCurrentIrpStackLocation(Irp);
+    return IoCallDriver(Fdo->LowerDeviceObject, Irp);
 }
 
+/* Dispatch - call down, and/or set completion, IRP not pended */
 static NTSTATUS
-FdoQuerySystemPowerDown(
-    IN  PXENFILT_FDO    Fdo,
+FdoDispatchDevicePower(
+    IN  PXENFILT_FDO   Fdo,
     IN  PIRP            Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
+    NTSTATUS status;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-
-    ASSERT3U(SystemState, >,  __FdoGetSystemPowerState(Fdo));
+    switch (StackLocation->MinorFunction) {
+    case IRP_MN_SET_POWER:
+        status = FdoDispatchSetDevicePower(Fdo, Irp);
+        break;
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    case IRP_MN_QUERY_POWER:
+        status = FdoDispatchQueryPower(Fdo, Irp);
+        break;
 
+    default:
+        ASSERT(FALSE);
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+        break;
+    }
     return status;
 }
 
+/* Dispatch - call down, and/or set completion, IRP not pended */
 static NTSTATUS
-FdoQuerySystemPower(
-    IN  PXENFILT_FDO    Fdo,
+FdoDispatchSystemPower(
+    IN  PXENFILT_FDO   Fdo,
     IN  PIRP            Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
+    NTSTATUS status;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
 
-    Trace("%s: ====> (%s:%s)\n",
-          __FdoGetName(Fdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction));
+    switch (StackLocation->MinorFunction) {
+    case IRP_MN_SET_POWER:
+        status = FdoDispatchSetSystemPower(Fdo, Irp);
+        break;
 
-    if (SystemState == __FdoGetSystemPowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    case IRP_MN_QUERY_POWER:
+        status = FdoDispatchQueryPower(Fdo, Irp);
+        break;
 
-        goto done;
+    default:
+        ASSERT(FALSE);
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+        break;
     }
-
-    status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?
-             FdoQuerySystemPowerUp(Fdo, Irp) :
-             FdoQuerySystemPowerDown(Fdo, Irp);
-
-done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __FdoGetName(Fdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction),
-          status);
-
     return status;
 }
 
-static NTSTATUS
-FdoDevicePower(
-    IN  PXENFILT_THREAD Self,
-    IN  PVOID           Context
-    )
-{
-    PXENFILT_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();
-
-        StackLocation = IoGetCurrentIrpStackLocation(Irp);
-        MinorFunction = StackLocation->MinorFunction;
-
-        switch (StackLocation->MinorFunction) {
-        case IRP_MN_SET_POWER:
-            (VOID) FdoSetDevicePower(Fdo, Irp);
-            break;
-
-        case IRP_MN_QUERY_POWER:
-            (VOID) FdoQueryDevicePower(Fdo, Irp);
-            break;
-
-        default:
-            ASSERT(FALSE);
-            break;
-        }
-
-        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
-    }
-
-    return STATUS_SUCCESS;
-}
-
-static NTSTATUS
-FdoSystemPower(
-    IN  PXENFILT_THREAD Self,
-    IN  PVOID           Context
-    )
-{
-    PXENFILT_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();
-
-        StackLocation = IoGetCurrentIrpStackLocation(Irp);
-        MinorFunction = StackLocation->MinorFunction;
-
-        switch (StackLocation->MinorFunction) {
-        case IRP_MN_SET_POWER:
-            (VOID) FdoSetSystemPower(Fdo, Irp);
-            break;
-
-        case IRP_MN_QUERY_POWER:
-            (VOID) FdoQuerySystemPower(Fdo, Irp);
-            break;
-
-        default:
-            ASSERT(FALSE);
-            break;
-        }
-
-        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
-    }
-
-    return STATUS_SUCCESS;
-}
-
-static NTSTATUS
+static DECLSPEC_NOINLINE NTSTATUS
 FdoDispatchPower(
-    IN  PXENFILT_FDO    Fdo,
+    IN  PXENFILT_FDO   Fdo,
     IN  PIRP            Irp
     )
 {
@@ -1585,79 +1382,36 @@ FdoDispatchPower(
     POWER_STATE_TYPE    PowerType;
     NTSTATUS            status;
 
-    status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     MinorFunction = StackLocation->MinorFunction;
 
     if (MinorFunction != IRP_MN_QUERY_POWER &&
         MinorFunction != IRP_MN_SET_POWER) {
         IoSkipCurrentIrpStackLocation(Irp);
-
         status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
 
         goto done;
     }
 
     PowerType = StackLocation->Parameters.Power.Type;
 
-    Trace("%s: ====> (%02x:%s)\n",
-          __FdoGetName(Fdo),
-          MinorFunction, 
-          PowerMinorFunctionName(MinorFunction)); 
-
     switch (PowerType) {
     case DevicePowerState:
-        IoMarkIrpPending(Irp);
-
-        ASSERT3P(Fdo->DevicePowerIrp, ==, NULL);
-        Fdo->DevicePowerIrp = Irp;
-        KeMemoryBarrier();
-
-        ThreadWake(Fdo->DevicePowerThread);
-
-        status = STATUS_PENDING;
+        status = FdoDispatchDevicePower(Fdo, Irp);
         break;
 
     case SystemPowerState:
-        IoMarkIrpPending(Irp);
-
-        ASSERT3P(Fdo->SystemPowerIrp, ==, NULL);
-        Fdo->SystemPowerIrp = Irp;
-        KeMemoryBarrier();
-
-        ThreadWake(Fdo->SystemPowerThread);
-
-        status = STATUS_PENDING;
+        status = FdoDispatchSystemPower(Fdo, Irp);
         break;
 
     default:
         IoSkipCurrentIrpStackLocation(Irp);
-
         status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
         break;
     }
 
-    Trace("%s: <==== (%02x:%s) (%08x)\n",
-          __FdoGetName(Fdo),
-          MinorFunction, 
-          PowerMinorFunctionName(MinorFunction),
-          status);
-
 done:
     return status;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
 }
 
 static NTSTATUS
@@ -1775,21 +1529,13 @@ FdoCreate(
     Fdo->LowerDeviceObject = LowerDeviceObject;
     Fdo->Type = Type;
 
-    status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    status = ThreadCreate(FdoDevicePower, Fdo, &Fdo->DevicePowerThread);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
     status = __FdoSetDeviceID(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail4;
 
     status = __FdoSetInstanceID(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail5;
 
     __FdoSetName(Fdo);
 
@@ -1814,24 +1560,10 @@ FdoCreate(
 
     return STATUS_SUCCESS;
 
-fail7:
-    Error("fail7\n");
-
-    __FdoClearDeviceID(Fdo);
-
-fail6:
-    Error("fail6\n");
-
-    ThreadAlert(Fdo->DevicePowerThread);
-    ThreadJoin(Fdo->DevicePowerThread);
-    Fdo->DevicePowerThread = NULL;
-
 fail5:
     Error("fail5\n");
 
-    ThreadAlert(Fdo->SystemPowerThread);
-    ThreadJoin(Fdo->SystemPowerThread);
-    Fdo->SystemPowerThread = NULL;
+    __FdoClearDeviceID(Fdo);
 
 fail4:
     Error("fail4\n");
@@ -1891,14 +1623,6 @@ FdoDestroy(
     __FdoClearInstanceID(Fdo);
     __FdoClearDeviceID(Fdo);
 
-    ThreadAlert(Fdo->DevicePowerThread);
-    ThreadJoin(Fdo->DevicePowerThread);
-    Fdo->DevicePowerThread = NULL;
-
-    ThreadAlert(Fdo->SystemPowerThread);
-    ThreadJoin(Fdo->SystemPowerThread);
-    Fdo->SystemPowerThread = NULL;
-
     Fdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN;
     Fdo->LowerDeviceObject = NULL;
     Fdo->PhysicalDeviceObject = NULL;
diff --git a/src/xenfilt/pdo.c b/src/xenfilt/pdo.c
index 741c2f3..2475c6a 100644
--- a/src/xenfilt/pdo.c
+++ b/src/xenfilt/pdo.c
@@ -56,11 +56,6 @@ struct _XENFILT_PDO {
     PDEVICE_OBJECT                  PhysicalDeviceObject;
     CHAR                            Name[MAXNAMELEN];
 
-    PXENFILT_THREAD                 SystemPowerThread;
-    PIRP                            SystemPowerIrp;
-    PXENFILT_THREAD                 DevicePowerThread;
-    PIRP                            DevicePowerIrp;
-
     PXENFILT_FDO                    Fdo;
     BOOLEAN                         Missing;
     const CHAR                      *Reason;
@@ -1186,82 +1181,84 @@ fail1:
     return status;
 }
 
+
+
+
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
 static NTSTATUS
-PdoSetDevicePowerUp(
-    IN  PXENFILT_PDO    Pdo,
-    IN  PIRP            Irp
+PdoCompleteSetDevicePowerUp(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
+    IN  PVOID           Context
     )
 {
+    PXENFILT_PDO        Pdo = (PXENFILT_PDO) Context;
     PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
     POWER_STATE         PowerState;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
 
-    ASSERT3U(DeviceState, <,  __PdoGetDevicePowerState(Pdo));
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    PowerState = StackLocation->Parameters.Power.State;
 
-    Trace("%s: %s -> %s\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(__PdoGetDevicePowerState(Pdo)),
-          DevicePowerStateName(DeviceState));
+    if (Irp->PendingReturned) {
+        IoMarkIrpPending(Irp);
+    }
 
-    PowerState.DeviceState = DeviceState;
-    PoSetPowerState(__PdoGetDeviceObject(Pdo),
+    __PdoSetDevicePowerState(Pdo, PowerState.DeviceState);
+    PoSetPowerState(Pdo->Dx->DeviceObject,
                     DevicePowerState,
                     PowerState);
 
-    __PdoSetDevicePowerState(Pdo, DeviceState);
+    return STATUS_CONTINUE_COMPLETION;
+}
 
-done:
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+static FORCEINLINE NTSTATUS
+PdoDispatchSetDevicePowerUp(
+    IN  PXENFILT_PDO     Pdo,
+    IN  PIRP            Irp
+    )
+{
+    PIO_STACK_LOCATION  StackLocation;
 
-    return status;
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           PdoCompleteSetDevicePowerUp,
+                           Pdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+    return IoCallDriver(Pdo->LowerDeviceObject, Irp);
 }
 
-static NTSTATUS
-PdoSetDevicePowerDown(
+static FORCEINLINE NTSTATUS
+PdoDispatchSetDevicePowerDown(
     IN  PXENFILT_PDO    Pdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
     POWER_STATE         PowerState;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
+    PowerState = StackLocation->Parameters.Power.State;
 
-    ASSERT3U(DeviceState, >,  __PdoGetDevicePowerState(Pdo));
-
-    Trace("%s: %s -> %s\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(__PdoGetDevicePowerState(Pdo)),
-          DevicePowerStateName(DeviceState));
-
-    PowerState.DeviceState = DeviceState;
-    PoSetPowerState(__PdoGetDeviceObject(Pdo),
+    __PdoSetDevicePowerState(Pdo, PowerState.DeviceState);
+    PoSetPowerState(Pdo->Dx->DeviceObject,
                     DevicePowerState,
                     PowerState);
 
-    __PdoSetDevicePowerState(Pdo, DeviceState);
-
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
+    IoSkipCurrentIrpStackLocation(Irp);
+    return IoCallDriver(Pdo->LowerDeviceObject, Irp);
 }
 
-static NTSTATUS
-PdoSetDevicePower(
-    IN  PXENFILT_PDO    Pdo,
+/* IRQL argnostic code, just mark power states.*/
+static FORCEINLINE NTSTATUS
+PdoDispatchSetDevicePower(
+    IN  PXENFILT_PDO     Pdo,
     IN  PIRP            Irp
     )
 {
@@ -1274,422 +1271,220 @@ PdoSetDevicePower(
     DeviceState = StackLocation->Parameters.Power.State.DeviceState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("%s: ====> (%s:%s)\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(DeviceState), 
+    /* See if we can get away without pending the IRP in a filter
+       driver. */
+
+    Trace("====> (%s:%s)\n",
+          DevicePowerStateName(DeviceState),
           PowerActionName(PowerAction));
 
-    if (DeviceState == __PdoGetDevicePowerState(Pdo)) {
-        status = PdoForwardIrpSynchronously(Pdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
+    if (DeviceState == __PdoGetDevicePowerState(Pdo)) {
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
         goto done;
     }
 
-    status = (DeviceState < __PdoGetDevicePowerState(Pdo)) ?
-             PdoSetDevicePowerUp(Pdo, Irp) :
-             PdoSetDevicePowerDown(Pdo, Irp);
+    if (DeviceState < __PdoGetDevicePowerState(Pdo)) {
+        status = PdoDispatchSetDevicePowerUp(Pdo, Irp);
+    } else {
+        status = PdoDispatchSetDevicePowerDown(Pdo, Irp);
+    }
 
 done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction),
-          status);
+    Trace("<==== (%s:%s)\n",
+          DevicePowerStateName(DeviceState),
+          PowerActionName(PowerAction));
+
     return status;
 }
 
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
 static NTSTATUS
-PdoSetSystemPowerUp(
-    IN  PXENFILT_PDO    Pdo,
-    IN  PIRP            Irp
+PdoCompleteSetSystemPowerUp(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
+    IN  PVOID           Context
     )
 {
+    PXENFILT_PDO     Pdo = (PXENFILT_PDO) Context;
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
 
-    ASSERT3U(SystemState, <,  __PdoGetSystemPowerState(Pdo));
-
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
-
-    Trace("%s: %s -> %s\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(__PdoGetSystemPowerState(Pdo)),
-          SystemPowerStateName(SystemState));
+    if (Irp->PendingReturned) {
+        IoMarkIrpPending(Irp);
+    }
 
     __PdoSetSystemPowerState(Pdo, SystemState);
 
-done:
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
+    return STATUS_CONTINUE_COMPLETION;
 }
 
-static NTSTATUS
-PdoSetSystemPowerDown(
+static FORCEINLINE NTSTATUS
+PdoDispatchSetSystemPowerUp(
     IN  PXENFILT_PDO     Pdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-
-    ASSERT3U(SystemState, >,  __PdoGetSystemPowerState(Pdo));
-
-    Trace("%s: %s -> %s\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(__PdoGetSystemPowerState(Pdo)),
-          SystemPowerStateName(SystemState));
-
-    __PdoSetSystemPowerState(Pdo, SystemState);
 
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+    IoSetCompletionRoutine(Irp,
+                           PdoCompleteSetSystemPowerUp,
+                           Pdo,
+                           TRUE,
+                           TRUE,
+                           TRUE);
+    return IoCallDriver(Pdo->LowerDeviceObject, Irp);
 }
 
-static NTSTATUS
-PdoSetSystemPower(
-    IN  PXENFILT_PDO    Pdo,
+static FORCEINLINE NTSTATUS
+PdoDispatchSetSystemPowerDown(
+    IN  PXENFILT_PDO     Pdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
-
-    Trace("%s: ====> (%s:%s)\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction));
-
-    if (SystemState == __PdoGetSystemPowerState(Pdo)) {
-        status = PdoForwardIrpSynchronously(Pdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-        goto done;
-    }
-
-    status = (SystemState < __PdoGetSystemPowerState(Pdo)) ?
-             PdoSetSystemPowerUp(Pdo, Irp) :
-             PdoSetSystemPowerDown(Pdo, Irp);
-
-done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction),
-          status);
-    return status;
-}
-
-static NTSTATUS
-PdoQueryDevicePowerUp(
-    IN  PXENFILT_PDO    Pdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-
-    ASSERT3U(DeviceState, <,  __PdoGetDevicePowerState(Pdo));
-
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-PdoQueryDevicePowerDown(
-    IN  PXENFILT_PDO    Pdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-
-    ASSERT3U(DeviceState, >,  __PdoGetDevicePowerState(Pdo));
 
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    __PdoSetSystemPowerState(Pdo, SystemState);
 
-    return status;
+    IoSkipCurrentIrpStackLocation(Irp);
+    return IoCallDriver(Pdo->LowerDeviceObject, Irp);
 }
 
-static NTSTATUS
-PdoQueryDevicePower(
-    IN  PXENFILT_PDO    Pdo,
+/* IRQL argnostic code, just mark power states.*/
+static FORCEINLINE NTSTATUS
+PdoDispatchSetSystemPower(
+    IN  PXENFILT_PDO     Pdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
+    SYSTEM_POWER_STATE  SystemState;
     POWER_ACTION        PowerAction;
     NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
+    SystemState = StackLocation->Parameters.Power.State.SystemState;
     PowerAction = StackLocation->Parameters.Power.ShutdownType;
 
-    Trace("%s: ====> (%s:%s)\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction));
+    /* See if we can get away without pending the IRP in a filter
+       driver. */
 
-    if (DeviceState == __PdoGetDevicePowerState(Pdo)) {
-        status = PdoForwardIrpSynchronously(Pdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    Trace("====> (%s:%s)\n",
+          SystemPowerStateName(SystemState),
+          PowerActionName(PowerAction));
 
+    if (SystemState == __PdoGetSystemPowerState(Pdo)) {
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
         goto done;
     }
 
-    status = (DeviceState < __PdoGetDevicePowerState(Pdo)) ?
-             PdoQueryDevicePowerUp(Pdo, Irp) :
-             PdoQueryDevicePowerDown(Pdo, Irp);
+    if (SystemState < __PdoGetSystemPowerState(Pdo)) {
+        status = PdoDispatchSetSystemPowerUp(Pdo, Irp);
+    } else {
+        status = PdoDispatchSetSystemPowerDown(Pdo, Irp);
+    }
 
 done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction),
-          status);
-    return status;
-}
-
-static NTSTATUS
-PdoQuerySystemPowerUp(
-    IN  PXENFILT_PDO    Pdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-
-    ASSERT3U(SystemState, <,  __PdoGetSystemPowerState(Pdo));
-
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    Trace("<==== (%s:%s)\n",
+          SystemPowerStateName(SystemState),
+          PowerActionName(PowerAction));
 
     return status;
 }
 
-static NTSTATUS
-PdoQuerySystemPowerDown(
+static FORCEINLINE NTSTATUS
+PdoDispatchQueryPower(
     IN  PXENFILT_PDO    Pdo,
     IN  PIRP            Irp
     )
 {
     PIO_STACK_LOCATION  StackLocation;
     SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     SystemState = StackLocation->Parameters.Power.State.SystemState;
 
-    ASSERT3U(SystemState, >,  __PdoGetSystemPowerState(Pdo));
-
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
+    /* Queries we will just pass thru, regardless of what they are.
+       Don't need to pend or set any completion routines. */
+    IoSkipCurrentIrpStackLocation(Irp);
+    return IoCallDriver(Pdo->LowerDeviceObject, Irp);
 }
 
+/* Dispatch - call down, and/or set completion, IRP not pended */
 static NTSTATUS
-PdoQuerySystemPower(
-    IN  PXENFILT_PDO    Pdo,
+PdoDispatchDevicePower(
+    IN  PXENFILT_PDO   Pdo,
     IN  PIRP            Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
+    NTSTATUS status;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
 
-    Trace("%s: ====> (%s:%s)\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction));
+    switch (StackLocation->MinorFunction) {
+    case IRP_MN_SET_POWER:
+        status = PdoDispatchSetDevicePower(Pdo, Irp);
+        break;
 
-    if (SystemState == __PdoGetSystemPowerState(Pdo)) {
-        status = PdoForwardIrpSynchronously(Pdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    case IRP_MN_QUERY_POWER:
+        status = PdoDispatchQueryPower(Pdo, Irp);
+        break;
 
-        goto done;
+    default:
+        ASSERT(FALSE);
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
+        break;
     }
-
-    status = (SystemState < __PdoGetSystemPowerState(Pdo)) ?
-             PdoQuerySystemPowerUp(Pdo, Irp) :
-             PdoQuerySystemPowerDown(Pdo, Irp);
-
-done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction),
-          status);
-
     return status;
 }
 
+/* Dispatch - call down, and/or set completion, IRP not pended */
 static NTSTATUS
-PdoDevicePower(
-    IN  PXENFILT_THREAD Self,
-    IN  PVOID           Context
+PdoDispatchSystemPower(
+    IN  PXENFILT_PDO   Pdo,
+    IN  PIRP            Irp
     )
 {
-    PXENFILT_PDO        Pdo = Context;
-    PKEVENT             Event;
-
-    Event = ThreadGetEvent(Self);
-
-    for (;;) {
-        PIRP                Irp;
-        PIO_STACK_LOCATION  StackLocation;
-        UCHAR               MinorFunction;
-
-        if (Pdo->DevicePowerIrp == NULL) {
-            (VOID) KeWaitForSingleObject(Event,
-                                         Executive,
-                                         KernelMode,
-                                         FALSE,
-                                         NULL);
-            KeClearEvent(Event);
-        }
-
-        if (ThreadIsAlerted(Self))
-            break;
-
-        Irp = Pdo->DevicePowerIrp;
+    NTSTATUS status;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
 
-        if (Irp == NULL)
-            continue;
-
-        Pdo->DevicePowerIrp = NULL;
-        KeMemoryBarrier();
-
-        StackLocation = IoGetCurrentIrpStackLocation(Irp);
-        MinorFunction = StackLocation->MinorFunction;
-
-        switch (StackLocation->MinorFunction) {
-        case IRP_MN_SET_POWER:
-            (VOID) PdoSetDevicePower(Pdo, Irp);
-            break;
-
-        case IRP_MN_QUERY_POWER:
-            (VOID) PdoQueryDevicePower(Pdo, Irp);
-            break;
+    switch (StackLocation->MinorFunction) {
+    case IRP_MN_SET_POWER:
+        status = PdoDispatchSetSystemPower(Pdo, Irp);
+        break;
 
-        default:
-            ASSERT(FALSE);
-            break;
-        }
+    case IRP_MN_QUERY_POWER:
+        status = PdoDispatchQueryPower(Pdo, Irp);
+        break;
 
-        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+    default:
+        ASSERT(FALSE);
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
+        break;
     }
-
-    return STATUS_SUCCESS;
+    return status;
 }
 
-static NTSTATUS
-PdoSystemPower(
-    IN  PXENFILT_THREAD Self,
-    IN  PVOID           Context
-    )
-{
-    PXENFILT_PDO        Pdo = Context;
-    PKEVENT             Event;
-
-    Event = ThreadGetEvent(Self);
-
-    for (;;) {
-        PIRP                Irp;
-        PIO_STACK_LOCATION  StackLocation;
-        UCHAR               MinorFunction;
-
-        if (Pdo->SystemPowerIrp == NULL) {
-            (VOID) KeWaitForSingleObject(Event,
-                                         Executive,
-                                         KernelMode,
-                                         FALSE,
-                                         NULL);
-            KeClearEvent(Event);
-        }
-
-        if (ThreadIsAlerted(Self))
-            break;
-
-        Irp = Pdo->SystemPowerIrp;
-
-        if (Irp == NULL)
-            continue;
 
-        Pdo->SystemPowerIrp = NULL;
-        KeMemoryBarrier();
-
-        StackLocation = IoGetCurrentIrpStackLocation(Irp);
-        MinorFunction = StackLocation->MinorFunction;
-
-        switch (StackLocation->MinorFunction) {
-        case IRP_MN_SET_POWER:
-            (VOID) PdoSetSystemPower(Pdo, Irp);
-            break;
-
-        case IRP_MN_QUERY_POWER:
-            (VOID) PdoQuerySystemPower(Pdo, Irp);
-            break;
-
-        default:
-            ASSERT(FALSE);
-            break;
-        }
-
-        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
-    }
-
-    return STATUS_SUCCESS;
-}
-
-static NTSTATUS
+static DECLSPEC_NOINLINE NTSTATUS
 PdoDispatchPower(
-    IN  PXENFILT_PDO    Pdo,
+    IN  PXENFILT_PDO   Pdo,
     IN  PIRP            Irp
     )
 {
@@ -1698,81 +1493,39 @@ PdoDispatchPower(
     POWER_STATE_TYPE    PowerType;
     NTSTATUS            status;
 
-    status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     MinorFunction = StackLocation->MinorFunction;
 
     if (MinorFunction != IRP_MN_QUERY_POWER &&
         MinorFunction != IRP_MN_SET_POWER) {
         IoSkipCurrentIrpStackLocation(Irp);
-
         status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
-        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
 
         goto done;
     }
 
     PowerType = StackLocation->Parameters.Power.Type;
 
-    Trace("%s: ====> (%02x:%s)\n",
-          __PdoGetName(Pdo),
-          MinorFunction, 
-          PowerMinorFunctionName(MinorFunction)); 
-
     switch (PowerType) {
     case DevicePowerState:
-        IoMarkIrpPending(Irp);
-
-        ASSERT3P(Pdo->DevicePowerIrp, ==, NULL);
-        Pdo->DevicePowerIrp = Irp;
-        KeMemoryBarrier();
-
-        ThreadWake(Pdo->DevicePowerThread);
-
-        status = STATUS_PENDING;
+        status = PdoDispatchDevicePower(Pdo, Irp);
         break;
 
     case SystemPowerState:
-        IoMarkIrpPending(Irp);
-
-        ASSERT3P(Pdo->SystemPowerIrp, ==, NULL);
-        Pdo->SystemPowerIrp = Irp;
-        KeMemoryBarrier();
-
-        ThreadWake(Pdo->SystemPowerThread);
-
-        status = STATUS_PENDING;
+        status = PdoDispatchSystemPower(Pdo, Irp);
         break;
 
     default:
         IoSkipCurrentIrpStackLocation(Irp);
-
         status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
-        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
         break;
     }
 
-    Trace("%s: <==== (%02x:%s) (%08x)\n",
-          __PdoGetName(Pdo),
-          MinorFunction, 
-          PowerMinorFunctionName(MinorFunction),
-          status);
-
 done:
     return status;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
 }
 
+
 static NTSTATUS
 PdoDispatchDefault(
     IN  PXENFILT_PDO    Pdo,
@@ -1907,17 +1660,9 @@ PdoCreate(
     Pdo->LowerDeviceObject = LowerDeviceObject;
     Pdo->Type = Type;
 
-    status = ThreadCreate(PdoSystemPower, Pdo, &Pdo->SystemPowerThread);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    status = ThreadCreate(PdoDevicePower, Pdo, &Pdo->DevicePowerThread);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
     status = PdoSetDeviceInformation(Pdo);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail4;
 
     status = DriverQueryId(Pdo->LowerDeviceObject,
                            BusQueryCompatibleIDs,
@@ -1932,7 +1677,7 @@ PdoCreate(
                                __PdoGetType(Pdo),
                                &Pdo->EmulatedObject);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail5;
 
     if (CompatibleIDs)
         ExFreePool(CompatibleIDs);
@@ -1957,28 +1702,14 @@ PdoCreate(
 
     return STATUS_SUCCESS;
 
-fail7:
-    Error("fail7\n");
+fail5:
+    Error("fail5\n");
 
     if (CompatibleIDs)
         ExFreePool(CompatibleIDs);
 
     PdoClearDeviceInformation(Pdo);
 
-fail6:
-    Error("fail6\n");
-
-    ThreadAlert(Pdo->DevicePowerThread);
-    ThreadJoin(Pdo->DevicePowerThread);
-    Pdo->DevicePowerThread = NULL;
-
-fail5:
-    Error("fail5\n");
-
-    ThreadAlert(Pdo->SystemPowerThread);
-    ThreadJoin(Pdo->SystemPowerThread);
-    Pdo->SystemPowerThread = NULL;
-
 fail4:
     Error("fail4\n");
 
@@ -2040,14 +1771,6 @@ PdoDestroy(
 
     PdoClearDeviceInformation(Pdo);
 
-    ThreadAlert(Pdo->DevicePowerThread);
-    ThreadJoin(Pdo->DevicePowerThread);
-    Pdo->DevicePowerThread = NULL;
-
-    ThreadAlert(Pdo->SystemPowerThread);
-    ThreadJoin(Pdo->SystemPowerThread);
-    Pdo->SystemPowerThread = NULL;
-
     Pdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN;
     Pdo->PhysicalDeviceObject = NULL;
     Pdo->LowerDeviceObject = NULL;
-- 
2.25.0.windows.1




 


Rackspace

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