|
@@ -44,6 +44,8 @@
|
|
|
#include <acpi/acpi_bus.h>
|
|
|
#include <acpi/acpi_drivers.h>
|
|
|
|
|
|
+#include "sleep.h"
|
|
|
+
|
|
|
#define _COMPONENT ACPI_POWER_COMPONENT
|
|
|
ACPI_MODULE_NAME("power");
|
|
|
#define ACPI_POWER_CLASS "power_resource"
|
|
@@ -361,17 +363,15 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
|
|
|
*/
|
|
|
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
|
|
{
|
|
|
- int i, err;
|
|
|
+ int i, err = 0;
|
|
|
|
|
|
if (!dev || !dev->wakeup.flags.valid)
|
|
|
return -EINVAL;
|
|
|
|
|
|
- /*
|
|
|
- * Do not execute the code below twice in a row without calling
|
|
|
- * acpi_disable_wakeup_device_power() in between for the same device
|
|
|
- */
|
|
|
- if (dev->wakeup.flags.prepared)
|
|
|
- return 0;
|
|
|
+ mutex_lock(&acpi_device_lock);
|
|
|
+
|
|
|
+ if (dev->wakeup.prepare_count++)
|
|
|
+ goto out;
|
|
|
|
|
|
/* Open power resource */
|
|
|
for (i = 0; i < dev->wakeup.resources.count; i++) {
|
|
@@ -379,7 +379,8 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
|
|
if (ret) {
|
|
|
printk(KERN_ERR PREFIX "Transition power state\n");
|
|
|
dev->wakeup.flags.valid = 0;
|
|
|
- return -ENODEV;
|
|
|
+ err = -ENODEV;
|
|
|
+ goto err_out;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -388,9 +389,13 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
|
|
* in arbitrary power state afterwards.
|
|
|
*/
|
|
|
err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
|
|
|
- if (!err)
|
|
|
- dev->wakeup.flags.prepared = 1;
|
|
|
|
|
|
+ err_out:
|
|
|
+ if (err)
|
|
|
+ dev->wakeup.prepare_count = 0;
|
|
|
+
|
|
|
+ out:
|
|
|
+ mutex_unlock(&acpi_device_lock);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -402,35 +407,42 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
|
|
|
*/
|
|
|
int acpi_disable_wakeup_device_power(struct acpi_device *dev)
|
|
|
{
|
|
|
- int i, ret;
|
|
|
+ int i, err = 0;
|
|
|
|
|
|
if (!dev || !dev->wakeup.flags.valid)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ mutex_lock(&acpi_device_lock);
|
|
|
+
|
|
|
+ if (--dev->wakeup.prepare_count > 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
/*
|
|
|
- * Do not execute the code below twice in a row without calling
|
|
|
- * acpi_enable_wakeup_device_power() in between for the same device
|
|
|
+ * Executing the code below even if prepare_count is already zero when
|
|
|
+ * the function is called may be useful, for example for initialisation.
|
|
|
*/
|
|
|
- if (!dev->wakeup.flags.prepared)
|
|
|
- return 0;
|
|
|
+ if (dev->wakeup.prepare_count < 0)
|
|
|
+ dev->wakeup.prepare_count = 0;
|
|
|
|
|
|
- dev->wakeup.flags.prepared = 0;
|
|
|
-
|
|
|
- ret = acpi_device_sleep_wake(dev, 0, 0, 0);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
+ err = acpi_device_sleep_wake(dev, 0, 0, 0);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
|
|
|
/* Close power resource */
|
|
|
for (i = 0; i < dev->wakeup.resources.count; i++) {
|
|
|
- ret = acpi_power_off_device(dev->wakeup.resources.handles[i], dev);
|
|
|
+ int ret = acpi_power_off_device(
|
|
|
+ dev->wakeup.resources.handles[i], dev);
|
|
|
if (ret) {
|
|
|
printk(KERN_ERR PREFIX "Transition power state\n");
|
|
|
dev->wakeup.flags.valid = 0;
|
|
|
- return -ENODEV;
|
|
|
+ err = -ENODEV;
|
|
|
+ goto out;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return ret;
|
|
|
+ out:
|
|
|
+ mutex_unlock(&acpi_device_lock);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------
|