ACPI / PM: Add more run-time wake-up fields
authorRafael J. Wysocki <rjw@sisk.pl>
Wed, 17 Feb 2010 22:41:49 +0000 (23:41 +0100)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Tue, 23 Feb 2010 00:20:51 +0000 (16:20 -0800)
Use the run_wake flag to mark all devices for which run-time wake-up
events may be generated by the platform.  Introduce a new wake-up
flag, always_enabled, for marking devices that should be permanently
enabled to generate run-time events.  Also, introduce a reference
counter for run-wake devices and a function that will initialize all
of the run-time wake-up fields for given device.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Len Brown <len.brown@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/acpi/button.c
drivers/acpi/scan.c
drivers/acpi/wakeup.c
include/acpi/acpi_bus.h

index 09ca3ce..f53fbe3 100644 (file)
@@ -425,6 +425,7 @@ static int acpi_button_add(struct acpi_device *device)
                acpi_enable_gpe(device->wakeup.gpe_device,
                                device->wakeup.gpe_number,
                                ACPI_GPE_TYPE_WAKE_RUN);
+               device->wakeup.run_wake_count++;
                device->wakeup.state.enabled = 1;
        }
 
@@ -448,6 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
                acpi_disable_gpe(device->wakeup.gpe_device,
                                device->wakeup.gpe_number,
                                ACPI_GPE_TYPE_WAKE_RUN);
+               device->wakeup.run_wake_count--;
                device->wakeup.state.enabled = 0;
        }
 
index 3e00967..7491a52 100644 (file)
@@ -741,19 +741,39 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
        return AE_OK;
 }
 
-static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
+static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
 {
-       acpi_status status = 0;
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *package = NULL;
-       int psw_error;
-
        struct acpi_device_id button_device_ids[] = {
                {"PNP0C0D", 0},
                {"PNP0C0C", 0},
                {"PNP0C0E", 0},
                {"", 0},
        };
+       acpi_status status;
+       acpi_event_status event_status;
+
+       device->wakeup.run_wake_count = 0;
+
+       /* Power button, Lid switch always enable wakeup */
+       if (!acpi_match_device_ids(device, button_device_ids)) {
+               device->wakeup.flags.run_wake = 1;
+               device->wakeup.flags.always_enabled = 1;
+               return;
+       }
+
+       status = acpi_get_gpe_status(NULL, device->wakeup.gpe_number,
+                                       ACPI_NOT_ISR, &event_status);
+       if (status == AE_OK)
+               device->wakeup.flags.run_wake =
+                               !!(event_status & ACPI_EVENT_FLAG_HANDLE);
+}
+
+static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
+{
+       acpi_status status = 0;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *package = NULL;
+       int psw_error;
 
        /* _PRW */
        status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
@@ -773,6 +793,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 
        device->wakeup.flags.valid = 1;
        device->wakeup.prepare_count = 0;
+       acpi_bus_set_run_wake_flags(device);
        /* Call _PSW/_DSW object to disable its ability to wake the sleeping
         * system for the ACPI device with the _PRW object.
         * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
@@ -784,10 +805,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                "error in _DSW or _PSW evaluation\n"));
 
-       /* Power button, Lid switch always enable wakeup */
-       if (!acpi_match_device_ids(device, button_device_ids))
-               device->wakeup.flags.run_wake = 1;
-
 end:
        if (ACPI_FAILURE(status))
                device->flags.wake_capable = 0;
index 6783986..4b9d339 100644 (file)
@@ -110,7 +110,8 @@ int __init acpi_wakeup_device_init(void)
                                                       struct acpi_device,
                                                       wakeup_list);
                /* In case user doesn't load button driver */
-               if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled)
+               if (!dev->wakeup.flags.always_enabled ||
+                   dev->wakeup.state.enabled)
                        continue;
                acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
                                ACPI_GPE_TYPE_WAKE);
index 3cd9ccd..60fcff4 100644 (file)
@@ -242,6 +242,7 @@ struct acpi_device_perf {
 struct acpi_device_wakeup_flags {
        u8 valid:1;             /* Can successfully enable wakeup? */
        u8 run_wake:1;          /* Run-Wake GPE devices */
+       u8 always_enabled:1;    /* Run-wake devices that are always enabled */
 };
 
 struct acpi_device_wakeup_state {
@@ -256,6 +257,7 @@ struct acpi_device_wakeup {
        struct acpi_device_wakeup_state state;
        struct acpi_device_wakeup_flags flags;
        int prepare_count;
+       int run_wake_count;
 };
 
 /* Device */