From 429be56ab748d55639a6274882c7da3ab7646ebf Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 19 Jun 2013 00:45:34 +0200 Subject: [PATCH] --- yaml --- r: 377274 b: refs/heads/master c: b9e95fc65ededbec083aa91b4faa58ad992c0891 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/acpi/acpi_lpss.c | 21 +++++++++++++++------ trunk/drivers/acpi/device_pm.c | 20 ++++++++++++++++++++ trunk/include/acpi/acpi_bus.h | 1 + 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index e1ab61e07522..8212775945e8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6ee22e9d59151550a55d370b14109bdae8b58bda +refs/heads/master: b9e95fc65ededbec083aa91b4faa58ad992c0891 diff --git a/trunk/drivers/acpi/acpi_lpss.c b/trunk/drivers/acpi/acpi_lpss.c index 652fd5ce303c..cab13f2fc28e 100644 --- a/trunk/drivers/acpi/acpi_lpss.c +++ b/trunk/drivers/acpi/acpi_lpss.c @@ -164,15 +164,24 @@ static int acpi_lpss_create_device(struct acpi_device *adev, if (dev_desc->clk_required) { ret = register_device_clock(adev, pdata); if (ret) { - /* - * Skip the device, but don't terminate the namespace - * scan. - */ - kfree(pdata); - return 0; + /* Skip the device, but continue the namespace scan. */ + ret = 0; + goto err_out; } } + /* + * This works around a known issue in ACPI tables where LPSS devices + * have _PS0 and _PS3 without _PSC (and no power resources), so + * acpi_bus_init_power() will assume that the BIOS has put them into D0. + */ + ret = acpi_device_fix_up_power(adev); + if (ret) { + /* Skip the device, but continue the namespace scan. */ + ret = 0; + goto err_out; + } + adev->driver_data = pdata; ret = acpi_create_platform_device(adev, id); if (ret > 0) diff --git a/trunk/drivers/acpi/device_pm.c b/trunk/drivers/acpi/device_pm.c index 318fa32a141e..31c217a42839 100644 --- a/trunk/drivers/acpi/device_pm.c +++ b/trunk/drivers/acpi/device_pm.c @@ -290,6 +290,26 @@ int acpi_bus_init_power(struct acpi_device *device) return 0; } +/** + * acpi_device_fix_up_power - Force device with missing _PSC into D0. + * @device: Device object whose power state is to be fixed up. + * + * Devices without power resources and _PSC, but having _PS0 and _PS3 defined, + * are assumed to be put into D0 by the BIOS. However, in some cases that may + * not be the case and this function should be used then. + */ +int acpi_device_fix_up_power(struct acpi_device *device) +{ + int ret = 0; + + if (!device->power.flags.power_resources + && !device->power.flags.explicit_get + && device->power.state == ACPI_STATE_D0) + ret = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0); + + return ret; +} + int acpi_bus_update_power(acpi_handle handle, int *state_p) { struct acpi_device *device; diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index 636c59f2003a..c13c919ab99e 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -382,6 +382,7 @@ const char *acpi_power_state_string(int state); int acpi_device_get_power(struct acpi_device *device, int *state); int acpi_device_set_power(struct acpi_device *device, int state); int acpi_bus_init_power(struct acpi_device *device); +int acpi_device_fix_up_power(struct acpi_device *device); int acpi_bus_update_power(acpi_handle handle, int *state_p); bool acpi_bus_power_manageable(acpi_handle handle);