diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 8a6c67c9da4209e648c87822bb99c34e8676a403..07f61dbd81360a6fb42160a9505e451b306c3e78 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -55,6 +55,7 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start, struct list_head *list); int acpi_add_power_resource(acpi_handle handle); void acpi_power_add_remove_device(struct acpi_device *adev, bool add); +int acpi_power_min_system_level(struct list_head *list); int acpi_device_sleep_wake(struct acpi_device *dev, int enable, int sleep_state, int dev_state); int acpi_power_get_inferred_state(struct acpi_device *device, int *state); diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 1600f753fafed4861fcb5d51fbe15df934d0baad..089a7c39348fe676429a64afec817539811f8d65 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -429,6 +429,20 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add) } } +int acpi_power_min_system_level(struct list_head *list) +{ + struct acpi_power_resource_entry *entry; + int system_level = 5; + + list_for_each_entry(entry, list, node) { + struct acpi_power_resource *resource = entry->resource; + + if (system_level > resource->system_level) + system_level = resource->system_level; + } + return system_level; +} + /* -------------------------------------------------------------------------- Device Power Management -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0b6a6b4febd69f8c06a3d3ac3e96fb04388dcb60..1fc57a349a3cf3164c64a348ff3fac17d9ccf44b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -950,6 +950,17 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, if (err) goto out; + if (!list_empty(&wakeup->resources)) { + int sleep_state; + + sleep_state = acpi_power_min_system_level(&wakeup->resources); + if (sleep_state < wakeup->sleep_state) { + acpi_handle_warn(handle, "Overriding _PRW sleep state " + "(S%d) by S%d from power resources\n", + (int)wakeup->sleep_state, sleep_state); + wakeup->sleep_state = sleep_state; + } + } acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); out: