[linux-pm] [patch 2.6.25-rc6 5/7] ACPI sets up device.power.can_wakeup flags

David Brownell david-b at pacbell.net
Thu Mar 20 14:20:40 PDT 2008


This exports the "acpi_device.wakeup.flags.valid" flag to the driver
model as "device.power.can_wakeup".  That is, each "ACPI device" in
the /proc/acpi/wakeup file that corresponds to a "real" device will
initialize the can_wakeup flag to true.

A separate patch is needed to make ACPI pay attention to the userspace
input:  devices that can_wakeup have a should_wakeup flag, initially
true, which is settable via sysfs and tested using device_may_wakeup().
That's intended to be the primary policy input to the system, not the
ACPI-specific /proc/acpi/wakeup file.

Note also that the ACPI tables list only motherboard devices, but many
systems include more peripherals than those.  While the USB framework
handles USB peripherals, nothing in Linux currently sets those flags
for wakeup-capable devices on other expansion busses (like PCI).

Signed-off-by: David Brownell <dbrownell at users.sourceforge.net>
---
 drivers/acpi/button.c |    3 +++
 drivers/acpi/glue.c   |    1 +
 drivers/acpi/power.c  |    4 ++++
 3 files changed, 8 insertions(+)

--- g26.orig/drivers/acpi/button.c	2008-03-20 03:02:45.000000000 -0700
+++ g26/drivers/acpi/button.c	2008-03-20 03:27:24.000000000 -0700
@@ -476,6 +476,9 @@ static int acpi_button_add(struct acpi_d
 	if (button->type == ACPI_BUTTON_TYPE_LID)
 		acpi_lid_send_state(button);
 
+	/* for these devices the ACPI node *IS* the "physical" device */
+	device_init_wakeup(&device->dev, device->wakeup.flags.valid);
+
 	if (device->wakeup.flags.valid) {
 		/* Button's GPE is run-wake GPE */
 		acpi_set_gpe_type(device->wakeup.gpe_device,
--- g26.orig/drivers/acpi/glue.c	2008-03-20 03:27:11.000000000 -0700
+++ g26/drivers/acpi/glue.c	2008-03-20 03:27:25.000000000 -0700
@@ -162,6 +162,7 @@ static int acpi_bind_one(struct device *
 	if (!ACPI_FAILURE(status)) {
 		int ret;
 
+		device_init_wakeup(dev, acpi_dev->wakeup.flags.valid);
 		ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
 				"firmware_node");
 		if (ret != 0)
--- g26.orig/drivers/acpi/power.c	2008-03-20 03:02:45.000000000 -0700
+++ g26/drivers/acpi/power.c	2008-03-20 03:27:25.000000000 -0700
@@ -313,6 +313,7 @@ int acpi_enable_wakeup_device_power(stru
 		ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
+			device_init_wakeup(&dev->dev, 0);
 			dev->wakeup.flags.valid = 0;
 			return -1;
 		}
@@ -322,6 +323,7 @@ int acpi_enable_wakeup_device_power(stru
 	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
 	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
 		printk(KERN_ERR PREFIX "Evaluate _PSW\n");
+		device_init_wakeup(&dev->dev, 0);
 		dev->wakeup.flags.valid = 0;
 		ret = -1;
 	}
@@ -351,6 +353,7 @@ int acpi_disable_wakeup_device_power(str
 	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
 	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
 		printk(KERN_ERR PREFIX "Evaluate _PSW\n");
+		device_init_wakeup(&dev->dev, 0);
 		dev->wakeup.flags.valid = 0;
 		return -1;
 	}
@@ -360,6 +363,7 @@ int acpi_disable_wakeup_device_power(str
 		ret = acpi_power_off_device(dev->wakeup.resources.handles[i], dev);
 		if (ret) {
 			printk(KERN_ERR PREFIX "Transition power state\n");
+			device_init_wakeup(&dev->dev, 0);
 			dev->wakeup.flags.valid = 0;
 			return -1;
 		}


More information about the linux-pm mailing list