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

[PATCH] Improve Xenfilt power and default IRP handling.


  • To: <win-pv-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Martin Harvey <Martin.Harvey@xxxxxxxxxx>
  • Date: Mon, 14 Mar 2022 17:01:41 +0000
  • Authentication-results: esa2.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: Mon, 14 Mar 2022 17:02:34 +0000
  • Ironport-data: A9a23:YIT+1K93jlAOTYK9uvEmDrUD0n6TJUtcMsCJ2f8bNWPcYEJGY0x3y mVMXzuPO63fYzbzeNsgYY609EsD65fdmtMwTANl/3o8E34SpcT7XtnIdU2Y0wF+jyHgoOCLy +1EN7Es+ehtFie0Si+Fa+Sn9T8mvU2xbuKU5NTsY0idfic5DnZ54f5fs7Rh2NQw2oHlW1nlV e7a+KUzBnf0g1aYDUpMg06zgEsHUCPa4W5wUvQWPJinjXeG/5UnJMt3yZKZdhMUdrJ8DO+iL 9sv+Znilo/vE7XBPfv++lrzWhVirrc/pmFigFIOM0SpqkAqSiDfTs/XnRfTAKtao2zhojx/9 DlCncaBdl8QFarmosEMTygDGg5xAop86JaSdBBTseTLp6HHW37lwvEoB0AqJ4wIvO1wBAmi9 9RBdmpLNErawbvrnvTrEYGAhex6RCXvFIYWoG1hy3fZBOw4TIHrSKTW/95Imjw3g6iiGN6AO ZBBNmY+M3wsZTUfFEgHL84AoNy5jzrneDZCjF2xi7QOtj27IAtZj+G2bYu9lsaxbdpUmAOAu CfK8nr0BjkeNceD0nyV/3S0nOjNkCjnHoUIG9WFGuVC2QPJgDZJUVtPCAX98aLRZlOCt8x3c X0rohMFqoII0V23f4L0cBKHh0SUl0tJMzZPKNES5AaIw6vSxg+WAGkYUzJMAOAbWN8KqS8Cj QHQwY6wbdB7mPjMEC/GqO/Ixd+nEXJNRVLucxPoWufsDzPLhIgoxizCQd94eEJepo2kQGqgq 9xmQcVXulnysSLp//jhlbwkq2j1znQscuLSzl+LNl9JFisjOOaYi3WAsDA3F8poIoeDVUWmt 3MZgcWY5+1mJcjTyHPUEbpXRO72vq7t3NjgbblHRcVJythQ0yT7IdA4DM9WeS+FzfroiRe2O RSO6Gu9FbdYPWewbL8fXm5CI59C8EQULvy8Dqq8RoMXOvBZLVbblAkzNR/49z28yyAEzPBgU ap3hO7xVB72/4w8l2HoLwrcuJd2rh0DKZT7HsmqkU74jeLAOBZ4i94taTOzUwzw14vcyC29z jqVH5fiJ8l3OAEmXhTqzA==
  • Ironport-hdrordr: A9a23:jjb7p6DNP1tPY/7lHemg55DYdb4zR+YMi2TC1yhKJyC9Ffbo8/ xG/c5rsyMc5wxwZJhNo7y90cq7MBbhHPxOkOos1N6ZNWGM0gaVxelZnOzfKlbbehEWmNQz6U 4ZSdkdNOHN
  • List-id: Developer list for the Windows PV Drivers subproject <win-pv-devel.lists.xenproject.org>

Signed-off-by: Martin Harvey <martin.harvey@xxxxxxxxxx>
---
 src/common/util.h |   8 +
 src/xenfilt/fdo.c | 785 ++++++++++++---------------------------------
 src/xenfilt/pdo.c | 790 ++++++++++++----------------------------------
 3 files changed, 411 insertions(+), 1172 deletions(-)

diff --git a/src/common/util.h b/src/common/util.h
index 36a36dd..fb9b9b7 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -36,6 +36,14 @@
 
 #include "assert.h"
 
+typedef enum _XEN_IRP_STRATEGY {
+    XEN_IRP_PASSDOWN_TRANSPARENT,
+    XEN_IRP_HANDLE_INDISPATCH_AND_COMPLETE,
+    XEN_IRP_HANDLE_INDISPATCH_PASSDOWN,
+    XEN_IRP_HANDLE_INCOMPLETION,
+    XEN_IRP_STRATEGY_MAX
+} XEN_IRP_STRATEGY, *PXEN_IRP_STRATEGY;
+
 #define        P2ROUNDUP(_x, _a)   \
         (-(-(_x) & -(_a)))
 
diff --git a/src/xenfilt/fdo.c b/src/xenfilt/fdo.c
index 63fa7b3..5d43d01 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;
@@ -1004,6 +999,26 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+FdoDispatchDefault(
+    IN  PXENFILT_FDO    Fdo,
+    IN  PIRP            Irp
+    )
+{
+    NTSTATUS status;
+    IoSkipCurrentIrpStackLocation(Irp);
+    status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return status;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
+}
+
+
 static NTSTATUS
 FdoDispatchPnp(
     IN  PXENFILT_FDO    Fdo,
@@ -1055,524 +1070,135 @@ FdoDispatchPnp(
         break;
 
     default:
-        status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp);
-        if (!NT_SUCCESS(status))
-            goto fail1;
-
-        IoSkipCurrentIrpStackLocation(Irp);
-
-        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
+        status = FdoDispatchDefault(Fdo, Irp);
         break;
     }
 
-    return status;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-FdoSetDevicePowerUp(
-    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;
-
-    ASSERT3U(DeviceState, <,  __FdoGetDevicePowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
-
-    Trace("%s: %s -> %s\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(__FdoGetDevicePowerState(Fdo)),
-          DevicePowerStateName(DeviceState));
-
-    PowerState.DeviceState = DeviceState;
-    PoSetPowerState(Fdo->Dx->DeviceObject,
-                    DevicePowerState,
-                    PowerState);
-
-    __FdoSetDevicePowerState(Fdo, DeviceState);
-
-done:
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-FdoSetDevicePowerDown(
-    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;
-
-    ASSERT3U(DeviceState, >,  __FdoGetDevicePowerState(Fdo));
-
-    Trace("%s: %s -> %s\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(__FdoGetDevicePowerState(Fdo)),
-          DevicePowerStateName(DeviceState));
-
-    PowerState.DeviceState = DeviceState;
-    PoSetPowerState(Fdo->Dx->DeviceObject,
-                    DevicePowerState,
-                    PowerState);
-
-    __FdoSetDevicePowerState(Fdo, DeviceState);
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-FdoSetDevicePower(
-    IN  PXENFILT_FDO    Fdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
-
-    Trace("%s: ====> (%s:%s)\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction));
-
-    if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-        goto done;
-    }
-
-    status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ?
-             FdoSetDevicePowerUp(Fdo, Irp) :
-             FdoSetDevicePowerDown(Fdo, Irp);
-
-done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction),
-          status);
-    return status;
-}
-
-static NTSTATUS
-FdoSetSystemPowerUp(
-    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);
-    if (!NT_SUCCESS(status))
-        goto done;
-
-    Trace("%s: %s -> %s\n",
-          __FdoGetName(Fdo),
-          SystemPowerStateName(__FdoGetSystemPowerState(Fdo)),
-          SystemPowerStateName(SystemState));
-
-    __FdoSetSystemPowerState(Fdo, SystemState);
-
-done:
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-FdoSetSystemPowerDown(
-    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;
-}
-
-static NTSTATUS
-FdoSetSystemPower(
-    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(
+FdoDispatchPowerImmediate(
     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;
+    NTSTATUS status = STATUS_INTERNAL_ERROR;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    UCHAR MinorFunction = StackLocation->MinorFunction;
 
-    ASSERT3U(DeviceState, >,  __FdoGetDevicePowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-FdoQueryDevicePower(
-    IN  PXENFILT_FDO    Fdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
+    if (MinorFunction != IRP_MN_SET_POWER)
+        goto fail1;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
+    POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;
 
-    Trace("%s: ====> (%s:%s)\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction));
+    switch (PowerType) {
+    case DevicePowerState:
+        POWER_STATE PowerState;
+        DEVICE_POWER_STATE DeviceState = 
StackLocation->Parameters.Power.State.DeviceState;
+        if (DeviceState >= __FdoGetDevicePowerState(Fdo))
+            goto fail3;
 
-    if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        __FdoSetDevicePowerState(Fdo, DeviceState);
+        PowerState.DeviceState = DeviceState;
+        PoSetPowerState(__FdoGetDeviceObject(Fdo),
+                        DevicePowerState,
+                        PowerState);
+    break;
+    case SystemPowerState:
+        SYSTEM_POWER_STATE SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+        if (SystemState >= __FdoGetSystemPowerState(Fdo))
+            goto fail3;
 
-        goto done;
+        __FdoSetSystemPowerState(Fdo, SystemState);
+    break;
+    default:
+        goto fail2;
     }
 
-    status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ?
-             FdoQueryDevicePowerUp(Fdo, Irp) :
-             FdoQueryDevicePowerDown(Fdo, Irp);
-
-done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __FdoGetName(Fdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction),
-          status);
-    return status;
-}
-
-static NTSTATUS
-FdoQuerySystemPowerUp(
-    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_SUCCESS;
 
+fail3:
+    Error("fail3 (%08x)\n", status);
+fail2:
+    Error("fail2 (%08x)\n", status);
+fail1:
+    Error("fail1 (%08x)\n", status);
     return status;
 }
 
-static NTSTATUS
-FdoQuerySystemPowerDown(
+static VOID
+FdoCompletionPower(
     IN  PXENFILT_FDO    Fdo,
     IN  PIRP            Irp
-    )
+)
 {
-    PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    NTSTATUS            status;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    UCHAR MinorFunction = StackLocation->MinorFunction;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-
-    ASSERT3U(SystemState, >,  __FdoGetSystemPowerState(Fdo));
-
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
+    if (MinorFunction != IRP_MN_SET_POWER)
+        goto fail1;
 
-static NTSTATUS
-FdoQuerySystemPower(
-    IN  PXENFILT_FDO    Fdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
+    POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
+    switch (PowerType) {
+    case DevicePowerState:
+        POWER_STATE PowerState;
+        DEVICE_POWER_STATE DeviceState = 
StackLocation->Parameters.Power.State.DeviceState;
+        if (DeviceState <= __FdoGetDevicePowerState(Fdo))
+            goto fail3;
 
-    Trace("%s: ====> (%s:%s)\n",
-          __FdoGetName(Fdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction));
+        PowerState.DeviceState = DeviceState;
+        PoSetPowerState(__FdoGetDeviceObject(Fdo),
+                        DevicePowerState,
+                        PowerState);
+        __FdoSetDevicePowerState(Fdo, DeviceState);
 
-    if (SystemState == __FdoGetSystemPowerState(Fdo)) {
-        status = FdoForwardIrpSynchronously(Fdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    break;
+    case SystemPowerState:
+        SYSTEM_POWER_STATE SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+        if (SystemState <= __FdoGetSystemPowerState(Fdo))
+            goto fail3;
 
-        goto done;
+        __FdoSetSystemPowerState(Fdo, SystemState);
+    break;
+    default:
+        goto fail2;
     }
 
-    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;
 
-    return status;
+fail3:
+    Error("fail3\n");
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1");
 }
 
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
 static NTSTATUS
-FdoDevicePower(
-    IN  PXENFILT_THREAD Self,
+FdoDispatchPowerCompletionV2(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
     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;
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-        default:
-            ASSERT(FALSE);
-            break;
-        }
+    if (Irp->PendingReturned)
+        IoMarkIrpPending(Irp);
 
-        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
-    }
+    //Assumption don't need STATUS_MORE_PROCESSING_REQUIRED.
+    FdoCompletionPower(Fdo, Irp);
 
+    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
 FdoDispatchPower(
@@ -1582,104 +1208,125 @@ FdoDispatchPower(
 {
     PIO_STACK_LOCATION  StackLocation;
     UCHAR               MinorFunction;
-    POWER_STATE_TYPE    PowerType;
     NTSTATUS            status;
-
-    status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp);
-    if (!NT_SUCCESS(status))
-        goto fail1;
+    XEN_IRP_STRATEGY    strategy;
+    BOOLEAN HaveRemoveLock = FALSE;
 
     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;
+    //Decide how we're going to handle this IRP.
+    switch(MinorFunction) {
+    case IRP_MN_QUERY_POWER:
+        strategy = XEN_IRP_PASSDOWN_TRANSPARENT; //Dont fail, don't need to 
check queries.
         break;
-
-    case SystemPowerState:
-        IoMarkIrpPending(Irp);
-
-        ASSERT3P(Fdo->SystemPowerIrp, ==, NULL);
-        Fdo->SystemPowerIrp = Irp;
-        KeMemoryBarrier();
-
-        ThreadWake(Fdo->SystemPowerThread);
-
-        status = STATUS_PENDING;
+    case IRP_MN_SET_POWER:
+        POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;
+
+        switch (PowerType) {
+        case DevicePowerState:
+            DEVICE_POWER_STATE DeviceState = 
StackLocation->Parameters.Power.State.DeviceState;
+
+            status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail1;
+
+            //If fails, then pending removal or already removed,
+            //freshly initialized (or not). Consider status to return...
+            HaveRemoveLock = TRUE;
+
+            if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
+                strategy = XEN_IRP_PASSDOWN_TRANSPARENT;
+            } else if (DeviceState < __FdoGetDevicePowerState(Fdo)) {
+                strategy = XEN_IRP_HANDLE_INDISPATCH_PASSDOWN;
+            } else {
+                strategy = XEN_IRP_HANDLE_INCOMPLETION;
+            }
+        case SystemPowerState:
+            SYSTEM_POWER_STATE SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+
+            status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail1;
+
+            //If fails, then pending removal or already removed,
+            //freshly initialized (or not). Consider status to return...
+            HaveRemoveLock = TRUE;
+
+            if (SystemState == __FdoGetSystemPowerState(Fdo)) {
+                strategy = XEN_IRP_PASSDOWN_TRANSPARENT;
+            } else if (SystemState < __FdoGetSystemPowerState(Fdo)) {
+                strategy = XEN_IRP_HANDLE_INDISPATCH_PASSDOWN;
+            } else {
+                strategy = XEN_IRP_HANDLE_INCOMPLETION;
+            }
         break;
-
+        default:
+            strategy = XEN_IRP_PASSDOWN_TRANSPARENT;
+            break;
+        }
     default:
-        IoSkipCurrentIrpStackLocation(Irp);
-
-        status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
+        strategy = XEN_IRP_PASSDOWN_TRANSPARENT;
         break;
     }
 
-    Trace("%s: <==== (%02x:%s) (%08x)\n",
-          __FdoGetName(Fdo),
-          MinorFunction, 
-          PowerMinorFunctionName(MinorFunction),
-          status);
-
-done:
-    return status;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
+    switch(strategy) {
+        case XEN_IRP_HANDLE_INDISPATCH_PASSDOWN:
+            status = FdoDispatchPowerImmediate(Fdo, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail2;
+            //Fallthru.
+        case XEN_IRP_PASSDOWN_TRANSPARENT:
+        default:
+            IoSkipCurrentIrpStackLocation(Irp);
+            status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail3;
 
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            if (HaveRemoveLock)
+                IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
+        break;
+        case XEN_IRP_HANDLE_INCOMPLETION:
+            IoMarkIrpPending(Irp);
+            IoCopyCurrentIrpStackLocationToNext(Irp);
+            IoSetCompletionRoutine(Irp,
+                                FdoDispatchPowerCompletionV2,
+                                Fdo,
+                                TRUE,
+                                TRUE,
+                                TRUE);
+            status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail4;
+            status = STATUS_PENDING; //Must return STATUS_PENDING after 
IoMarkIrpPending, whatever happens next.
+        break;
+    }
 
     return status;
-}
-
-static NTSTATUS
-FdoDispatchDefault(
-    IN  PXENFILT_FDO    Fdo,
-    IN  PIRP            Irp
-    )
-{
-    NTSTATUS            status;
-
-    status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp);
-    if (!NT_SUCCESS(status))
-        goto fail1;
 
-    IoSkipCurrentIrpStackLocation(Irp);
-
-    status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-    IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
+fail4:
+    //Error from lower driver, have remove lock, and completion routine.
+    //Comp routine shd be called on error to drop remove lock.
+    Error("fail4 (%08x)\n", status);
+    status = STATUS_PENDING; //Must return STATUS_PENDING after 
IoMarkIrpPending, whatever happens next.
+    return status;
 
+fail3:
+    //Error from lower driver, have remove lock, called down.
+    Error("fail3 (%08x)\n", status);
+    if (HaveRemoveLock)
+        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
     return status;
 
+fail2:
+    //Immediate error, have remove lock, not called down.
+    Error("fail2 (%08x)\n", status);
+    if (HaveRemoveLock)
+        IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
+    //Fallthru.
+
 fail1:
+    //Immediate error, no remove lock, not called down.
     Error("fail1 (%08x)\n", status);
 
     Irp->IoStatus.Status = status;
@@ -1775,14 +1422,6 @@ 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;
@@ -1822,20 +1461,6 @@ fail7:
 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;
-
-fail4:
-    Error("fail4\n");
-
     Fdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN;
     Fdo->PhysicalDeviceObject = NULL;
     Fdo->LowerDeviceObject = NULL;
@@ -1891,14 +1516,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..ee2a049 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;
@@ -1101,6 +1096,26 @@ PdoEject(
     return status;
 }
 
+static NTSTATUS
+PdoDispatchDefault(
+    IN  PXENFILT_PDO    Pdo,
+    IN  PIRP            Irp
+    )
+{
+    NTSTATUS status;
+    IoSkipCurrentIrpStackLocation(Irp);
+    status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return status;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
+}
+
+
 static NTSTATUS
 PdoDispatchPnp(
     IN  PXENFILT_PDO    Pdo,
@@ -1164,528 +1179,136 @@ PdoDispatchPnp(
         break;
 
     default:
-        status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
-        if (!NT_SUCCESS(status))
-            goto fail1;
-
-        IoSkipCurrentIrpStackLocation(Irp);
-
-        status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
-        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+        status = PdoDispatchDefault(Pdo, Irp);
         break;
     }
 
-    return status;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-PdoSetDevicePowerUp(
-    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;
-
-    ASSERT3U(DeviceState, <,  __PdoGetDevicePowerState(Pdo));
-
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-    if (!NT_SUCCESS(status))
-        goto done;
-
-    Trace("%s: %s -> %s\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(__PdoGetDevicePowerState(Pdo)),
-          DevicePowerStateName(DeviceState));
-
-    PowerState.DeviceState = DeviceState;
-    PoSetPowerState(__PdoGetDeviceObject(Pdo),
-                    DevicePowerState,
-                    PowerState);
-
-    __PdoSetDevicePowerState(Pdo, DeviceState);
-
-done:
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
     return status;
 }
 
-static NTSTATUS
-PdoSetDevicePowerDown(
-    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;
-
-    ASSERT3U(DeviceState, >,  __PdoGetDevicePowerState(Pdo));
-
-    Trace("%s: %s -> %s\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(__PdoGetDevicePowerState(Pdo)),
-          DevicePowerStateName(DeviceState));
-
-    PowerState.DeviceState = DeviceState;
-    PoSetPowerState(__PdoGetDeviceObject(Pdo),
-                    DevicePowerState,
-                    PowerState);
-
-    __PdoSetDevicePowerState(Pdo, DeviceState);
-
-    status = PdoForwardIrpSynchronously(Pdo, Irp);
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
 
 static NTSTATUS
-PdoSetDevicePower(
+PdoDispatchPowerImmediate(
     IN  PXENFILT_PDO    Pdo,
     IN  PIRP            Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
+    NTSTATUS status = STATUS_INTERNAL_ERROR;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    UCHAR MinorFunction = StackLocation->MinorFunction;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
-
-    Trace("%s: ====> (%s:%s)\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction));
-
-    if (DeviceState == __PdoGetDevicePowerState(Pdo)) {
-        status = PdoForwardIrpSynchronously(Pdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-        goto done;
-    }
-
-    status = (DeviceState < __PdoGetDevicePowerState(Pdo)) ?
-             PdoSetDevicePowerUp(Pdo, Irp) :
-             PdoSetDevicePowerDown(Pdo, Irp);
-
-done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction),
-          status);
-    return status;
-}
-
-static NTSTATUS
-PdoSetSystemPowerUp(
-    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);
-    if (!NT_SUCCESS(status))
-        goto done;
-
-    Trace("%s: %s -> %s\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(__PdoGetSystemPowerState(Pdo)),
-          SystemPowerStateName(SystemState));
-
-    __PdoSetSystemPowerState(Pdo, SystemState);
-
-done:
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-static NTSTATUS
-PdoSetSystemPowerDown(
-    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;
-}
-
-static NTSTATUS
-PdoSetSystemPower(
-    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);
-
-    return status;
-}
-
-static NTSTATUS
-PdoQueryDevicePower(
-    IN  PXENFILT_PDO    Pdo,
-    IN  PIRP            Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    DEVICE_POWER_STATE  DeviceState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    DeviceState = StackLocation->Parameters.Power.State.DeviceState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
+    if (MinorFunction != IRP_MN_SET_POWER)
+        goto fail1;
 
-    Trace("%s: ====> (%s:%s)\n",
-          __PdoGetName(Pdo),
-          DevicePowerStateName(DeviceState), 
-          PowerActionName(PowerAction));
+    POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;
 
-    if (DeviceState == __PdoGetDevicePowerState(Pdo)) {
-        status = PdoForwardIrpSynchronously(Pdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    switch (PowerType) {
+    case DevicePowerState:
+        POWER_STATE PowerState;
+        DEVICE_POWER_STATE DeviceState = 
StackLocation->Parameters.Power.State.DeviceState;
+        if (DeviceState >= __PdoGetDevicePowerState(Pdo))
+            goto fail3;
+
+        __PdoSetDevicePowerState(Pdo, DeviceState);
+        PowerState.DeviceState = DeviceState;
+        PoSetPowerState(__PdoGetDeviceObject(Pdo),
+                        DevicePowerState,
+                        PowerState);
+    break;
+    case SystemPowerState:
+        SYSTEM_POWER_STATE SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+        if (SystemState >= __PdoGetSystemPowerState(Pdo))
+            goto fail3;
 
-        goto done;
+        __PdoSetSystemPowerState(Pdo, SystemState);
+    break;
+    default:
+        goto fail2;
     }
 
-    status = (DeviceState < __PdoGetDevicePowerState(Pdo)) ?
-             PdoQueryDevicePowerUp(Pdo, Irp) :
-             PdoQueryDevicePowerDown(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);
-
-    return status;
-}
-
-static NTSTATUS
-PdoQuerySystemPowerDown(
-    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_SUCCESS;
 
+fail3:
+    Error("fail3 (%08x)\n", status);
+fail2:
+    Error("fail2 (%08x)\n", status);
+fail1:
+    Error("fail1 (%08x)\n", status);
     return status;
 }
 
-static NTSTATUS
-PdoQuerySystemPower(
+static VOID
+PdoCompletionPower(
     IN  PXENFILT_PDO    Pdo,
     IN  PIRP            Irp
-    )
+)
 {
-    PIO_STACK_LOCATION  StackLocation;
-    SYSTEM_POWER_STATE  SystemState;
-    POWER_ACTION        PowerAction;
-    NTSTATUS            status;
+    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    UCHAR MinorFunction = StackLocation->MinorFunction;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    SystemState = StackLocation->Parameters.Power.State.SystemState;
-    PowerAction = StackLocation->Parameters.Power.ShutdownType;
+    if (MinorFunction != IRP_MN_SET_POWER)
+        goto fail1;
 
-    Trace("%s: ====> (%s:%s)\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction));
+    POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;
 
-    if (SystemState == __PdoGetSystemPowerState(Pdo)) {
-        status = PdoForwardIrpSynchronously(Pdo, Irp);
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    switch (PowerType) {
+    case DevicePowerState:
+        POWER_STATE PowerState;
+        DEVICE_POWER_STATE DeviceState = 
StackLocation->Parameters.Power.State.DeviceState;
+        if (DeviceState <= __PdoGetDevicePowerState(Pdo))
+            goto fail3;
+
+        PowerState.DeviceState = DeviceState;
+        PoSetPowerState(__PdoGetDeviceObject(Pdo),
+                        DevicePowerState,
+                        PowerState);
+        __PdoSetDevicePowerState(Pdo, DeviceState);
+
+    break;
+    case SystemPowerState:
+        SYSTEM_POWER_STATE SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+        if (SystemState <= __PdoGetSystemPowerState(Pdo))
+            goto fail3;
 
-        goto done;
+        __PdoSetSystemPowerState(Pdo, SystemState);
+    break;
+    default:
+        goto fail2;
     }
 
-    status = (SystemState < __PdoGetSystemPowerState(Pdo)) ?
-             PdoQuerySystemPowerUp(Pdo, Irp) :
-             PdoQuerySystemPowerDown(Pdo, Irp);
+    return;
 
-done:
-    Trace("%s: <==== (%s:%s)(%08x)\n",
-          __PdoGetName(Pdo),
-          SystemPowerStateName(SystemState), 
-          PowerActionName(PowerAction),
-          status);
-
-    return status;
+fail3:
+    Error("fail3\n");
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1");
 }
 
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
 static NTSTATUS
-PdoDevicePower(
-    IN  PXENFILT_THREAD Self,
+PdoDispatchPowerCompletionV2(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp,
     IN  PVOID           Context
     )
 {
     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;
-
-        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;
+    UNREFERENCED_PARAMETER(DeviceObject);
 
-        default:
-            ASSERT(FALSE);
-            break;
-        }
+    if (Irp->PendingReturned)
+        IoMarkIrpPending(Irp);
 
-        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
-    }
+    //Assumption don't need STATUS_MORE_PROCESSING_REQUIRED.
+    PdoCompletionPower(Pdo, Irp);
 
+    IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
     return STATUS_SUCCESS;
 }
 
-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
 PdoDispatchPower(
@@ -1695,104 +1318,125 @@ PdoDispatchPower(
 {
     PIO_STACK_LOCATION  StackLocation;
     UCHAR               MinorFunction;
-    POWER_STATE_TYPE    PowerType;
     NTSTATUS            status;
-
-    status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
-    if (!NT_SUCCESS(status))
-        goto fail1;
+    XEN_IRP_STRATEGY    strategy;
+    BOOLEAN HaveRemoveLock = FALSE;
 
     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;
+    //Decide how we're going to handle this IRP.
+    switch(MinorFunction) {
+    case IRP_MN_QUERY_POWER:
+        strategy = XEN_IRP_PASSDOWN_TRANSPARENT; //Dont fail, don't need to 
check queries.
         break;
+    case IRP_MN_SET_POWER:
+        POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;
 
-    case SystemPowerState:
-        IoMarkIrpPending(Irp);
+        switch (PowerType) {
+        case DevicePowerState:
+            DEVICE_POWER_STATE DeviceState = 
StackLocation->Parameters.Power.State.DeviceState;
 
-        ASSERT3P(Pdo->SystemPowerIrp, ==, NULL);
-        Pdo->SystemPowerIrp = Irp;
-        KeMemoryBarrier();
-
-        ThreadWake(Pdo->SystemPowerThread);
-
-        status = STATUS_PENDING;
+            status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail1;
+
+            //If fails, then pending removal or already removed,
+            //freshly initialized (or not). Consider status to return...
+            HaveRemoveLock = TRUE;
+
+            if (DeviceState == __PdoGetDevicePowerState(Pdo)) {
+                strategy = XEN_IRP_PASSDOWN_TRANSPARENT;
+            } else if (DeviceState < __PdoGetDevicePowerState(Pdo)) {
+                strategy = XEN_IRP_HANDLE_INDISPATCH_PASSDOWN;
+            } else {
+                strategy = XEN_IRP_HANDLE_INCOMPLETION;
+            }
+        case SystemPowerState:
+            SYSTEM_POWER_STATE SystemState = 
StackLocation->Parameters.Power.State.SystemState;
+
+            status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail1;
+
+            //If fails, then pending removal or already removed,
+            //freshly initialized (or not). Consider status to return...
+            HaveRemoveLock = TRUE;
+
+            if (SystemState == __PdoGetSystemPowerState(Pdo)) {
+                strategy = XEN_IRP_PASSDOWN_TRANSPARENT;
+            } else if (SystemState < __PdoGetSystemPowerState(Pdo)) {
+                strategy = XEN_IRP_HANDLE_INDISPATCH_PASSDOWN;
+            } else {
+                strategy = XEN_IRP_HANDLE_INCOMPLETION;
+            }
         break;
-
+        default:
+            strategy = XEN_IRP_PASSDOWN_TRANSPARENT;
+        break;
+        }
     default:
-        IoSkipCurrentIrpStackLocation(Irp);
-
-        status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
-        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+        strategy = XEN_IRP_PASSDOWN_TRANSPARENT;
         break;
     }
 
-    Trace("%s: <==== (%02x:%s) (%08x)\n",
-          __PdoGetName(Pdo),
-          MinorFunction, 
-          PowerMinorFunctionName(MinorFunction),
-          status);
-
-done:
-    return status;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
+    switch(strategy) {
+        case XEN_IRP_HANDLE_INDISPATCH_PASSDOWN:
+            status = PdoDispatchPowerImmediate(Pdo, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail2;
+            //Fallthru.
+        case XEN_IRP_PASSDOWN_TRANSPARENT:
+        default:
+            IoSkipCurrentIrpStackLocation(Irp);
+            status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail3;
 
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            if (HaveRemoveLock)
+                IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+        break;
+        case XEN_IRP_HANDLE_INCOMPLETION:
+            IoMarkIrpPending(Irp);
+            IoCopyCurrentIrpStackLocationToNext(Irp);
+            IoSetCompletionRoutine(Irp,
+                                PdoDispatchPowerCompletionV2,
+                                Pdo,
+                               TRUE,
+                               TRUE,
+                               TRUE);
+            status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
+            if (!NT_SUCCESS(status))
+                goto fail4;
+            status = STATUS_PENDING; //Must return STATUS_PENDING after 
IoMarkIrpPending, whatever happens next.
+        break;
+    }
 
     return status;
-}
-
-static NTSTATUS
-PdoDispatchDefault(
-    IN  PXENFILT_PDO    Pdo,
-    IN  PIRP            Irp
-    )
-{
-    NTSTATUS            status;
 
-    status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    IoSkipCurrentIrpStackLocation(Irp);
-
-    status = IoCallDriver(Pdo->LowerDeviceObject, Irp);
-    IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+fail4:
+    //Error from lower driver, have remove lock, and completion routine.
+    //Comp routine shd be called on error to drop remove lock.
+    Error("fail4 (%08x)\n", status);
+    status = STATUS_PENDING; //Must return STATUS_PENDING after 
IoMarkIrpPending, whatever happens next.
+    return status;
 
+fail3:
+    //Error from lower driver, have remove lock, called down.
+    Error("fail3 (%08x)\n", status);
+    if (HaveRemoveLock)
+        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
     return status;
 
+fail2:
+    //Immediate error, have remove lock, not called down.
+    Error("fail2 (%08x)\n", status);
+    if (HaveRemoveLock)
+        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+    //Fallthru.
+
 fail1:
+    //Immediate error, no remove lock, not called down.
     Error("fail1 (%08x)\n", status);
 
     Irp->IoStatus.Status = status;
@@ -1907,14 +1551,6 @@ 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;
@@ -1968,20 +1604,6 @@ fail7:
 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");
-
     Pdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN;
     Pdo->PhysicalDeviceObject = NULL;
     Pdo->LowerDeviceObject = NULL;
@@ -2040,14 +1662,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®.