- Call acpi_bus_set_power instead of acpi_power_transition

- Make sure the device has power management capabilities before calling acpi_bus_set_power
 - Report the new power state with PoSetPowerState
 - Initialize PDOs with the correct device power state (Patch by Samuel Serapion)
 - Initialze PDOs with the correct system power state

svn path=/trunk/; revision=45959
This commit is contained in:
Cameron Gutman 2010-03-06 18:15:56 +00:00
parent daa14c5f08
commit 53a7ff99b9
3 changed files with 51 additions and 30 deletions

View file

@ -32,15 +32,10 @@ Bus_PDO_PnP (
) )
{ {
NTSTATUS status; NTSTATUS status;
struct acpi_device *device = NULL;
POWER_STATE state; POWER_STATE state;
PAGED_CODE (); PAGED_CODE ();
if (DeviceData->AcpiHandle)
acpi_bus_get_device(DeviceData->AcpiHandle, &device);
// //
// NB: Because we are a bus enumerator, we have no one to whom we could // NB: Because we are a bus enumerator, we have no one to whom we could
// defer these irps. Therefore we do not pass them down but merely // defer these irps. Therefore we do not pass them down but merely
@ -56,9 +51,10 @@ Bus_PDO_PnP (
// required to allow others to access this device. // required to allow others to access this device.
// Power up the device. // Power up the device.
// //
if (device && !ACPI_SUCCESS(acpi_power_transition(device, ACPI_STATE_D0))) if (DeviceData->AcpiHandle && acpi_bus_power_manageable(DeviceData->AcpiHandle) &&
!ACPI_SUCCESS(acpi_bus_set_power(DeviceData->AcpiHandle, ACPI_STATE_D0)))
{ {
DPRINT1("Device %x failed to start!\n", device); DPRINT1("Device %x failed to start!\n", DeviceData->AcpiHandle);
status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL;
break; break;
} }
@ -76,9 +72,10 @@ Bus_PDO_PnP (
// Here we shut down the device and give up and unmap any resources // Here we shut down the device and give up and unmap any resources
// we acquired for the device. // we acquired for the device.
// //
if (device && !ACPI_SUCCESS(acpi_power_transition(device, ACPI_STATE_D3))) if (DeviceData->AcpiHandle && acpi_bus_power_manageable(DeviceData->AcpiHandle) &&
!ACPI_SUCCESS(acpi_bus_set_power(DeviceData->AcpiHandle, ACPI_STATE_D3)))
{ {
DPRINT1("Device %x failed to stop!\n", device); DPRINT1("Device %x failed to stop!\n", DeviceData->AcpiHandle);
status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL;
break; break;
} }
@ -125,8 +122,6 @@ Bus_PDO_PnP (
// We did receive a query-stop, so restore. // We did receive a query-stop, so restore.
// //
RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common); RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common);
if (device)
acpi_power_transition(device, ACPI_STATE_D0);
} }
status = STATUS_SUCCESS;// We must not fail this IRP. status = STATUS_SUCCESS;// We must not fail this IRP.
break; break;

View file

@ -417,6 +417,8 @@ Bus_InitializePdo (
) )
{ {
PPDO_DEVICE_DATA pdoData; PPDO_DEVICE_DATA pdoData;
int acpistate;
DEVICE_POWER_STATE ntState;
PAGED_CODE (); PAGED_CODE ();
@ -424,6 +426,31 @@ Bus_InitializePdo (
DPRINT("pdo 0x%p, extension 0x%p\n", Pdo, pdoData); DPRINT("pdo 0x%p, extension 0x%p\n", Pdo, pdoData);
if (pdoData->AcpiHandle)
acpi_bus_get_power(pdoData->AcpiHandle, &acpistate);
else
acpistate = ACPI_STATE_D0;
switch(acpistate)
{
case ACPI_STATE_D0:
ntState = PowerDeviceD0;
break;
case ACPI_STATE_D1:
ntState = PowerDeviceD1;
break;
case ACPI_STATE_D2:
ntState = PowerDeviceD2;
break;
case ACPI_STATE_D3:
ntState = PowerDeviceD3;
break;
default:
DPRINT1("Unknown power state (%d) returned by acpi\n",acpistate);
ntState = PowerDeviceUnspecified;
break;
}
// //
// Initialize the rest // Initialize the rest
// //
@ -435,12 +462,8 @@ Bus_InitializePdo (
INITIALIZE_PNP_STATE(pdoData->Common); INITIALIZE_PNP_STATE(pdoData->Common);
// pdoData->Common.DevicePowerState = ntState;
// PDO's usually start their life at D3 pdoData->Common.SystemPowerState = FdoData->Common.SystemPowerState;
//
pdoData->Common.DevicePowerState = PowerDeviceD3;
pdoData->Common.SystemPowerState = PowerSystemWorking;
Pdo->Flags |= DO_POWER_PAGABLE; Pdo->Flags |= DO_POWER_PAGABLE;

View file

@ -63,6 +63,7 @@ Bus_FDO_Power (
PIO_STACK_LOCATION stack; PIO_STACK_LOCATION stack;
ULONG AcpiState; ULONG AcpiState;
ACPI_STATUS AcpiStatus; ACPI_STATUS AcpiStatus;
SYSTEM_POWER_STATE oldPowerState;
stack = IoGetCurrentIrpStackLocation (Irp); stack = IoGetCurrentIrpStackLocation (Irp);
powerType = stack->Parameters.Power.Type; powerType = stack->Parameters.Power.Type;
@ -77,8 +78,8 @@ Bus_FDO_Power (
DbgDevicePowerString(powerState.DeviceState))); DbgDevicePowerString(powerState.DeviceState)));
} }
if (powerType == SystemPowerState) { if (powerType == SystemPowerState)
status = STATUS_SUCCESS; {
switch (powerState.SystemState) { switch (powerState.SystemState) {
case PowerSystemSleeping1: case PowerSystemSleeping1:
AcpiState = ACPI_STATE_S1; AcpiState = ACPI_STATE_S1;
@ -96,13 +97,17 @@ Bus_FDO_Power (
AcpiState = ACPI_STATE_S5; AcpiState = ACPI_STATE_S5;
break; break;
default: default:
return STATUS_UNSUCCESSFUL; AcpiState = ACPI_STATE_UNKNOWN;
break; ASSERT(FALSE);
break;
} }
oldPowerState = Data->Common.SystemPowerState;
Data->Common.SystemPowerState = powerState.SystemState;
AcpiStatus = AcpiEnterSleepState(AcpiState); AcpiStatus = AcpiEnterSleepState(AcpiState);
if (!ACPI_SUCCESS(AcpiStatus)) { if (!ACPI_SUCCESS(AcpiStatus)) {
DPRINT1("Failed to enter sleep state %d (Status 0x%X)\n", DPRINT1("Failed to enter sleep state %d (Status 0x%X)\n",
AcpiState, AcpiStatus); AcpiState, AcpiStatus);
Data->Common.SystemPowerState = oldPowerState;
status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL;
} }
} }
@ -124,15 +129,11 @@ Bus_PDO_Power (
POWER_STATE powerState; POWER_STATE powerState;
POWER_STATE_TYPE powerType; POWER_STATE_TYPE powerType;
ULONG error; ULONG error;
struct acpi_device *device;
stack = IoGetCurrentIrpStackLocation (Irp); stack = IoGetCurrentIrpStackLocation (Irp);
powerType = stack->Parameters.Power.Type; powerType = stack->Parameters.Power.Type;
powerState = stack->Parameters.Power.State; powerState = stack->Parameters.Power.State;
if (PdoData->AcpiHandle)
acpi_bus_get_device(PdoData->AcpiHandle, &device);
switch (stack->MinorFunction) { switch (stack->MinorFunction) {
case IRP_MN_SET_POWER: case IRP_MN_SET_POWER:
@ -144,8 +145,9 @@ Bus_PDO_Power (
switch (powerType) { switch (powerType) {
case DevicePowerState: case DevicePowerState:
if (!device) if (!PdoData->AcpiHandle || !acpi_bus_power_manageable(PdoData->AcpiHandle))
{ {
PoSetPowerState(PdoData->Common.Self, DevicePowerState, powerState);
PdoData->Common.DevicePowerState = powerState.DeviceState; PdoData->Common.DevicePowerState = powerState.DeviceState;
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
break; break;
@ -154,19 +156,19 @@ Bus_PDO_Power (
switch (powerState.DeviceState) switch (powerState.DeviceState)
{ {
case PowerDeviceD0: case PowerDeviceD0:
error = acpi_power_transition(device, ACPI_STATE_D0); error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D0);
break; break;
case PowerDeviceD1: case PowerDeviceD1:
error = acpi_power_transition(device, ACPI_STATE_D1); error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D1);
break; break;
case PowerDeviceD2: case PowerDeviceD2:
error = acpi_power_transition(device, ACPI_STATE_D2); error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D2);
break; break;
case PowerDeviceD3: case PowerDeviceD3:
error = acpi_power_transition(device, ACPI_STATE_D3); error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D3);
break; break;
default: default:
@ -176,6 +178,7 @@ Bus_PDO_Power (
if (ACPI_SUCCESS(error)) if (ACPI_SUCCESS(error))
{ {
PoSetPowerState(PdoData->Common.Self, DevicePowerState, powerState);
PdoData->Common.DevicePowerState = powerState.DeviceState; PdoData->Common.DevicePowerState = powerState.DeviceState;
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
} }