|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH 2/3] [XenBus] Asynchronous power handling.
From: Martin Harvey <Martin.Harvey@xxxxxxxxxx>
Replace a static, single thread for System and Device power transitions with
an IO_WORKITEM for each transition. IO_WORKITEMs are only used when a transition
requires calling codepaths that must be called at PASSIVE_LEVEL.
Move the bulk of power transitions to pending IRPs and IRP completion routines.
Signed-off-by: Martin Harvey <martin.harvey@xxxxxxxxxx>
Refactored to only apply to XenBus power
Signed-off-by: Owen Smith <owen.smith@xxxxxxxxx>
---
src/xenbus/fdo.c | 792 ++++++++++++++++++++++++++---------------------
src/xenbus/pdo.c | 250 ++++++---------
2 files changed, 534 insertions(+), 508 deletions(-)
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 976a7a3..3d35e77 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -107,9 +107,9 @@ struct _XENBUS_FDO {
ULONG Usage[DeviceUsageTypeDumpFile + 1];
BOOLEAN NotDisableable;
- PXENBUS_THREAD SystemPowerThread;
+ PIO_WORKITEM SystemPowerWorkItem;
PIRP SystemPowerIrp;
- PXENBUS_THREAD DevicePowerThread;
+ PIO_WORKITEM DevicePowerWorkItem;
PIRP DevicePowerIrp;
CHAR VendorName[MAXNAMELEN];
@@ -4800,38 +4800,105 @@ FdoDispatchPnp(
return status;
}
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
+static VOID
+FdoSetDevcePowerUpWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ )
+{
+ PXENBUS_FDO Fdo = (PXENBUS_FDO) Context;
+ PIRP Irp;
+
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ Irp = InterlockedExchangePointer(&Fdo->DevicePowerIrp, NULL);
+ ASSERT(Irp != NULL);
+
+ (VOID) FdoD3ToD0(Fdo);
+
+ /* Cannot change Irp->IoStatus */
+ /* Continue completion chain */
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
static NTSTATUS
-FdoSetDevicePowerUp(
- IN PXENBUS_FDO Fdo,
- IN PIRP Irp
+FdoSetDevicePowerUpComplete(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context
)
{
+ PXENBUS_FDO Fdo = (PXENBUS_FDO) Context;
PIO_STACK_LOCATION StackLocation;
DEVICE_POWER_STATE DeviceState;
- NTSTATUS status;
+
+ UNREFERENCED_PARAMETER(DeviceObject);
StackLocation = IoGetCurrentIrpStackLocation(Irp);
DeviceState = StackLocation->Parameters.Power.State.DeviceState;
- ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo));
-
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- if (!NT_SUCCESS(status))
- goto done;
-
- Info("%s: %s -> %s\n",
- __FdoGetName(Fdo),
+ /* Already marked pending by us */
+ Info("%s -> %s\n",
DevicePowerStateName(__FdoGetDevicePowerState(Fdo)),
DevicePowerStateName(DeviceState));
+ /* Don't worry about IRP IoStatus */
ASSERT3U(DeviceState, ==, PowerDeviceD0);
- status = FdoD3ToD0(Fdo);
- ASSERT(NT_SUCCESS(status));
-done:
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ (VOID) InterlockedExchangePointer(&Fdo->DevicePowerIrp, Irp);
- return status;
+ IoQueueWorkItem(Fdo->DevicePowerWorkItem,
+ FdoSetDevcePowerUpWorker,
+ DelayedWorkQueue,
+ Fdo);
+
+ /* Stop completion chain in all circumstances. */
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+static NTSTATUS
+FdoSetDevicePowerUp(
+ IN PXENBUS_FDO Fdo,
+ IN PIRP Irp
+ )
+{
+ IoMarkIrpPending(Irp);
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ FdoSetDevicePowerUpComplete,
+ Fdo,
+ TRUE,
+ TRUE,
+ TRUE);
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
+ return STATUS_PENDING;
+}
+
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
+static VOID
+FdoSetDevicePowerDownWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ )
+{
+ PXENBUS_FDO Fdo = (PXENBUS_FDO)Context;
+ PIRP Irp;
+
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ Irp = InterlockedExchangePointer(&Fdo->DevicePowerIrp, NULL);
+ ASSERT(Irp != NULL);
+
+ FdoD0ToD3(Fdo);
+
+ /* We are on dispatch path here, irp pended. */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
}
static NTSTATUS
@@ -4856,12 +4923,24 @@ FdoSetDevicePowerDown(
ASSERT3U(DeviceState, ==, PowerDeviceD3);
- if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0)
- FdoD0ToD3(Fdo);
+ if (__FdoGetDevicePowerState(Fdo) != PowerDeviceD0) {
+ IoSkipCurrentIrpStackLocation(Irp);
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ goto done;
+ }
+
+ IoMarkIrpPending(Irp);
+ status = STATUS_PENDING;
+
+ (VOID) InterlockedExchangePointer(&Fdo->DevicePowerIrp, Irp);
+ IoQueueWorkItem(Fdo->DevicePowerWorkItem,
+ FdoSetDevicePowerDownWorker,
+ DelayedWorkQueue,
+ Fdo);
+
+done:
return status;
}
@@ -4884,11 +4963,9 @@ 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;
}
@@ -4907,8 +4984,8 @@ done:
__drv_functionClass(REQUEST_POWER_COMPLETE)
__drv_sameIRQL
-VOID
-FdoRequestSetDevicePowerCompletion(
+static VOID
+FdoRequestDevicePowerUpComplete(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
@@ -4916,112 +4993,204 @@ 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));
-
- KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+ /* Although can change Irp->IoStatus for pended IRP, drivers should not
fail this. */
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
-__drv_requiresIRQL(PASSIVE_LEVEL)
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
static VOID
-FdoRequestSetDevicePower(
- IN PXENBUS_FDO Fdo,
- IN DEVICE_POWER_STATE DeviceState
+FdoSetSystemPowerUpWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
)
{
- POWER_STATE PowerState;
- KEVENT Event;
- NTSTATUS status;
+ PXENBUS_FDO Fdo = (PXENBUS_FDO)Context;
+ PIRP Irp;
+ PIO_STACK_LOCATION StackLocation;
+ SYSTEM_POWER_STATE SystemState;
+ POWER_STATE PowerState;
+ NTSTATUS status;
- Trace("%s\n", DevicePowerStateName(DeviceState));
+ UNREFERENCED_PARAMETER(DeviceObject);
- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+ Irp = InterlockedExchangePointer(&Fdo->SystemPowerIrp, NULL);
+ ASSERT(Irp != NULL);
- PowerState.DeviceState = DeviceState;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ __FdoSetSystemPowerState(Fdo, PowerSystemHibernate);
+ FdoS4ToS3(Fdo);
+
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ SystemState = StackLocation->Parameters.Power.State.SystemState;
+
+ Info("%s -> %s\n",
+ SystemPowerStateName(__FdoGetSystemPowerState(Fdo)),
+ SystemPowerStateName(SystemState));
+
+ __FdoSetSystemPowerState(Fdo, SystemState);
+
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
IRP_MN_SET_POWER,
PowerState,
- FdoRequestSetDevicePowerCompletion,
- &Event,
+ FdoRequestDevicePowerUpComplete,
+ Irp,
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; /* FdoRequestDevicePowerUpComplete will complete the request.*/
+
+fail1:
+ Error("fail1 - but continue IRP processing. (%08x)\n", status);
+ /* Although can change Irp->IoStatus for pended IRP, drivers should not
fail this. */
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
static NTSTATUS
-FdoSetSystemPowerUp(
- IN PXENBUS_FDO Fdo,
- IN PIRP Irp
+FdoSetSystemPowerUpComplete(
+ 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;
+ POWER_STATE PowerState;
NTSTATUS status;
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ /* IRP marked as pending on dispatch path, no need to check pending
returned */
+
+ /* Don't worry about IRP IoStatus */
StackLocation = IoGetCurrentIrpStackLocation(Irp);
SystemState = StackLocation->Parameters.Power.State.SystemState;
- ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo));
+ if (SystemState < PowerSystemHibernate &&
+ __FdoGetSystemPowerState(Fdo) >= PowerSystemHibernate) {
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- if (!NT_SUCCESS(status))
- goto done;
+ (VOID) InterlockedExchangePointer(&Fdo->SystemPowerIrp, Irp);
- Info("%s: %s -> %s\n",
- __FdoGetName(Fdo),
- SystemPowerStateName(__FdoGetSystemPowerState(Fdo)),
- SystemPowerStateName(SystemState));
+ IoQueueWorkItem(Fdo->SystemPowerWorkItem,
+ FdoSetSystemPowerUpWorker,
+ DelayedWorkQueue,
+ Fdo);
- if (SystemState < PowerSystemHibernate &&
- __FdoGetSystemPowerState(Fdo) >= PowerSystemHibernate) {
- __FdoSetSystemPowerState(Fdo, PowerSystemHibernate);
- FdoS4ToS3(Fdo);
+ goto done; /* Stop completion routine for the moment... */
}
+ Info("%s -> %s\n",
+ SystemPowerStateName(__FdoGetSystemPowerState(Fdo)),
+ SystemPowerStateName(SystemState));
+
__FdoSetSystemPowerState(Fdo, SystemState);
- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
- FdoRequestSetDevicePower(Fdo, DeviceState);
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+
+ status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+ IRP_MN_SET_POWER,
+ PowerState,
+ FdoRequestDevicePowerUpComplete,
+ Irp,
+ NULL);
+ /* Whatever happens, we have stopped completion processing for SIrp,
+ to restart SIrp processing, call IoCompleteRequest. */
+ if (!NT_SUCCESS(status))
+ goto fail1;
done:
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_MORE_PROCESSING_REQUIRED; /* FdoRequestDevicePowerUpComplete
will complete the request.*/
- return status;
+fail1:
+ Error("fail1 - but continue IRP processing. (%08x)\n", status);
+ /* marked pending on dispatch path, don't change Irp->IoStatus, keep
going.*/
+ return STATUS_CONTINUE_COMPLETION;
}
static NTSTATUS
-FdoSetSystemPowerDown(
+FdoSetSystemPowerUp(
IN PXENBUS_FDO Fdo,
IN PIRP Irp
)
{
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ FdoSetSystemPowerUpComplete,
+ Fdo,
+ TRUE,
+ TRUE,
+ TRUE);
+ return IoCallDriver(Fdo->LowerDeviceObject, Irp);
+}
+
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
+static VOID
+FdoSetSystemPowerDownWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ )
+{
+ PXENBUS_FDO Fdo = (PXENBUS_FDO)Context;
PIO_STACK_LOCATION StackLocation;
SYSTEM_POWER_STATE SystemState;
- DEVICE_POWER_STATE DeviceState;
- NTSTATUS status;
+ PIRP Irp;
+
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ Irp = InterlockedExchangePointer(&Fdo->SystemPowerIrp, NULL);
+ ASSERT(Irp != NULL);
StackLocation = IoGetCurrentIrpStackLocation(Irp);
SystemState = StackLocation->Parameters.Power.State.SystemState;
- ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo));
+ /* Meet preconditions for S3 to S4 */
+ __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
+ FdoS3ToS4(Fdo);
+ __FdoSetSystemPowerState(Fdo, SystemState);
- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
+}
- FdoRequestSetDevicePower(Fdo, DeviceState);
+__drv_functionClass(REQUEST_POWER_COMPLETE)
+__drv_sameIRQL
+static VOID
+FdoRequestDevicePowerDownComplete(
+ 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);
+
+ if (!NT_SUCCESS(IoStatus->Status))
+ Error("fail1 - but continue IRP processing. (%08x)\n",
IoStatus->Status);
Info("%s: %s -> %s\n",
__FdoGetName(Fdo),
@@ -5030,145 +5199,118 @@ FdoSetSystemPowerDown(
if (SystemState >= PowerSystemHibernate &&
__FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) {
- __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
- FdoS3ToS4(Fdo);
+
+ (VOID) InterlockedExchangePointer(&Fdo->SystemPowerIrp, Irp);
+
+ IoQueueWorkItem(Fdo->SystemPowerWorkItem,
+ FdoSetSystemPowerDownWorker,
+ DelayedWorkQueue,
+ Fdo);
+ goto done;
}
__FdoSetSystemPowerState(Fdo, SystemState);
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
- return status;
+done:
+ return;
}
static NTSTATUS
-FdoSetSystemPower(
+FdoSetSystemPowerDown(
IN PXENBUS_FDO Fdo,
IN PIRP Irp
)
{
PIO_STACK_LOCATION StackLocation;
SYSTEM_POWER_STATE SystemState;
- POWER_ACTION PowerAction;
+ POWER_STATE PowerState;
NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
SystemState = StackLocation->Parameters.Power.State.SystemState;
- PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Trace("====> (%s:%s)\n",
- SystemPowerStateName(SystemState),
- PowerActionName(PowerAction));
+ ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo));
- ASSERT3U(PowerAction, <, PowerActionShutdown);
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
- if (SystemState == __FdoGetSystemPowerState(Fdo)) {
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ if (SystemState >= PowerSystemShutdown) {
+ /* No DIrp generation, no FDO Powerdown.
+ Legacy shutdown just yanks system power.
+ Best device state for S5 is advertised as D3,
+ which is not *really* the case, but we can't increase it. */
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
goto done;
}
- status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?
- FdoSetSystemPowerUp(Fdo, Irp) :
- FdoSetSystemPowerDown(Fdo, Irp);
+ status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+ IRP_MN_SET_POWER,
+ PowerState,
+ FdoRequestDevicePowerDownComplete,
+ Irp,
+ NULL);
+ if (!NT_SUCCESS(status))
+ goto fail1;
done:
- Trace("<==== (%s:%s)(%08x)\n",
- SystemPowerStateName(SystemState),
- PowerActionName(PowerAction),
- status);
- return status;
-}
-
-static NTSTATUS
-FdoQueryDevicePowerUp(
- IN PXENBUS_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 PXENBUS_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);
+fail1:
+ /* In theory could change IRP status, but are not supposed to fail this
IRP. */
+ Error("fail1 - but continue IRP processing. (%08x)\n", status);
return status;
}
static NTSTATUS
-FdoQueryDevicePower(
+FdoSetSystemPower(
IN PXENBUS_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;
+ /* IRP_MN_SET_POWER Setting system power, IRP's *must* be pended. */
+ IoMarkIrpPending(Irp);
+
Trace("====> (%s:%s)\n",
- DevicePowerStateName(DeviceState),
+ SystemPowerStateName(SystemState),
PowerActionName(PowerAction));
- ASSERT3U(PowerAction, <, PowerActionShutdown);
-
- if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ if (SystemState == __FdoGetSystemPowerState(Fdo)) {
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Pended, copy not skip */
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
goto done;
}
- status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ?
- FdoQueryDevicePowerUp(Fdo, Irp) :
- FdoQueryDevicePowerDown(Fdo, Irp);
+ status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?
+ FdoSetSystemPowerUp(Fdo, Irp) :
+ FdoSetSystemPowerDown(Fdo, Irp);
done:
Trace("<==== (%s:%s)(%08x)\n",
- DevicePowerStateName(DeviceState),
+ SystemPowerStateName(SystemState),
PowerActionName(PowerAction),
status);
+
return status;
}
__drv_functionClass(REQUEST_POWER_COMPLETE)
__drv_sameIRQL
-VOID
-FdoRequestQueryDevicePowerCompletion(
+static VOID
+FdoRequestQuerySystemPowerUpComplete(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
@@ -5176,48 +5318,56 @@ 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
+FdoQuerySystemPowerUpComplete(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context
)
{
- POWER_STATE PowerState;
- KEVENT Event;
- NTSTATUS status;
-
- Trace("%s\n", DevicePowerStateName(DeviceState));
+ PXENBUS_FDO Fdo = (PXENBUS_FDO) Context;
+ PIO_STACK_LOCATION StackLocation;
+ SYSTEM_POWER_STATE SystemState;
+ POWER_STATE PowerState;
+ NTSTATUS status;
- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+ UNREFERENCED_PARAMETER(DeviceObject);
- PowerState.DeviceState = DeviceState;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ /* IRP marked as pending on dispatch path. */
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ SystemState = StackLocation->Parameters.Power.State.SystemState;
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
IRP_MN_QUERY_POWER,
PowerState,
- FdoRequestQueryDevicePowerCompletion,
- &Event,
+ FdoRequestQuerySystemPowerUpComplete,
+ Irp,
NULL);
- ASSERT(NT_SUCCESS(status));
+ if (!NT_SUCCESS(status))
+ goto fail1;
- (VOID) KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
+ return STATUS_MORE_PROCESSING_REQUIRED;
+
+fail1:
+ /* Irp marked as pending on dispatch path, so can change final IoStatus,
pass to completion routine above. */
+ Error("fail1 (%08x)\n", status);
+ Irp->IoStatus.Status = status;
+
+ return STATUS_CONTINUE_COMPLETION;
}
static NTSTATUS
@@ -5226,29 +5376,50 @@ FdoQuerySystemPowerUp(
IN PIRP Irp
)
{
+ IoMarkIrpPending(Irp); /* Must mark IRP pending because we want to
complete it *after* completion routine. */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ FdoQuerySystemPowerUpComplete,
+ Fdo,
+ TRUE,
+ TRUE,
+ TRUE);
+ return IoCallDriver(Fdo->LowerDeviceObject, Irp);
+}
- PIO_STACK_LOCATION StackLocation;
- SYSTEM_POWER_STATE SystemState;
- DEVICE_POWER_STATE DeviceState;
- NTSTATUS status;
-
- StackLocation = IoGetCurrentIrpStackLocation(Irp);
- SystemState = StackLocation->Parameters.Power.State.SystemState;
+__drv_functionClass(REQUEST_POWER_COMPLETE)
+__drv_sameIRQL
+static VOID
+FdoRequestQuerySystemPowerDownComplete(
+ 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;
- ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo));
+ UNREFERENCED_PARAMETER(DeviceObject);
+ UNREFERENCED_PARAMETER(MinorFunction);
+ UNREFERENCED_PARAMETER(PowerState);
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- if (!NT_SUCCESS(status))
- goto done;
+ if (!NT_SUCCESS(IoStatus->Status))
+ goto fail1;
- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended. */
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
- FdoRequestQueryDevicePower(Fdo, DeviceState);
+ return;
-done:
+fail1:
+ Error("fail1 (%08x)\n", IoStatus->Status);
+ Irp->IoStatus.Status = IoStatus->Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return status;
}
static NTSTATUS
@@ -5259,7 +5430,7 @@ FdoQuerySystemPowerDown(
{
PIO_STACK_LOCATION StackLocation;
SYSTEM_POWER_STATE SystemState;
- DEVICE_POWER_STATE DeviceState;
+ POWER_STATE PowerState;
NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
@@ -5267,11 +5438,24 @@ FdoQuerySystemPowerDown(
ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo));
- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
- FdoRequestQueryDevicePower(Fdo, DeviceState);
+ status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+ IRP_MN_QUERY_POWER,
+ PowerState,
+ FdoRequestQuerySystemPowerDownComplete,
+ Irp,
+ NULL);
+ if (!NT_SUCCESS(status))
+ goto fail1;
- status = FdoForwardIrpSynchronously(Fdo, Irp);
+ IoMarkIrpPending(Irp);
+ return STATUS_PENDING;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
@@ -5296,11 +5480,9 @@ 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;
}
@@ -5319,117 +5501,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;
+ PIO_STACK_LOCATION StackLocation;
+ NTSTATUS status;
- switch (StackLocation->MinorFunction) {
- case IRP_MN_SET_POWER:
- (VOID) FdoSetDevicePower(Fdo, Irp);
- break;
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
- case IRP_MN_QUERY_POWER:
- (VOID) FdoQueryDevicePower(Fdo, Irp);
- break;
+ switch (StackLocation->MinorFunction) {
+ case IRP_MN_SET_POWER:
+ status = FdoSetDevicePower(Fdo, Irp);
+ break;
- default:
- ASSERT(FALSE);
- break;
- }
+ default:
+ IoSkipCurrentIrpStackLocation(Irp);
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+ break;
}
- return STATUS_SUCCESS;
+ return status;
}
static NTSTATUS
-FdoSystemPower(
- IN 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);
- }
-
- if (ThreadIsAlerted(Self))
- break;
-
- Irp = Fdo->SystemPowerIrp;
-
- if (Irp == NULL)
- continue;
-
- Fdo->SystemPowerIrp = NULL;
- KeMemoryBarrier();
+ PIO_STACK_LOCATION StackLocation;
+ NTSTATUS status;
- StackLocation = IoGetCurrentIrpStackLocation(Irp);
- MinorFunction = StackLocation->MinorFunction;
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
- switch (StackLocation->MinorFunction) {
- case IRP_MN_SET_POWER:
- (VOID) FdoSetSystemPower(Fdo, Irp);
- break;
+ switch (StackLocation->MinorFunction) {
+ case IRP_MN_SET_POWER:
+ status = FdoSetSystemPower(Fdo, Irp);
+ break;
- case IRP_MN_QUERY_POWER:
- (VOID) FdoQuerySystemPower(Fdo, Irp);
- break;
+ case IRP_MN_QUERY_POWER:
+ status = FdoQuerySystemPower(Fdo, Irp);
+ break;
- default:
- ASSERT(FALSE);
- break;
- }
+ default:
+ IoSkipCurrentIrpStackLocation(Irp);
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+ break;
}
- return STATUS_SUCCESS;
+ return status;
}
static NTSTATUS
@@ -5439,55 +5561,21 @@ FdoDispatchPower(
)
{
PIO_STACK_LOCATION StackLocation;
- UCHAR MinorFunction;
POWER_STATE_TYPE PowerType;
POWER_ACTION PowerAction;
NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
- MinorFunction = StackLocation->MinorFunction;
-
- if (MinorFunction != IRP_MN_QUERY_POWER &&
- MinorFunction != IRP_MN_SET_POWER) {
- IoSkipCurrentIrpStackLocation(Irp);
- status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-
- goto done;
- }
-
PowerType = StackLocation->Parameters.Power.Type;
PowerAction = StackLocation->Parameters.Power.ShutdownType;
- if (PowerAction >= PowerActionShutdown) {
- IoSkipCurrentIrpStackLocation(Irp);
- status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-
- goto done;
- }
-
switch (PowerType) {
case DevicePowerState:
- IoMarkIrpPending(Irp);
-
- ASSERT3P(Fdo->DevicePowerIrp, ==, NULL);
- Fdo->DevicePowerIrp = Irp;
- KeMemoryBarrier();
-
- ThreadWake(Fdo->DevicePowerThread);
-
- status = STATUS_PENDING;
+ status = 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:
@@ -5496,10 +5584,10 @@ FdoDispatchPower(
break;
}
-done:
return status;
}
+
static NTSTATUS
FdoDispatchDefault(
IN PXENBUS_FDO Fdo,
@@ -5748,12 +5836,12 @@ FdoCreate(
Fdo->LowerDeviceObject = IoAttachDeviceToDeviceStack(FunctionDeviceObject,
PhysicalDeviceObject);
- status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread);
- if (!NT_SUCCESS(status))
+ Fdo->SystemPowerWorkItem = IoAllocateWorkItem(FunctionDeviceObject);
+ if (Fdo->SystemPowerWorkItem == NULL)
goto fail3;
- status = ThreadCreate(FdoDevicePower, Fdo, &Fdo->DevicePowerThread);
- if (!NT_SUCCESS(status))
+ Fdo->DevicePowerWorkItem = IoAllocateWorkItem(FunctionDeviceObject);
+ if (Fdo->DevicePowerWorkItem == NULL)
goto fail4;
status = FdoAcquireLowerBusInterface(Fdo);
@@ -5992,17 +6080,15 @@ fail6:
fail5:
Error("fail5\n");
- ThreadAlert(Fdo->DevicePowerThread);
- ThreadJoin(Fdo->DevicePowerThread);
- Fdo->DevicePowerThread = NULL;
-
+ IoFreeWorkItem(Fdo->DevicePowerWorkItem);
+ Fdo->DevicePowerWorkItem = NULL;
+
fail4:
Error("fail4\n");
- ThreadAlert(Fdo->SystemPowerThread);
- ThreadJoin(Fdo->SystemPowerThread);
- Fdo->SystemPowerThread = NULL;
-
+ IoFreeWorkItem(Fdo->SystemPowerWorkItem);
+ Fdo->SystemPowerWorkItem = NULL;
+
fail3:
Error("fail3\n");
@@ -6117,13 +6203,11 @@ FdoDestroy(
FdoReleaseLowerBusInterface(Fdo);
- ThreadAlert(Fdo->DevicePowerThread);
- ThreadJoin(Fdo->DevicePowerThread);
- Fdo->DevicePowerThread = NULL;
+ IoFreeWorkItem(Fdo->DevicePowerWorkItem);
+ Fdo->DevicePowerWorkItem = NULL;
- ThreadAlert(Fdo->SystemPowerThread);
- ThreadJoin(Fdo->SystemPowerThread);
- Fdo->SystemPowerThread = NULL;
+ IoFreeWorkItem(Fdo->SystemPowerWorkItem);
+ Fdo->SystemPowerWorkItem = NULL;
IoDetachDevice(Fdo->LowerDeviceObject);
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 3f1e4c5..9163923 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -58,9 +58,9 @@
struct _XENBUS_PDO {
PXENBUS_DX Dx;
- PXENBUS_THREAD SystemPowerThread;
+ PIO_WORKITEM SystemPowerWorkItem;
PIRP SystemPowerIrp;
- PXENBUS_THREAD DevicePowerThread;
+ PIO_WORKITEM DevicePowerWorkItem;
PIRP DevicePowerIrp;
PXENBUS_FDO Fdo;
@@ -1695,26 +1695,31 @@ PdoDispatchPnp(
return status;
}
-static NTSTATUS
-PdoSetDevicePower(
- IN PXENBUS_PDO Pdo,
- IN PIRP Irp
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
+static VOID
+PdoSetDevicePowerWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
)
{
+ PXENBUS_PDO Pdo = (PXENBUS_PDO) Context;
+ PIRP Irp;
+ NTSTATUS status;
PIO_STACK_LOCATION StackLocation;
DEVICE_POWER_STATE DeviceState;
POWER_ACTION PowerAction;
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ Irp = InterlockedExchangePointer(&Pdo->DevicePowerIrp, NULL);
+ ASSERT(Irp != NULL);
+
StackLocation = IoGetCurrentIrpStackLocation(Irp);
DeviceState = StackLocation->Parameters.Power.State.DeviceState;
PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Trace("====> (%s:%s)\n",
- DevicePowerStateName(DeviceState),
- PowerActionName(PowerAction));
-
- ASSERT3U(PowerAction, <, PowerActionShutdown);
-
+ status = STATUS_SUCCESS;
if (__PdoGetDevicePowerState(Pdo) > DeviceState) {
Trace("%s: POWERING UP: %s -> %s\n",
__PdoGetName(Pdo),
@@ -1722,7 +1727,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),
@@ -1733,76 +1738,76 @@ 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
+PdoSetDevicePower(
+ 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);
- }
+ PIO_STACK_LOCATION StackLocation;
+ DEVICE_POWER_STATE DeviceState;
+ POWER_ACTION PowerAction;
- if (ThreadIsAlerted(Self))
- break;
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ DeviceState = StackLocation->Parameters.Power.State.DeviceState;
+ PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Irp = Pdo->DevicePowerIrp;
+ Trace("====> (%s:%s)\n",
+ DevicePowerStateName(DeviceState),
+ PowerActionName(PowerAction));
- if (Irp == NULL)
- continue;
+ IoMarkIrpPending(Irp);
- Pdo->DevicePowerIrp = NULL;
- KeMemoryBarrier();
+ (VOID) InterlockedExchangePointer(&Pdo->DevicePowerIrp, Irp);
- (VOID) PdoSetDevicePower(Pdo, Irp);
- }
+ IoQueueWorkItem(Pdo->DevicePowerWorkItem,
+ PdoSetDevicePowerWorker,
+ DelayedWorkQueue,
+ Pdo);
- return STATUS_SUCCESS;
+ return STATUS_PENDING;
}
-static NTSTATUS
-PdoSetSystemPower(
- IN PXENBUS_PDO Pdo,
- IN PIRP Irp
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
+static VOID
+PdoSetSystemPowerWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
)
{
+ PXENBUS_PDO Pdo = (PXENBUS_PDO) Context;
+ PIRP Irp;
PIO_STACK_LOCATION StackLocation;
SYSTEM_POWER_STATE SystemState;
POWER_ACTION PowerAction;
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ Irp = InterlockedExchangePointer(&Pdo->SystemPowerIrp, NULL);
+ ASSERT(Irp != NULL);
+
StackLocation = IoGetCurrentIrpStackLocation(Irp);
SystemState = StackLocation->Parameters.Power.State.SystemState;
PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Trace("====> (%s:%s)\n",
- SystemPowerStateName(SystemState),
- PowerActionName(PowerAction));
-
- ASSERT3U(PowerAction, <, PowerActionShutdown);
-
if (__PdoGetSystemPowerState(Pdo) > SystemState) {
if (SystemState < PowerSystemHibernate &&
__PdoGetSystemPowerState(Pdo) >= PowerSystemHibernate) {
@@ -1836,52 +1841,40 @@ PdoSetSystemPower(
Trace("<==== (%s:%s)\n",
SystemPowerStateName(SystemState),
PowerActionName(PowerAction));
-
- return STATUS_SUCCESS;
}
static NTSTATUS
-PdoSystemPower(
- IN PXENBUS_THREAD Self,
- IN PVOID Context
+PdoSetSystemPower(
+ IN PXENBUS_PDO Pdo,
+ IN PIRP Irp
)
{
- PXENBUS_PDO Pdo = Context;
- PKEVENT Event;
-
- Event = ThreadGetEvent(Self);
-
- for (;;) {
- PIRP Irp;
-
- if (Pdo->SystemPowerIrp == NULL) {
- (VOID) KeWaitForSingleObject(Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- KeClearEvent(Event);
- }
+ PIO_STACK_LOCATION StackLocation;
+ SYSTEM_POWER_STATE SystemState;
+ POWER_ACTION PowerAction;
- if (ThreadIsAlerted(Self))
- break;
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ SystemState = StackLocation->Parameters.Power.State.SystemState;
+ PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Irp = Pdo->SystemPowerIrp;
+ Trace("====> (%s:%s)\n",
+ SystemPowerStateName(SystemState),
+ PowerActionName(PowerAction));
- if (Irp == NULL)
- continue;
+ IoMarkIrpPending(Irp);
- Pdo->SystemPowerIrp = NULL;
- KeMemoryBarrier();
+ (VOID) InterlockedExchangePointer(&Pdo->SystemPowerIrp, Irp);
- (VOID) PdoSetSystemPower(Pdo, Irp);
- }
+ IoQueueWorkItem(Pdo->SystemPowerWorkItem,
+ PdoSetSystemPowerWorker,
+ DelayedWorkQueue,
+ Pdo);
- return STATUS_SUCCESS;
+ return STATUS_PENDING;
}
static NTSTATUS
-PdoSetPower(
+PdoDispatchSetPower(
IN PXENBUS_PDO Pdo,
IN PIRP Irp
)
@@ -1895,38 +1888,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 = PdoSetDevicePower(Pdo, Irp);
break;
case SystemPowerState:
- IoMarkIrpPending(Irp);
-
- ASSERT3P(Pdo->SystemPowerIrp, ==, NULL);
- Pdo->SystemPowerIrp = Irp;
- KeMemoryBarrier();
-
- ThreadWake(Pdo->SystemPowerThread);
-
- status = STATUS_PENDING;
+ status = PdoSetSystemPower(Pdo, Irp);
break;
default:
@@ -1935,25 +1903,6 @@ PdoSetPower(
break;
}
-done:
- return status;
-}
-
-static NTSTATUS
-PdoQueryPower(
- IN PXENBUS_PDO Pdo,
- IN PIRP Irp
- )
-{
- NTSTATUS status;
-
- UNREFERENCED_PARAMETER(Pdo);
-
- status = STATUS_SUCCESS;
-
- Irp->IoStatus.Status = status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
return status;
}
@@ -1972,14 +1921,11 @@ PdoDispatchPower(
switch (StackLocation->MinorFunction) {
case IRP_MN_SET_POWER:
- status = PdoSetPower(Pdo, Irp);
- break;
-
- case IRP_MN_QUERY_POWER:
- status = PdoQueryPower(Pdo, Irp);
+ status = PdoDispatchSetPower(Pdo, Irp);
break;
default:
+ /* TODO - Always complete with status success?? */
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
@@ -2093,12 +2039,12 @@ PdoCreate(
Pdo->Dx = Dx;
Pdo->Fdo = Fdo;
- status = ThreadCreate(PdoSystemPower, Pdo, &Pdo->SystemPowerThread);
- if (!NT_SUCCESS(status))
+ Pdo->SystemPowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject);
+ if (Pdo->SystemPowerWorkItem == NULL)
goto fail3;
- status = ThreadCreate(PdoDevicePower, Pdo, &Pdo->DevicePowerThread);
- if (!NT_SUCCESS(status))
+ Pdo->DevicePowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject);
+ if (Pdo->DevicePowerWorkItem == NULL)
goto fail4;
__PdoSetName(Pdo, Name);
@@ -2135,16 +2081,14 @@ fail5:
Pdo->Ejectable = FALSE;
Pdo->Removable = FALSE;
- ThreadAlert(Pdo->DevicePowerThread);
- ThreadJoin(Pdo->DevicePowerThread);
- Pdo->DevicePowerThread = NULL;
+ IoFreeWorkItem(Pdo->DevicePowerWorkItem);
+ Pdo->DevicePowerWorkItem = NULL;
fail4:
Error("fail4\n");
- ThreadAlert(Pdo->SystemPowerThread);
- ThreadJoin(Pdo->SystemPowerThread);
- Pdo->SystemPowerThread = NULL;
+ IoFreeWorkItem(Pdo->SystemPowerWorkItem);
+ Pdo->SystemPowerWorkItem = NULL;
fail3:
Error("fail3\n");
@@ -2198,13 +2142,11 @@ 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;
+ IoFreeWorkItem(Pdo->DevicePowerWorkItem);
+ Pdo->DevicePowerWorkItem = NULL;
+
+ IoFreeWorkItem(Pdo->SystemPowerWorkItem);
+ Pdo->SystemPowerWorkItem = NULL;
Pdo->Fdo = NULL;
Pdo->Dx = NULL;
--
2.41.0.windows.3
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |