+ PowerSystemStateName(__FdoGetSystemPowerState(Fdo)),
+ PowerSystemStateName(SystemState));
+
+ __FdoSetSystemPowerState(Fdo, SystemState);
+
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+
+ status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+ IRP_MN_SET_POWER,
+ PowerState,
+ FdoRequestSetDevicePowerUpComplete,
+ Irp,
+ NULL);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+ }
+
+ /* Will later complete the IRP (which is marked pending, in worker or 2nd
level comp routine.)*/
+ return STATUS_MORE_PROCESSING_REQUIRED;
+
+fail1:
+ Error("fail1 - but continue IRP processing. (%08x)\n", status);
+ /* marked pending on dispatch path, don't change Irp->IoStatus, keep
going.*/
+ return STATUS_CONTINUE_COMPLETION;
}
static FORCEINLINE NTSTATUS
@@ -2337,42 +2509,103 @@ __FdoSetSystemPowerUp(
IN PIRP Irp
)
{
-
PIO_STACK_LOCATION StackLocation;
SYSTEM_POWER_STATE SystemState;
- DEVICE_POWER_STATE DeviceState;
- NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
SystemState = StackLocation->Parameters.Power.State.SystemState;
ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo));
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- if (!NT_SUCCESS(status))
- goto done;
+ /* IRP already pended, and we want to complete it *after* completion
routine. */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ FdoSetSystemPowerUpComplete,
+ Fdo,
+ TRUE,
+ TRUE,
+ TRUE);
- Info("%s: %s -> %s\n",
- __FdoGetName(Fdo),
- PowerSystemStateName(__FdoGetSystemPowerState(Fdo)),
- PowerSystemStateName(SystemState));
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
- if (SystemState < PowerSystemHibernate &&
- __FdoGetSystemPowerState(Fdo) >= PowerSystemHibernate) {
- __FdoSetSystemPowerState(Fdo, PowerSystemHibernate);
- FdoS4ToS3(Fdo);
- }
+ return STATUS_PENDING;
+}
+
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
+static VOID
+FdoSystemPowerDownWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
+ )
+{
+ PXENVIF_FDO Fdo = (PXENVIF_FDO) Context;
+ PIRP Irp;
+ PIO_STACK_LOCATION StackLocation;
+ SYSTEM_POWER_STATE SystemState;
+
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ Irp = InterlockedExchangePointer(&Fdo->SystemPowerIrp, NULL);
+ ASSERT(Irp != NULL);
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ SystemState = StackLocation->Parameters.Power.State.SystemState;
+
+ __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
+ FdoS3ToS4(Fdo);
__FdoSetSystemPowerState(Fdo, SystemState);
- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
- FdoRequestSetDevicePower(Fdo, DeviceState);
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
+}
-done:
- Irp->IoStatus.Status = status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+__drv_functionClass(REQUEST_POWER_COMPLETE)
+__drv_sameIRQL
+static VOID
+FdoRequestSetDevicePowerDownComplete(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR MinorFunction,
+ IN POWER_STATE PowerState,
+ IN PVOID Context,
+ IN PIO_STATUS_BLOCK IoStatus
+ )
+{
+ PIRP Irp = (PIRP) Context;
+ PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ PDEVICE_OBJECT UpperDeviceObject = StackLocation->DeviceObject;
+ PXENVIF_DX Dx =
(PXENVIF_DX)UpperDeviceObject->DeviceExtension;
+ PXENVIF_FDO Fdo = Dx->Fdo;
+ SYSTEM_POWER_STATE SystemState =
StackLocation->Parameters.Power.State.SystemState;
- return status;
+ UNREFERENCED_PARAMETER(DeviceObject);
+ UNREFERENCED_PARAMETER(MinorFunction);
+ UNREFERENCED_PARAMETER(PowerState);
+
+ if (!NT_SUCCESS(IoStatus->Status))
+ Error("fail1 - but continue IRP processing. (%08x)\n",
IoStatus->Status);
+
+ Info("%s -> %s\n",
+ PowerSystemStateName(__FdoGetSystemPowerState(Fdo)),
+ PowerSystemStateName(SystemState));
+
+ if (SystemState >= PowerSystemHibernate &&
+ __FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) {
+ PVOID Exchange;
+
+ Exchange = InterlockedExchangePointer(&Fdo->SystemPowerIrp, Irp);
+ ASSERT(Exchange == NULL);
+
+ IoQueueWorkItem(Fdo->DevicePowerWorkItem,
+ FdoSystemPowerDownWorker,
+ DelayedWorkQueue,
+ Fdo);
+ } else {
+ __FdoSetSystemPowerState(Fdo, SystemState);
+
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
+ }
}
static FORCEINLINE NTSTATUS
@@ -2383,33 +2616,44 @@ __FdoSetSystemPowerDown(
{
PIO_STACK_LOCATION StackLocation;
SYSTEM_POWER_STATE SystemState;
- DEVICE_POWER_STATE DeviceState;
+ POWER_STATE PowerState;
NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ BUG_ON(StackLocation->DeviceObject != Fdo->Dx->DeviceObject);
SystemState = StackLocation->Parameters.Power.State.SystemState;
ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo));
- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
-
- FdoRequestSetDevicePower(Fdo, DeviceState);
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
- Info("%s: %s -> %s\n",
- __FdoGetName(Fdo),
- PowerSystemStateName(__FdoGetSystemPowerState(Fdo)),
- PowerSystemStateName(SystemState));
-
- if (SystemState >= PowerSystemHibernate &&
- __FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) {
- __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3);
- FdoS3ToS4(Fdo);
+ if (SystemState >= PowerSystemShutdown) {
+ /* No DIrp generation, no FDO Powerdown.
+ Legacy shutdown just yanks system power.
+ Best device state for S5 is advertised as D3,
+ which is not *really* the case, but we can't increase it. */
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+ } else {
+ status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+ IRP_MN_SET_POWER,
+ PowerState,
+ FdoRequestSetDevicePowerDownComplete,
+ Irp,
+ NULL);
+ if (!NT_SUCCESS(status))
+ goto fail1;
}
+ /* IRP already marked pending - nothing more to do if awaiting callback. */
- __FdoSetSystemPowerState(Fdo, SystemState);
+ return status;
- IoSkipCurrentIrpStackLocation(Irp);
- status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+fail1:
+ /* In theory could change IRP status, but are not supposed to fail this
IRP. */
+ Error("fail1 - but continue IRP processing. (%08x)\n", status);
+
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended */
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
return status;
}
@@ -2429,29 +2673,31 @@ __FdoSetSystemPower(
SystemState = StackLocation->Parameters.Power.State.SystemState;
PowerAction = StackLocation->Parameters.Power.ShutdownType;
+ /* IRP_MN_SET_POWER Setting system power, IRP's *must* be pended. */
+ IoMarkIrpPending(Irp);
+
Trace("====> (%s:%s)\n",
- PowerSystemStateName(SystemState),
+ PowerSystemStateName(SystemState),
PowerActionName(PowerAction));
- ASSERT3U(PowerAction, <, PowerActionShutdown);
-
if (SystemState == __FdoGetSystemPowerState(Fdo)) {
- IoSkipCurrentIrpStackLocation(Irp);
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Pended, copy not skip */
status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
goto done;
}
- status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?
+ status = SystemState < __FdoGetSystemPowerState(Fdo) ?
__FdoSetSystemPowerUp(Fdo, Irp) :
__FdoSetSystemPowerDown(Fdo, Irp);
done:
Trace("<==== (%s:%s)(%08x)\n",
- PowerSystemStateName(SystemState),
+ PowerSystemStateName(SystemState),
PowerActionName(PowerAction),
status);
- return status;
+
+ return STATUS_PENDING;
}
static FORCEINLINE NTSTATUS
@@ -2469,10 +2715,9 @@ __FdoQueryDevicePowerUp(
ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo));
- status = FdoForwardIrpSynchronously(Fdo, Irp);
-
- Irp->IoStatus.Status = status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ /* N.B. Shutdown / hibernation failures caused by our device state could
be vetoed here. */
+ IoSkipCurrentIrpStackLocation(Irp);
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
return status;
}
@@ -2492,6 +2737,7 @@ __FdoQueryDevicePowerDown(
ASSERT3U(DeviceState, >, __FdoGetDevicePowerState(Fdo));
+ /* N.B. Shutdown / hibernation failures caused by our device state could be vetoed here. */
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
@@ -2514,11 +2760,9 @@ __FdoQueryDevicePower(
PowerAction = StackLocation->Parameters.Power.ShutdownType;
Trace("====> (%s:%s)\n",
- PowerDeviceStateName(DeviceState),
+ PowerDeviceStateName(DeviceState),
PowerActionName(PowerAction));
- ASSERT3U(PowerAction, <, PowerActionShutdown);
-
if (DeviceState == __FdoGetDevicePowerState(Fdo)) {
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
@@ -2532,7 +2776,7 @@ __FdoQueryDevicePower(
done:
Trace("<==== (%s:%s)(%08x)\n",
- PowerDeviceStateName(DeviceState),
+ PowerDeviceStateName(DeviceState),
PowerActionName(PowerAction),
status);
return status;
@@ -2540,8 +2784,8 @@ done:
__drv_functionClass(REQUEST_POWER_COMPLETE)
__drv_sameIRQL
-VOID
-__FdoRequestQueryDevicePower(
+static VOID
+FdoRequestQueryDevicePowerUpComplete(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
@@ -2549,47 +2793,58 @@ __FdoRequestQueryDevicePower(
IN PIO_STATUS_BLOCK IoStatus
)
{
- PKEVENT Event = Context;
+ PIRP Irp = (PIRP) Context;
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(MinorFunction);
UNREFERENCED_PARAMETER(PowerState);
- ASSERT(NT_SUCCESS(IoStatus->Status));
+ if (!NT_SUCCESS(IoStatus->Status))
+ Irp->IoStatus.Status = IoStatus->Status;
- KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
-static VOID
-FdoRequestQueryDevicePower(
- IN PXENVIF_FDO Fdo,
- IN DEVICE_POWER_STATE DeviceState
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+__drv_sameIRQL
+static NTSTATUS
+FdoQuerySystemPowerUpComplete(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context
)
{
- POWER_STATE PowerState;
- KEVENT Event;
- NTSTATUS status;
-
- Trace("%s\n", PowerDeviceStateName(DeviceState));
+ PXENVIF_FDO Fdo = (PXENVIF_FDO) Context;
+ PIO_STACK_LOCATION StackLocation;
+ SYSTEM_POWER_STATE SystemState;
+ POWER_STATE PowerState;
+ NTSTATUS status;
- ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+ UNREFERENCED_PARAMETER(DeviceObject);
- PowerState.DeviceState = DeviceState;
- KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ /* IRP marked as pending on dispatch path. */
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ SystemState = StackLocation->Parameters.Power.State.SystemState;
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
IRP_MN_QUERY_POWER,
PowerState,
- __FdoRequestQueryDevicePower,
- &Event,
+ FdoRequestQueryDevicePowerUpComplete,
+ Irp,
NULL);
- ASSERT(NT_SUCCESS(status));
+ if (!NT_SUCCESS(status))
+ goto fail1;
- (VOID) KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
+ /* Will later complete the IRP (which is marked pending, in 2nd level comp
routine.)*/
+ return STATUS_MORE_PROCESSING_REQUIRED;
+
+fail1:
+ /* Irp marked as pending on dispatch path, so can change final IoStatus,
pass to completion routine above. */
+ Error("fail1 (%08x)\n", status);
+ Irp->IoStatus.Status = status;
+
+ return STATUS_CONTINUE_COMPLETION;
}
static FORCEINLINE NTSTATUS
@@ -2598,30 +2853,61 @@ __FdoQuerySystemPowerUp(
IN PIRP Irp
)
{
-
PIO_STACK_LOCATION StackLocation;
SYSTEM_POWER_STATE SystemState;
- DEVICE_POWER_STATE DeviceState;
- NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
SystemState = StackLocation->Parameters.Power.State.SystemState;
ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo));
- status = FdoForwardIrpSynchronously(Fdo, Irp);
- if (!NT_SUCCESS(status))
- goto done;
+ IoMarkIrpPending(Irp); /* Must mark IRP pending because we want to
complete it *after* completion routine. */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ FdoQuerySystemPowerUpComplete,
+ Fdo,
+ TRUE,
+ TRUE,
+ TRUE);
+ (VOID) IoCallDriver(Fdo->LowerDeviceObject, Irp);
- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+ return STATUS_PENDING;
+}
- FdoRequestQueryDevicePower(Fdo, DeviceState);
+__drv_functionClass(REQUEST_POWER_COMPLETE)
+__drv_sameIRQL
+static VOID
+FdoRequestQueryDevicePowerDownComplete(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR MinorFunction,
+ IN POWER_STATE PowerState,
+ IN PVOID Context,
+ IN PIO_STATUS_BLOCK IoStatus
+ )
+{
+ PIRP Irp = (PIRP) Context;
+ PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ PDEVICE_OBJECT UpperDeviceObject = StackLocation->DeviceObject;
+ PXENVIF_DX Dx =
(PXENVIF_DX)UpperDeviceObject->DeviceExtension;
+ PXENVIF_FDO Fdo = Dx->Fdo;
-done:
- Irp->IoStatus.Status = status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ UNREFERENCED_PARAMETER(DeviceObject);
+ UNREFERENCED_PARAMETER(MinorFunction);
+ UNREFERENCED_PARAMETER(PowerState);
- return status;
+ if (!NT_SUCCESS(IoStatus->Status))
+ goto fail1;
+
+ IoCopyCurrentIrpStackLocationToNext(Irp); /* Irp has been pended. */
+ IoCallDriver(Fdo->LowerDeviceObject, Irp);
+
+ return;
+
+fail1:
+ Error("fail1 (%08x)\n", IoStatus->Status);
+
+ Irp->IoStatus.Status = IoStatus->Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
static FORCEINLINE NTSTATUS
@@ -2632,7 +2918,7 @@ __FdoQuerySystemPowerDown(
{
PIO_STACK_LOCATION StackLocation;
SYSTEM_POWER_STATE SystemState;
- DEVICE_POWER_STATE DeviceState;
+ POWER_STATE PowerState;
NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
@@ -2640,12 +2926,26 @@ __FdoQuerySystemPowerDown(
ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo));
- DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
+ PowerState.DeviceState =
Fdo->LowerDeviceCapabilities.DeviceState[SystemState];
- FdoRequestQueryDevicePower(Fdo, DeviceState);
+ status = PoRequestPowerIrp(Fdo->LowerDeviceObject,
+ IRP_MN_QUERY_POWER,
+ PowerState,
+ FdoRequestQueryDevicePowerDownComplete,
+ Irp,
+ NULL);
+ if (!NT_SUCCESS(status))
+ goto fail1;
- IoSkipCurrentIrpStackLocation(Irp);
- status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+ IoMarkIrpPending(Irp);
+
+ return STATUS_PENDING;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ Irp->IoStatus.Status = status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
@@ -2666,11 +2966,9 @@ __FdoQuerySystemPower(
PowerAction = StackLocation->Parameters.Power.ShutdownType;
Trace("====> (%s:%s)\n",
- PowerSystemStateName(SystemState),
+ PowerSystemStateName(SystemState),
PowerActionName(PowerAction));
- ASSERT3U(PowerAction, <, PowerActionShutdown);
-
if (SystemState == __FdoGetSystemPowerState(Fdo)) {
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
@@ -2684,183 +2982,91 @@ __FdoQuerySystemPower(
done:
Trace("<==== (%s:%s)(%08x)\n",
- PowerSystemStateName(SystemState),
+ PowerSystemStateName(SystemState),
PowerActionName(PowerAction),
status);
return status;
}
-static NTSTATUS
-FdoDevicePower(
- IN PXENVIF_THREAD Self,
- IN PVOID Context
+static FORCEINLINE NTSTATUS
+__FdoDevicePower(
+ IN PXENVIF_FDO Fdo,
+ IN PIRP Irp
)
{
- PXENVIF_FDO Fdo = Context;
- PKEVENT Event;
-
- Event = ThreadGetEvent(Self);
-
- for (;;) {
- PIRP Irp;
- PIO_STACK_LOCATION StackLocation;
- UCHAR MinorFunction;
-
- if (Fdo->DevicePowerIrp == NULL) {
- (VOID) KeWaitForSingleObject(Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- KeClearEvent(Event);
- }
-
- if (ThreadIsAlerted(Self))
- break;
-
- Irp = Fdo->DevicePowerIrp;
-
- if (Irp == NULL)
- continue;
-
- Fdo->DevicePowerIrp = NULL;
- KeMemoryBarrier();
+ PIO_STACK_LOCATION StackLocation;
+ NTSTATUS status;
- StackLocation = IoGetCurrentIrpStackLocation(Irp);
- MinorFunction = StackLocation->MinorFunction;
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
- switch (StackLocation->MinorFunction) {
- case IRP_MN_SET_POWER:
- (VOID) __FdoSetDevicePower(Fdo, Irp);
- break;
+ switch (StackLocation->MinorFunction) {
+ case IRP_MN_SET_POWER:
+ status = __FdoSetDevicePower(Fdo, Irp);
+ break;
- case IRP_MN_QUERY_POWER:
- (VOID) __FdoQueryDevicePower(Fdo, Irp);
- break;
+ case IRP_MN_QUERY_POWER:
+ status = __FdoQueryDevicePower(Fdo, Irp);
+ break;
- default:
- ASSERT(FALSE);
- break;
- }
+ default:
+ IoSkipCurrentIrpStackLocation(Irp);
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+ break;
}
- return STATUS_SUCCESS;
+ return status;
}
-static NTSTATUS
-FdoSystemPower(
- IN PXENVIF_THREAD Self,
- IN PVOID Context
+static FORCEINLINE NTSTATUS
+__FdoSystemPower(
+ IN PXENVIF_FDO Fdo,
+ IN PIRP Irp
)
{
- PXENVIF_FDO Fdo = Context;
- PKEVENT Event;
-
- Event = ThreadGetEvent(Self);
-
- for (;;) {
- PIRP Irp;
- PIO_STACK_LOCATION StackLocation;
- UCHAR MinorFunction;
-
- if (Fdo->SystemPowerIrp == NULL) {
- (VOID) KeWaitForSingleObject(Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- KeClearEvent(Event);
- }
-
- if (ThreadIsAlerted(Self))
- break;
-
- Irp = Fdo->SystemPowerIrp;
-
- if (Irp == NULL)
- continue;
-
- Fdo->SystemPowerIrp = NULL;
- KeMemoryBarrier();
+ PIO_STACK_LOCATION StackLocation;
+ NTSTATUS status;
- StackLocation = IoGetCurrentIrpStackLocation(Irp);
- MinorFunction = StackLocation->MinorFunction;
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
- switch (StackLocation->MinorFunction) {
- case IRP_MN_SET_POWER:
- (VOID) __FdoSetSystemPower(Fdo, Irp);
- break;
+ switch (StackLocation->MinorFunction) {
+ case IRP_MN_SET_POWER:
+ status = __FdoSetSystemPower(Fdo, Irp);
+ break;
- case IRP_MN_QUERY_POWER:
- (VOID) __FdoQuerySystemPower(Fdo, Irp);
- break;
+ case IRP_MN_QUERY_POWER:
+ status = __FdoQuerySystemPower(Fdo, Irp);
+ break;
- default:
- ASSERT(FALSE);
- break;
- }
+ default:
+ IoSkipCurrentIrpStackLocation(Irp);
+ status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+ break;
}
- return STATUS_SUCCESS;
+ return status;
}
static DECLSPEC_NOINLINE NTSTATUS
FdoDispatchPower(
- IN PXENVIF_FDO Fdo,
+ IN PXENVIF_FDO Fdo,
IN PIRP Irp
)
{
PIO_STACK_LOCATION StackLocation;
- UCHAR MinorFunction;
POWER_STATE_TYPE PowerType;
- POWER_ACTION PowerAction;
NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
- MinorFunction = StackLocation->MinorFunction;
-
- if (MinorFunction != IRP_MN_QUERY_POWER &&
- MinorFunction != IRP_MN_SET_POWER) {
- IoSkipCurrentIrpStackLocation(Irp);
- status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-
- goto done;
- }
-
PowerType = StackLocation->Parameters.Power.Type;
- PowerAction = StackLocation->Parameters.Power.ShutdownType;
-
- if (PowerAction >= PowerActionShutdown) {
- IoSkipCurrentIrpStackLocation(Irp);
- status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
-
- goto done;
- }
switch (PowerType) {
case DevicePowerState:
- IoMarkIrpPending(Irp);
-
- ASSERT3P(Fdo->DevicePowerIrp, ==, NULL);
- Fdo->DevicePowerIrp = Irp;
- KeMemoryBarrier();
-
- ThreadWake(Fdo->DevicePowerThread);
-
- status = STATUS_PENDING;
+ status = __FdoDevicePower(Fdo, Irp);
break;
case SystemPowerState:
- IoMarkIrpPending(Irp);
-
- ASSERT3P(Fdo->SystemPowerIrp, ==, NULL);
- Fdo->SystemPowerIrp = Irp;
- KeMemoryBarrier();
-
- ThreadWake(Fdo->SystemPowerThread);
-
- status = STATUS_PENDING;
+ status = __FdoSystemPower(Fdo, Irp);
break;
default:
@@ -2869,7 +3075,6 @@ FdoDispatchPower(
break;
}
-done:
return status;
}
@@ -3063,12 +3268,12 @@ FdoCreate(
Fdo->LowerDeviceObject = IoAttachDeviceToDeviceStack(FunctionDeviceObject,
PhysicalDeviceObject);
- status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread);
- if (!NT_SUCCESS(status))
+ Fdo->SystemPowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject);
+ if (Fdo->SystemPowerWorkItem == NULL)
goto fail3;
- status = ThreadCreate(FdoDevicePower, Fdo, &Fdo->DevicePowerThread);
- if (!NT_SUCCESS(status))
+ Fdo->DevicePowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject);
+ if (Fdo->DevicePowerWorkItem == NULL)
goto fail4;
status = __FdoAcquireLowerBusInterface(Fdo);
@@ -3226,16 +3431,14 @@ fail6:
fail5:
Error("fail5\n");
- ThreadAlert(Fdo->DevicePowerThread);
- ThreadJoin(Fdo->DevicePowerThread);
- Fdo->DevicePowerThread = NULL;
-
+ IoFreeWorkItem(Fdo->DevicePowerWorkItem);
+ Fdo->DevicePowerWorkItem = NULL;
+
fail4:
Error("fail4\n");
- ThreadAlert(Fdo->SystemPowerThread);
- ThreadJoin(Fdo->SystemPowerThread);
- Fdo->SystemPowerThread = NULL;
+ IoFreeWorkItem(Fdo->SystemPowerWorkItem);
+ Fdo->SystemPowerWorkItem = NULL;
fail3:
Error("fail3\n");
@@ -3311,13 +3514,11 @@ FdoDestroy(
__FdoReleaseLowerBusInterface(Fdo);
- ThreadAlert(Fdo->DevicePowerThread);
- ThreadJoin(Fdo->DevicePowerThread);
- Fdo->DevicePowerThread = NULL;
+ IoFreeWorkItem(Fdo->DevicePowerWorkItem);
+ Fdo->DevicePowerWorkItem = NULL;
- ThreadAlert(Fdo->SystemPowerThread);
- ThreadJoin(Fdo->SystemPowerThread);
- Fdo->SystemPowerThread = NULL;
+ IoFreeWorkItem(Fdo->SystemPowerWorkItem);
+ Fdo->SystemPowerWorkItem = NULL;
IoDetachDevice(Fdo->LowerDeviceObject);
diff --git a/src/xenvif/pdo.c b/src/xenvif/pdo.c
index 0cef2d5..2979f53 100644
--- a/src/xenvif/pdo.c
+++ b/src/xenvif/pdo.c
@@ -68,9 +68,9 @@
struct _XENVIF_PDO {
PXENVIF_DX Dx;
- PXENVIF_THREAD SystemPowerThread;
+ PIO_WORKITEM SystemPowerWorkItem;
PIRP SystemPowerIrp;
- PXENVIF_THREAD DevicePowerThread;
+ PIO_WORKITEM DevicePowerWorkItem;
PIRP DevicePowerIrp;
PXENVIF_FDO Fdo;
@@ -2365,28 +2365,31 @@ PdoDispatchPnp(
return status;
}
-static FORCEINLINE NTSTATUS
-__PdoSetDevicePower(
- IN PXENVIF_PDO Pdo,
- IN PIRP Irp
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
+static VOID
+PdoDevicePowerWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
)
{
+ PXENVIF_PDO Pdo = (PXENVIF_PDO) Context;
+ PIRP Irp;
PIO_STACK_LOCATION StackLocation;
DEVICE_POWER_STATE DeviceState;
POWER_ACTION PowerAction;
NTSTATUS status;
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ Irp = InterlockedExchangePointer(&Pdo->DevicePowerIrp, NULL);
+ ASSERT(Irp != NULL);
+
StackLocation = IoGetCurrentIrpStackLocation(Irp);
DeviceState = StackLocation->Parameters.Power.State.DeviceState;
PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Trace("====> (%s) (%s:%s)\n",
- __PdoGetName(Pdo),
- PowerDeviceStateName(DeviceState),
- PowerActionName(PowerAction));
-
- ASSERT3U(PowerAction, <, PowerActionShutdown);
-
+ status = STATUS_SUCCESS;
if (__PdoGetDevicePowerState(Pdo) > DeviceState) {
Trace("%s: POWERING UP: %s -> %s\n",
__PdoGetName(Pdo),
@@ -2395,7 +2398,6 @@ __PdoSetDevicePower(
ASSERT3U(DeviceState, ==, PowerDeviceD0);
status = PdoD3ToD0(Pdo);
- ASSERT(NT_SUCCESS(status));
} else if (__PdoGetDevicePowerState(Pdo) < DeviceState) {
Trace("%s: POWERING DOWN: %s -> %s\n",
__PdoGetName(Pdo),
@@ -2406,77 +2408,71 @@ __PdoSetDevicePower(
PdoD0ToD3(Pdo);
}
+ /* Cannot fail the IRP at this point, keep going. */
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
- Trace("<==== (%s:%s)\n",
+ Trace("<==== (%s:%s)(%08x)\n",
PowerDeviceStateName(DeviceState),
- PowerActionName(PowerAction));
-
- return STATUS_SUCCESS;
+ PowerActionName(PowerAction),
+ status);
}
-static NTSTATUS
-PdoDevicePower(
- IN PXENVIF_THREAD Self,
- IN PVOID Context
+static FORCEINLINE NTSTATUS
+__PdoSetDevicePower(
+ IN PXENVIF_PDO Pdo,
+ IN PIRP Irp
)
{
- PXENVIF_PDO Pdo = Context;
- PKEVENT Event;
-
- Event = ThreadGetEvent(Self);
-
- for (;;) {
- PIRP Irp;
-
- if (Pdo->DevicePowerIrp == NULL) {
- (VOID) KeWaitForSingleObject(Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- KeClearEvent(Event);
- }
+ PIO_STACK_LOCATION StackLocation;
+ DEVICE_POWER_STATE DeviceState;
+ POWER_ACTION PowerAction;
+ PVOID Exchange;
- if (ThreadIsAlerted(Self))
- break;
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ DeviceState = StackLocation->Parameters.Power.State.DeviceState;
+ PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Irp = Pdo->DevicePowerIrp;
+ Trace("====> (%s:%s)\n",
+ PowerDeviceStateName(DeviceState),
+ PowerActionName(PowerAction));
- if (Irp == NULL)
- continue;
+ IoMarkIrpPending(Irp);
- Pdo->DevicePowerIrp = NULL;
- KeMemoryBarrier();
+ Exchange = InterlockedExchangePointer(&Pdo->DevicePowerIrp, Irp);
+ ASSERT(Exchange == NULL);
- (VOID) __PdoSetDevicePower(Pdo, Irp);
- }
+ IoQueueWorkItem(Pdo->DevicePowerWorkItem,
+ PdoDevicePowerWorker,
+ DelayedWorkQueue,
+ Pdo);
- return STATUS_SUCCESS;
+ return STATUS_PENDING;
}
-static FORCEINLINE NTSTATUS
-__PdoSetSystemPower(
- IN PXENVIF_PDO Pdo,
- IN PIRP Irp
+__drv_functionClass(IO_WORKITEM_ROUTINE)
+__drv_sameIRQL
+static VOID
+PdoSystemPowerWorker(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context
)
{
- PIO_STACK_LOCATION StackLocation;
- SYSTEM_POWER_STATE SystemState;
- POWER_ACTION PowerAction;
+ PXENVIF_PDO Pdo = (PXENVIF_PDO) Context;
+ PIRP Irp;
+ PIO_STACK_LOCATION StackLocation;
+ SYSTEM_POWER_STATE SystemState;
+ POWER_ACTION PowerAction;
+
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ Irp = InterlockedExchangePointer(&Pdo->SystemPowerIrp, NULL);
+ ASSERT(Irp != NULL);
StackLocation = IoGetCurrentIrpStackLocation(Irp);
SystemState = StackLocation->Parameters.Power.State.SystemState;
PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Trace("====> (%s) (%s:%s)\n",
- __PdoGetName(Pdo),
- PowerSystemStateName(SystemState),
- PowerActionName(PowerAction));
-
- ASSERT3U(PowerAction, <, PowerActionShutdown);
-
if (__PdoGetSystemPowerState(Pdo) > SystemState) {
if (SystemState < PowerSystemHibernate &&
__PdoGetSystemPowerState(Pdo) >= PowerSystemHibernate) {
@@ -2488,6 +2484,7 @@ __PdoSetSystemPower(
__PdoGetName(Pdo),
PowerSystemStateName(__PdoGetSystemPowerState(Pdo)),
PowerSystemStateName(SystemState));
+
} else if (__PdoGetSystemPowerState(Pdo) < SystemState) {
Trace("%s: POWERING DOWN: %s -> %s\n",
__PdoGetName(Pdo),
@@ -2509,97 +2506,60 @@ __PdoSetSystemPower(
Trace("<==== (%s:%s)\n",
PowerSystemStateName(SystemState),
PowerActionName(PowerAction));
-
- return STATUS_SUCCESS;
}
-static NTSTATUS
-PdoSystemPower(
- IN PXENVIF_THREAD Self,
- IN PVOID Context
+static FORCEINLINE NTSTATUS
+__PdoSetSystemPower(
+ IN PXENVIF_PDO Pdo,
+ IN PIRP Irp
)
{
- PXENVIF_PDO Pdo = Context;
- PKEVENT Event;
-
- Event = ThreadGetEvent(Self);
-
- for (;;) {
- PIRP Irp;
-
- if (Pdo->SystemPowerIrp == NULL) {
- (VOID) KeWaitForSingleObject(Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- KeClearEvent(Event);
- }
+ PIO_STACK_LOCATION StackLocation;
+ SYSTEM_POWER_STATE SystemState;
+ POWER_ACTION PowerAction;
+ PVOID Exchange;
- if (ThreadIsAlerted(Self))
- break;
+ StackLocation = IoGetCurrentIrpStackLocation(Irp);
+ SystemState = StackLocation->Parameters.Power.State.SystemState;
+ PowerAction = StackLocation->Parameters.Power.ShutdownType;
- Irp = Pdo->SystemPowerIrp;
+ Trace("====> (%s:%s)\n",
+ PowerSystemStateName(SystemState),
+ PowerActionName(PowerAction));
- if (Irp == NULL)
- continue;
+ IoMarkIrpPending(Irp);
- Pdo->SystemPowerIrp = NULL;
- KeMemoryBarrier();
+ Exchange = InterlockedExchangePointer(&Pdo->SystemPowerIrp, Irp);
+ ASSERT(Exchange == NULL);
- (VOID) __PdoSetSystemPower(Pdo, Irp);
- }
+ IoQueueWorkItem(Pdo->SystemPowerWorkItem,
+ PdoSystemPowerWorker,
+ DelayedWorkQueue,
+ Pdo);
- return STATUS_SUCCESS;
+ return STATUS_PENDING;
}
-static DECLSPEC_NOINLINE NTSTATUS
-PdoSetPower(
+static FORCEINLINE NTSTATUS
+__PdoSetPower(
IN PXENVIF_PDO Pdo,
IN PIRP Irp
)
{
PIO_STACK_LOCATION StackLocation;
POWER_STATE_TYPE PowerType;
- POWER_ACTION PowerAction;
NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
PowerType = StackLocation->Parameters.Power.Type;
- PowerAction = StackLocation->Parameters.Power.ShutdownType;
-
- if (PowerAction >= PowerActionShutdown) {
- Irp->IoStatus.Status = STATUS_SUCCESS;
-
- status = Irp->IoStatus.Status;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- goto done;
- }
switch (PowerType) {
case DevicePowerState:
- IoMarkIrpPending(Irp);
-
- ASSERT3P(Pdo->DevicePowerIrp, ==, NULL);
- Pdo->DevicePowerIrp = Irp;
- KeMemoryBarrier();
-
- ThreadWake(Pdo->DevicePowerThread);
-
- status = STATUS_PENDING;
+ status = __PdoSetDevicePower(Pdo, Irp);
break;
case SystemPowerState:
- IoMarkIrpPending(Irp);
-
- ASSERT3P(Pdo->SystemPowerIrp, ==, NULL);
- Pdo->SystemPowerIrp = Irp;
- KeMemoryBarrier();
-
- ThreadWake(Pdo->SystemPowerThread);
-
- status = STATUS_PENDING;
+ status = __PdoSetSystemPower(Pdo, Irp);
break;
default:
@@ -2608,48 +2568,41 @@ PdoSetPower(
break;
}
-done:
return status;
}
-static DECLSPEC_NOINLINE NTSTATUS
-PdoQueryPower(
- IN PXENVIF_PDO Pdo,
- IN PIRP Irp
+static FORCEINLINE NTSTATUS
+__PdoQueryPower(
+ IN PXENVIF_PDO Pdo,
+ IN PIRP Irp
)
{
- NTSTATUS status;
-
UNREFERENCED_PARAMETER(Pdo);
Irp->IoStatus.Status = STATUS_SUCCESS;
-
- status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return status;
+
+ return STATUS_SUCCESS;
}
-static DECLSPEC_NOINLINE NTSTATUS
+static NTSTATUS
PdoDispatchPower(
IN PXENVIF_PDO Pdo,
IN PIRP Irp
)
{
PIO_STACK_LOCATION StackLocation;
- UCHAR MinorFunction;
NTSTATUS status;
StackLocation = IoGetCurrentIrpStackLocation(Irp);
- MinorFunction = StackLocation->MinorFunction;
switch (StackLocation->MinorFunction) {
case IRP_MN_SET_POWER:
- status = PdoSetPower(Pdo, Irp);
+ status = __PdoSetPower(Pdo, Irp);
break;
case IRP_MN_QUERY_POWER:
- status = PdoQueryPower(Pdo, Irp);
+ status = __PdoQueryPower(Pdo, Irp);
break;
default:
@@ -2762,12 +2715,12 @@ PdoCreate(
Pdo->Dx = Dx;
Pdo->Fdo = Fdo;
- status = ThreadCreate(PdoSystemPower, Pdo, &Pdo->SystemPowerThread);
- if (!NT_SUCCESS(status))
+ Pdo->SystemPowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject);
+ if (Pdo->SystemPowerWorkItem == NULL)
goto fail3;
- status = ThreadCreate(PdoDevicePower, Pdo, &Pdo->DevicePowerThread);
- if (!NT_SUCCESS(status))
+ Pdo->DevicePowerWorkItem = IoAllocateWorkItem(PhysicalDeviceObject);
+ if (Pdo->DevicePowerWorkItem == NULL)
goto fail4;
__PdoSetName(Pdo, Number);
@@ -2860,16 +2813,14 @@ fail6:
fail5:
Error("fail5\n");
- ThreadAlert(Pdo->DevicePowerThread);
- ThreadJoin(Pdo->DevicePowerThread);
- Pdo->DevicePowerThread = NULL;
+ IoFreeWorkItem(Pdo->DevicePowerWorkItem);
+ Pdo->DevicePowerWorkItem = NULL;
fail4:
Error("fail4\n");
- ThreadAlert(Pdo->SystemPowerThread);
- ThreadJoin(Pdo->SystemPowerThread);
- Pdo->SystemPowerThread = NULL;
+ IoFreeWorkItem(Pdo->SystemPowerWorkItem);
+ Pdo->SystemPowerWorkItem = NULL;
fail3:
Error("fail3\n");
@@ -2939,13 +2890,11 @@ PdoDestroy(
__PdoClearPermanentAddress(Pdo);
- ThreadAlert(Pdo->DevicePowerThread);
- ThreadJoin(Pdo->DevicePowerThread);
- Pdo->DevicePowerThread = NULL;
+ IoFreeWorkItem(Pdo->DevicePowerWorkItem);
+ Pdo->DevicePowerWorkItem = NULL;
- ThreadAlert(Pdo->SystemPowerThread);
- ThreadJoin(Pdo->SystemPowerThread);
- Pdo->SystemPowerThread = NULL;
+ IoFreeWorkItem(Pdo->SystemPowerWorkItem);
+ Pdo->SystemPowerWorkItem = NULL;
Pdo->Fdo = NULL;
Pdo->Dx = NULL;