diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2008-07-06 21:34:48 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-07-07 19:26:28 -0400 |
commit | eb9d0fe40e313c0a74115ef456a2e43a6c8da72f (patch) | |
tree | 7a90a68b8dc152d49a38469fd6a6a7840954bac2 /drivers/acpi | |
parent | 0af4b8c4fb31193dc666f4893107a18fef82baab (diff) |
PCI ACPI: Rework PCI handling of wake-up
* Introduce function acpi_pm_device_sleep_wake() for enabling and
disabling the system wake-up capability of devices that are power
manageable by ACPI.
* Introduce function acpi_bus_can_wakeup() allowing other (dependent)
subsystems to check if ACPI is able to enable the system wake-up
capability of given device.
* Introduce callback .sleep_wake() in struct pci_platform_pm_ops and
for the ACPI PCI 'driver' make it use acpi_pm_device_sleep_wake().
* Introduce callback .can_wakeup() in struct pci_platform_pm_ops and
for the ACPI 'driver' make it use acpi_bus_can_wakeup().
* Move the PME# handlig code out of pci_enable_wake() and split it
into two functions, pci_pme_capable() and pci_pme_active(),
allowing the caller to check if given device is capable of
generating PME# from given power state and to enable/disable the
device's PME# functionality, respectively.
* Modify pci_enable_wake() to use the new ACPI callbacks and the new
PME#-related functions.
* Drop the generic .platform_enable_wakeup() callback that is not
used any more.
* Introduce device_set_wakeup_capable() that will set the
power.can_wakeup flag of given device.
* Rework PCI device PM initialization so that, if given device is
capable of generating wake-up events, either natively through the
PME# mechanism, or with the help of the platform, its
power.can_wakeup flag is set and its power.should_wakeup flag is
unset as appropriate.
* Make ACPI set the power.can_wakeup flag for devices found to be
wake-up capable by it.
* Make the ACPI wake-up code enable/disable GPEs for devices that
have the wakeup.flags.prepared flag set (which means that their
wake-up power has been enabled).
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/bus.c | 11 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 2 | ||||
-rw-r--r-- | drivers/acpi/sleep/main.c | 25 | ||||
-rw-r--r-- | drivers/acpi/sleep/wakeup.c | 11 |
4 files changed, 45 insertions, 4 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b9b69d9629b5..fc1110d6a078 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -306,6 +306,17 @@ bool acpi_bus_power_manageable(acpi_handle handle) | |||
306 | 306 | ||
307 | EXPORT_SYMBOL(acpi_bus_power_manageable); | 307 | EXPORT_SYMBOL(acpi_bus_power_manageable); |
308 | 308 | ||
309 | bool acpi_bus_can_wakeup(acpi_handle handle) | ||
310 | { | ||
311 | struct acpi_device *device; | ||
312 | int result; | ||
313 | |||
314 | result = acpi_bus_get_device(handle, &device); | ||
315 | return result ? false : device->wakeup.flags.valid; | ||
316 | } | ||
317 | |||
318 | EXPORT_SYMBOL(acpi_bus_can_wakeup); | ||
319 | |||
309 | /* -------------------------------------------------------------------------- | 320 | /* -------------------------------------------------------------------------- |
310 | Event Management | 321 | Event Management |
311 | -------------------------------------------------------------------------- */ | 322 | -------------------------------------------------------------------------- */ |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 06f8634fe58b..87c5d456e180 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -166,6 +166,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
166 | "firmware_node"); | 166 | "firmware_node"); |
167 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | 167 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, |
168 | "physical_node"); | 168 | "physical_node"); |
169 | if (acpi_dev->wakeup.flags.valid) | ||
170 | device_set_wakeup_capable(dev, true); | ||
169 | } | 171 | } |
170 | 172 | ||
171 | return 0; | 173 | return 0; |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 4addf8ad50ae..af7f4663deaa 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
@@ -468,6 +468,31 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) | |||
468 | *d_min_p = d_min; | 468 | *d_min_p = d_min; |
469 | return d_max; | 469 | return d_max; |
470 | } | 470 | } |
471 | |||
472 | /** | ||
473 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up | ||
474 | * capability of given device | ||
475 | * @dev: device to handle | ||
476 | * @enable: 'true' - enable, 'false' - disable the wake-up capability | ||
477 | */ | ||
478 | int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | ||
479 | { | ||
480 | acpi_handle handle; | ||
481 | struct acpi_device *adev; | ||
482 | |||
483 | if (!device_may_wakeup(dev)) | ||
484 | return -EINVAL; | ||
485 | |||
486 | handle = DEVICE_ACPI_HANDLE(dev); | ||
487 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { | ||
488 | printk(KERN_DEBUG "ACPI handle has no context!\n"); | ||
489 | return -ENODEV; | ||
490 | } | ||
491 | |||
492 | return enable ? | ||
493 | acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : | ||
494 | acpi_disable_wakeup_device_power(adev); | ||
495 | } | ||
471 | #endif | 496 | #endif |
472 | 497 | ||
473 | static void acpi_power_off_prepare(void) | 498 | static void acpi_power_off_prepare(void) |
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 7422a2213944..38655eb132dc 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c | |||
@@ -66,13 +66,15 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
66 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | 66 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
67 | struct acpi_device *dev = | 67 | struct acpi_device *dev = |
68 | container_of(node, struct acpi_device, wakeup_list); | 68 | container_of(node, struct acpi_device, wakeup_list); |
69 | |||
69 | if (!dev->wakeup.flags.valid) | 70 | if (!dev->wakeup.flags.valid) |
70 | continue; | 71 | continue; |
72 | |||
71 | /* If users want to disable run-wake GPE, | 73 | /* If users want to disable run-wake GPE, |
72 | * we only disable it for wake and leave it for runtime | 74 | * we only disable it for wake and leave it for runtime |
73 | */ | 75 | */ |
74 | if (!dev->wakeup.state.enabled || | 76 | if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) |
75 | sleep_state > (u32) dev->wakeup.sleep_state) { | 77 | || sleep_state > (u32) dev->wakeup.sleep_state) { |
76 | if (dev->wakeup.flags.run_wake) { | 78 | if (dev->wakeup.flags.run_wake) { |
77 | spin_unlock(&acpi_device_lock); | 79 | spin_unlock(&acpi_device_lock); |
78 | /* set_gpe_type will disable GPE, leave it like that */ | 80 | /* set_gpe_type will disable GPE, leave it like that */ |
@@ -110,8 +112,9 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
110 | 112 | ||
111 | if (!dev->wakeup.flags.valid) | 113 | if (!dev->wakeup.flags.valid) |
112 | continue; | 114 | continue; |
113 | if (!dev->wakeup.state.enabled || | 115 | |
114 | sleep_state > (u32) dev->wakeup.sleep_state) { | 116 | if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) |
117 | || sleep_state > (u32) dev->wakeup.sleep_state) { | ||
115 | if (dev->wakeup.flags.run_wake) { | 118 | if (dev->wakeup.flags.run_wake) { |
116 | spin_unlock(&acpi_device_lock); | 119 | spin_unlock(&acpi_device_lock); |
117 | acpi_set_gpe_type(dev->wakeup.gpe_device, | 120 | acpi_set_gpe_type(dev->wakeup.gpe_device, |