]> Pileus Git - ~andy/linux/blobdiff - drivers/acpi/device_pm.c
Merge branches 'acpi-processor', 'acpi-hotplug', 'acpi-init', 'acpi-pm' and 'acpica'
[~andy/linux] / drivers / acpi / device_pm.c
index a94383d1f3502ae35138e7e677df02c1d8df3d72..c14a00d3dca61e5d943c41d5fe11fb90669550a6 100644 (file)
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
-#include <linux/device.h>
+#include <linux/acpi.h>
 #include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/pm_qos.h>
 #include <linux/pm_runtime.h>
 
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
 #include "internal.h"
 
 #define _COMPONENT     ACPI_POWER_COMPONENT
@@ -118,9 +114,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
        /*
         * If we were unsure about the device parent's power state up to this
         * point, the fact that the device is in D0 implies that the parent has
-        * to be in D0 too.
+        * to be in D0 too, except if ignore_parent is set.
         */
-       if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN
+       if (!device->power.flags.ignore_parent && device->parent
+           && device->parent->power.state == ACPI_STATE_UNKNOWN
            && result == ACPI_STATE_D0)
                device->parent->power.state = ACPI_STATE_D0;
 
@@ -177,7 +174,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
                         acpi_power_state_string(state));
                return -ENODEV;
        }
-       if (device->parent && (state < device->parent->power.state)) {
+       if (!device->power.flags.ignore_parent &&
+           device->parent && (state < device->parent->power.state)) {
                dev_warn(&device->dev,
                         "Cannot transition to power state %s for parent in %s\n",
                         acpi_power_state_string(state),
@@ -258,6 +256,8 @@ int acpi_bus_init_power(struct acpi_device *device)
                return -EINVAL;
 
        device->power.state = ACPI_STATE_UNKNOWN;
+       if (!acpi_device_is_present(device))
+               return 0;
 
        result = acpi_device_get_power(device, &state);
        if (result)
@@ -304,15 +304,18 @@ int acpi_device_fix_up_power(struct acpi_device *device)
        return ret;
 }
 
-int acpi_bus_update_power(acpi_handle handle, int *state_p)
+int acpi_device_update_power(struct acpi_device *device, int *state_p)
 {
-       struct acpi_device *device;
        int state;
        int result;
 
-       result = acpi_bus_get_device(handle, &device);
-       if (result)
+       if (device->power.state == ACPI_STATE_UNKNOWN) {
+               result = acpi_bus_init_power(device);
+               if (!result && state_p)
+                       *state_p = device->power.state;
+
                return result;
+       }
 
        result = acpi_device_get_power(device, &state);
        if (result)
@@ -340,6 +343,15 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
 
        return 0;
 }
+
+int acpi_bus_update_power(acpi_handle handle, int *state_p)
+{
+       struct acpi_device *device;
+       int result;
+
+       result = acpi_bus_get_device(handle, &device);
+       return result ? result : acpi_device_update_power(device, state_p);
+}
 EXPORT_SYMBOL_GPL(acpi_bus_update_power);
 
 bool acpi_bus_power_manageable(acpi_handle handle)
@@ -546,7 +558,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
  */
 int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
 {
-       acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
+       acpi_handle handle = ACPI_HANDLE(dev);
        struct acpi_device *adev;
        int ret, d_min, d_max;
 
@@ -654,7 +666,7 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
        if (!device_run_wake(phys_dev))
                return -EINVAL;
 
-       handle = DEVICE_ACPI_HANDLE(phys_dev);
+       handle = ACPI_HANDLE(phys_dev);
        if (!handle || acpi_bus_get_device(handle, &adev)) {
                dev_dbg(phys_dev, "ACPI handle without context in %s!\n",
                        __func__);
@@ -698,7 +710,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
        if (!device_can_wakeup(dev))
                return -EINVAL;
 
-       handle = DEVICE_ACPI_HANDLE(dev);
+       handle = ACPI_HANDLE(dev);
        if (!handle || acpi_bus_get_device(handle, &adev)) {
                dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
                return -ENODEV;
@@ -714,18 +726,6 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 }
 #endif /* CONFIG_PM_SLEEP */
 
-/**
- * acpi_dev_pm_get_node - Get ACPI device node for the given physical device.
- * @dev: Device to get the ACPI node for.
- */
-struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
-{
-       acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
-       struct acpi_device *adev;
-
-       return handle && !acpi_bus_get_device(handle, &adev) ? adev : NULL;
-}
-
 /**
  * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
  * @dev: Device to put into a low-power state.
@@ -766,7 +766,7 @@ static int acpi_dev_pm_full_power(struct acpi_device *adev)
  */
 int acpi_dev_runtime_suspend(struct device *dev)
 {
-       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       struct acpi_device *adev = ACPI_COMPANION(dev);
        bool remote_wakeup;
        int error;
 
@@ -797,7 +797,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_runtime_suspend);
  */
 int acpi_dev_runtime_resume(struct device *dev)
 {
-       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       struct acpi_device *adev = ACPI_COMPANION(dev);
        int error;
 
        if (!adev)
@@ -850,7 +850,7 @@ EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume);
  */
 int acpi_dev_suspend_late(struct device *dev)
 {
-       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       struct acpi_device *adev = ACPI_COMPANION(dev);
        u32 target_state;
        bool wakeup;
        int error;
@@ -882,7 +882,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_suspend_late);
  */
 int acpi_dev_resume_early(struct device *dev)
 {
-       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       struct acpi_device *adev = ACPI_COMPANION(dev);
        int error;
 
        if (!adev)
@@ -973,7 +973,7 @@ static struct dev_pm_domain acpi_general_pm_domain = {
  */
 int acpi_dev_pm_attach(struct device *dev, bool power_on)
 {
-       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       struct acpi_device *adev = ACPI_COMPANION(dev);
 
        if (!adev)
                return -ENODEV;
@@ -1005,7 +1005,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
  */
 void acpi_dev_pm_detach(struct device *dev, bool power_off)
 {
-       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       struct acpi_device *adev = ACPI_COMPANION(dev);
 
        if (adev && dev->pm_domain == &acpi_general_pm_domain) {
                dev->pm_domain = NULL;