libata-sff: separate out BMDMA qc_issue
[safe/jmp/linux-2.6] / drivers / acpi / power.c
index 1bef942..ddc7678 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include "sleep.h"
 
-#define _COMPONENT             ACPI_POWER_COMPONENT
+#define PREFIX "ACPI: "
+
+#define _COMPONENT                     ACPI_POWER_COMPONENT
 ACPI_MODULE_NAME("power");
-#define ACPI_POWER_COMPONENT           0x00800000
 #define ACPI_POWER_CLASS               "power_resource"
 #define ACPI_POWER_DEVICE_NAME         "Power Resource"
 #define ACPI_POWER_FILE_INFO           "info"
@@ -54,12 +57,16 @@ ACPI_MODULE_NAME("power");
 #define ACPI_POWER_RESOURCE_STATE_OFF  0x00
 #define ACPI_POWER_RESOURCE_STATE_ON   0x01
 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
+
+int acpi_power_nocheck;
+module_param_named(power_nocheck, acpi_power_nocheck, bool, 000);
+
 static int acpi_power_add(struct acpi_device *device);
 static int acpi_power_remove(struct acpi_device *device, int type);
 static int acpi_power_resume(struct acpi_device *device);
 static int acpi_power_open_fs(struct inode *inode, struct file *file);
 
-static struct acpi_device_id power_device_ids[] = {
+static const struct acpi_device_id power_device_ids[] = {
        {ACPI_POWER_HID, 0},
        {"", 0},
 };
@@ -128,24 +135,29 @@ acpi_power_get_context(acpi_handle handle,
        return 0;
 }
 
-static int acpi_power_get_state(struct acpi_power_resource *resource, int *state)
+static int acpi_power_get_state(acpi_handle handle, int *state)
 {
        acpi_status status = AE_OK;
-       unsigned long sta = 0;
+       unsigned long long sta = 0;
+       char node_name[5];
+       struct acpi_buffer buffer = { sizeof(node_name), node_name };
 
 
-       if (!resource || !state)
+       if (!handle || !state)
                return -EINVAL;
 
-       status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta);
+       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
        *state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
                              ACPI_POWER_RESOURCE_STATE_OFF;
 
+       acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
+
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
-                         resource->name, state ? "on" : "off"));
+                         node_name,
+                               *state ? "on" : "off"));
 
        return 0;
 }
@@ -153,7 +165,6 @@ static int acpi_power_get_state(struct acpi_power_resource *resource, int *state
 static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
 {
        int result = 0, state1;
-       struct acpi_power_resource *resource = NULL;
        u32 i = 0;
 
 
@@ -161,12 +172,15 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
                return -EINVAL;
 
        /* The state of the list is 'on' IFF all resources are 'on'. */
+       /* */
 
        for (i = 0; i < list->count; i++) {
-               result = acpi_power_get_context(list->handles[i], &resource);
-               if (result)
-                       return result;
-               result = acpi_power_get_state(resource, &state1);
+               /*
+                * The state of the power resource can be obtained by
+                * using the ACPI handle. In such case it is unnecessary to
+                * get the Power resource first and then get its state again.
+                */
+               result = acpi_power_get_state(list->handles[i], &state1);
                if (result)
                        return result;
 
@@ -184,7 +198,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
 
 static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
 {
-       int result = 0, state;
+       int result = 0;
        int found = 0;
        acpi_status status = AE_OK;
        struct acpi_power_resource *resource = NULL;
@@ -226,12 +240,6 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       result = acpi_power_get_state(resource, &state);
-       if (result)
-               return result;
-       if (state != ACPI_POWER_RESOURCE_STATE_ON)
-               return -ENOEXEC;
-
        /* Update the power resource's _device_ power state */
        resource->device->power.state = ACPI_STATE_D0;
 
@@ -242,7 +250,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
 
 static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
 {
-       int result = 0, state;
+       int result = 0;
        acpi_status status = AE_OK;
        struct acpi_power_resource *resource = NULL;
        struct list_head *node, *next;
@@ -277,12 +285,6 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       result = acpi_power_get_state(resource, &state);
-       if (result)
-               return result;
-       if (state != ACPI_POWER_RESOURCE_STATE_OFF)
-               return -ENOEXEC;
-
        /* Update the power resource's _device_ power state */
        resource->device->power.state = ACPI_STATE_D3;
 
@@ -363,17 +365,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++) {
@@ -381,7 +381,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;
                }
        }
 
@@ -390,9 +391,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;
 }
 
@@ -404,35 +409,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;
 }
 
 /* --------------------------------------------------------------------------
@@ -494,11 +506,6 @@ int acpi_power_transition(struct acpi_device *device, int state)
        cl = &device->power.states[device->power.state].resources;
        tl = &device->power.states[state].resources;
 
-       if (!cl->count && !tl->count) {
-               result = -ENODEV;
-               goto end;
-       }
-
        /* TBD: Resources must be ordered. */
 
        /*
@@ -555,7 +562,7 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
        if (!resource)
                goto end;
 
-       result = acpi_power_get_state(resource, &state);
+       result = acpi_power_get_state(resource->device->handle, &state);
        if (result)
                goto end;
 
@@ -668,7 +675,7 @@ static int acpi_power_add(struct acpi_device *device)
        resource->system_level = acpi_object.power_resource.system_level;
        resource->order = acpi_object.power_resource.resource_order;
 
-       result = acpi_power_get_state(resource, &state);
+       result = acpi_power_get_state(device->handle, &state);
        if (result)
                goto end;
 
@@ -735,7 +742,7 @@ static int acpi_power_resume(struct acpi_device *device)
 
        resource = acpi_driver_data(device);
 
-       result = acpi_power_get_state(resource, &state);
+       result = acpi_power_get_state(device->handle, &state);
        if (result)
                return result;
 
@@ -752,14 +759,10 @@ static int acpi_power_resume(struct acpi_device *device)
        return 0;
 }
 
-static int __init acpi_power_init(void)
+int __init acpi_power_init(void)
 {
        int result = 0;
 
-
-       if (acpi_disabled)
-               return 0;
-
        INIT_LIST_HEAD(&acpi_power_resource_list);
 
        acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir);
@@ -774,5 +777,3 @@ static int __init acpi_power_init(void)
 
        return 0;
 }
-
-subsys_initcall(acpi_power_init);