===================================================================
@@ -13,6 +13,8 @@
#include <linux/acpi.h>
#include <linux/pm_link.h>
+#include "sleep.h"
+
#define ACPI_GLUE_DEBUG 0
#if ACPI_GLUE_DEBUG
#define DBG(x...) printk(PREFIX x)
@@ -168,6 +170,13 @@ static int acpi_bind_one(struct device *
"physical_node");
if (acpi_dev->wakeup.flags.valid) {
device_set_wakeup_capable(dev, true);
+ /* Allow PCI root bridges to wake up the system. */
+ if (acpi_dev_is_root_bridge(acpi_dev)) {
+ mutex_lock(&acpi_device_lock);
+ acpi_dev->wakeup.state.enabled = true;
+ propagate_enable_wakeup(acpi_dev);
+ mutex_unlock(&acpi_device_lock);
+ }
device_set_wakeup_enable(dev,
acpi_dev->wakeup.state.enabled);
}
===================================================================
@@ -138,26 +138,27 @@ acpi_handle acpi_get_pci_rootbridge_hand
EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
/**
+ * acpi_dev_is_root_bridge - determine if an ACPI device is a PCI root bridge
+ * @device: ACPI device to check.
+ */
+bool acpi_dev_is_root_bridge(struct acpi_device *device)
+{
+ return !acpi_match_device_ids(device, root_device_ids);
+}
+
+/**
* acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
- * @handle - the ACPI CA node in question.
- *
- * Note: we could make this API take a struct acpi_device * instead, but
- * for now, it's more convenient to operate on an acpi_handle.
+ * @handle: the ACPI CA node in question.
*/
int acpi_is_root_bridge(acpi_handle handle)
{
int ret;
struct acpi_device *device;
- ret = acpi_bus_get_device(handle, &device);
+ ret = !acpi_bus_get_device(handle, &device);
if (ret)
- return 0;
-
- ret = acpi_match_device_ids(device, root_device_ids);
- if (ret)
- return 0;
- else
- return 1;
+ ret = acpi_dev_is_root_bridge(device);
+ return ret;
}
EXPORT_SYMBOL_GPL(acpi_is_root_bridge);
===================================================================
@@ -371,6 +371,7 @@ struct device *acpi_get_physical_device(
/* helper */
acpi_handle acpi_get_child(acpi_handle, acpi_integer);
+bool acpi_dev_is_root_bridge(struct acpi_device *);
int acpi_is_root_bridge(acpi_handle);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
===================================================================
@@ -377,14 +377,6 @@ acpi_system_wakeup_device_seq_show(struc
return 0;
}
-static void physical_device_enable_wakeup(struct acpi_device *adev)
-{
- struct device *dev = acpi_get_physical_device(adev->handle);
-
- if (dev && device_can_wakeup(dev))
- device_set_wakeup_enable(dev, adev->wakeup.state.enabled);
-}
-
static ssize_t
acpi_system_write_wakeup_device(struct file *file,
const char __user * buffer,
@@ -420,26 +412,7 @@ acpi_system_write_wakeup_device(struct f
}
if (found_dev) {
physical_device_enable_wakeup(found_dev);
- list_for_each_safe(node, next, &acpi_wakeup_device_list) {
- struct acpi_device *dev = container_of(node,
- struct
- acpi_device,
- wakeup_list);
-
- if ((dev != found_dev) &&
- (dev->wakeup.gpe_number ==
- found_dev->wakeup.gpe_number)
- && (dev->wakeup.gpe_device ==
- found_dev->wakeup.gpe_device)) {
- printk(KERN_WARNING
- "ACPI: '%s' and '%s' have the same GPE, "
- "can't disable/enable one seperately\n",
- dev->pnp.bus_id, found_dev->pnp.bus_id);
- dev->wakeup.state.enabled =
- found_dev->wakeup.state.enabled;
- physical_device_enable_wakeup(dev);
- }
- }
+ propagate_enable_wakeup(found_dev);
}
mutex_unlock(&acpi_device_lock);
return count;
===================================================================
@@ -124,6 +124,41 @@ void acpi_disable_wakeup_device(u8 sleep
}
}
+void physical_device_enable_wakeup(struct acpi_device *adev)
+{
+ struct device *dev = acpi_get_physical_device(adev->handle);
+
+ if (dev && device_can_wakeup(dev))
+ device_set_wakeup_enable(dev, adev->wakeup.state.enabled);
+}
+
+void propagate_enable_wakeup(struct acpi_device *wakeup_dev)
+{
+ struct list_head *node, *next;
+
+ list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+ struct acpi_device *dev =
+ container_of(node, struct acpi_device, wakeup_list);
+
+ if (!dev->wakeup.flags.valid)
+ continue;
+
+ if (dev == wakeup_dev)
+ continue;
+
+ if (dev->wakeup.gpe_number != wakeup_dev->wakeup.gpe_number
+ || dev->wakeup.gpe_device != wakeup_dev->wakeup.gpe_device)
+ continue;
+
+ printk(KERN_WARNING "ACPI: '%s' and '%s' share a GPE, "
+ "unable to disable/enable one seperately\n",
+ dev->pnp.bus_id, wakeup_dev->pnp.bus_id);
+
+ dev->wakeup.state.enabled = wakeup_dev->wakeup.state.enabled;
+ physical_device_enable_wakeup(dev);
+ }
+}
+
int __init acpi_wakeup_device_init(void)
{
struct list_head *node, *next;
===================================================================
@@ -5,6 +5,8 @@ extern int acpi_suspend (u32 state);
extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
extern void acpi_enable_wakeup_device(u8 sleep_state);
extern void acpi_disable_wakeup_device(u8 sleep_state);
+extern void physical_device_enable_wakeup(struct acpi_device *adev);
+extern void propagate_enable_wakeup(struct acpi_device *wakeup_dev);
extern struct list_head acpi_wakeup_device_list;
extern struct mutex acpi_device_lock;