From 439913fffd39374c3737186b22d2d56c3a0ae526 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 28 Jan 2010 10:53:19 +0800 Subject: ACPI: replace acpi_integer by u64 acpi_integer is now obsolete and removed from the ACPICA code base, replaced by u64. Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpi_bus.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 3cd9ccdcbd8..71c105c9b0e 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -250,8 +250,8 @@ struct acpi_device_wakeup_state { struct acpi_device_wakeup { acpi_handle gpe_device; - acpi_integer gpe_number; - acpi_integer sleep_state; + u64 gpe_number; + u64 sleep_state; struct acpi_handle_list resources; struct acpi_device_wakeup_state state; struct acpi_device_wakeup_flags flags; @@ -380,7 +380,7 @@ struct acpi_pci_root { }; /* helper */ -acpi_handle acpi_get_child(acpi_handle, acpi_integer); +acpi_handle acpi_get_child(acpi_handle, u64); int acpi_is_root_bridge(acpi_handle); acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); -- cgit v1.2.3-70-g09d2 From f517709d65beed95f52f021b43e3035b52ef791a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 17 Feb 2010 23:41:49 +0100 Subject: ACPI / PM: Add more run-time wake-up fields 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 Acked-by: Len Brown Signed-off-by: Jesse Barnes --- drivers/acpi/button.c | 2 ++ drivers/acpi/scan.c | 37 +++++++++++++++++++++++++++---------- drivers/acpi/wakeup.c | 3 ++- include/acpi/acpi_bus.h | 2 ++ 4 files changed, 33 insertions(+), 11 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 09ca3ce7a05..f53fbe307c9 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -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; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 3e009674f33..7491a52ad97 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -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; diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index 6783986c746..4b9d339a6e2 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c @@ -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); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 3cd9ccdcbd8..60fcff41935 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -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 */ -- cgit v1.2.3-70-g09d2 From b67ea76172d4b1922c4b3c46c8ea8e9fec1ff38c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 17 Feb 2010 23:44:09 +0100 Subject: PCI / ACPI / PM: Platform support for PCI PME wake-up Although the majority of PCI devices can generate PMEs that in principle may be used to wake up devices suspended at run time, platform support is generally necessary to convert PMEs into wake-up events that can be delivered to the kernel. If ACPI is used for this purpose, PME signals generated by a PCI device will trigger the ACPI GPE associated with the device to generate an ACPI wake-up event that we can set up a handler for, provided that everything is configured correctly. Unfortunately, the subset of PCI devices that have GPEs associated with them is quite limited. The devices without dedicated GPEs have to rely on the GPEs associated with other devices (in the majority of cases their upstream bridges and, possibly, the root bridge) to generate ACPI wake-up events in response to PME signals from them. Add ACPI platform support for PCI PME wake-up: o Add a framework making is possible to use ACPI system notify handlers for run-time PM. o Add new PCI platform callback ->run_wake() to struct pci_platform_pm_ops allowing us to enable/disable the platform to generate wake-up events for given device. Implemet this callback for the ACPI platform. o Define ACPI wake-up handlers for PCI devices and PCI root buses and make the PCI-ACPI binding code register wake-up notifiers for all PCI devices present in the ACPI tables. o Add function pci_dev_run_wake() which can be used by PCI drivers to check if given device is capable of generating wake-up events at run time. Developed in cooperation with Matthew Garrett . Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/acpi/internal.h | 2 - drivers/acpi/pci_bind.c | 14 +++- drivers/acpi/pci_root.c | 8 ++ drivers/acpi/scan.c | 1 + drivers/pci/pci-acpi.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/pci.c | 67 +++++++++++++++ drivers/pci/pci.h | 7 ++ include/acpi/acpi_bus.h | 4 + include/linux/pci-acpi.h | 7 ++ include/linux/pci.h | 1 + 10 files changed, 319 insertions(+), 3 deletions(-) (limited to 'include/acpi/acpi_bus.h') diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index cb28e0502ac..9c4c962e46e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -36,8 +36,6 @@ static inline int acpi_debug_init(void) { return 0; } int acpi_power_init(void); int acpi_device_sleep_wake(struct acpi_device *dev, int enable, int sleep_state, int dev_state); -int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); -int acpi_disable_wakeup_device_power(struct acpi_device *dev); int acpi_power_get_inferred_state(struct acpi_device *device); int acpi_power_transition(struct acpi_device *device, int state); extern int acpi_power_nocheck; diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index a5a77b78a72..2ef04098cc1 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -26,7 +26,9 @@ #include #include #include +#include #include +#include #include #include @@ -38,7 +40,13 @@ static int acpi_pci_unbind(struct acpi_device *device) struct pci_dev *dev; dev = acpi_get_pci_dev(device->handle); - if (!dev || !dev->subordinate) + if (!dev) + goto out; + + device_set_run_wake(&dev->dev, false); + pci_acpi_remove_pm_notifier(device); + + if (!dev->subordinate) goto out; acpi_pci_irq_del_prt(dev->subordinate); @@ -62,6 +70,10 @@ static int acpi_pci_bind(struct acpi_device *device) if (!dev) return 0; + pci_acpi_add_pm_notifier(device, dev); + if (device->wakeup.flags.run_wake) + device_set_run_wake(&dev->dev, true); + /* * Install the 'bind' function to facilitate callbacks for * children of the P2P bridge. diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 64f55b6db73..9cd8bedb1e5 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -528,6 +529,10 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (flags != base_flags) acpi_pci_osc_support(root, flags); + pci_acpi_add_bus_pm_notifier(device, root->bus); + if (device->wakeup.flags.run_wake) + device_set_run_wake(root->bus->bridge, true); + return 0; end: @@ -549,6 +554,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) { struct acpi_pci_root *root = acpi_driver_data(device); + device_set_run_wake(root->bus->bridge, false); + pci_acpi_remove_bus_pm_notifier(device); + kfree(root); return 0; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7491a52ad97..fb7fc24fe72 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -753,6 +753,7 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) acpi_event_status event_status; device->wakeup.run_wake_count = 0; + device->wakeup.flags.notifier_present = 0; /* Power button, Lid switch always enable wakeup */ if (!acpi_match_device_ids(device, button_device_ids)) { diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 7e2829538a4..c0c73913833 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -16,8 +16,144 @@ #include #include +#include #include "pci.h" +static DEFINE_MUTEX(pci_acpi_pm_notify_mtx); + +/** + * pci_acpi_wake_bus - Wake-up notification handler for root buses. + * @handle: ACPI handle of a device the notification is for. + * @event: Type of the signaled event. + * @context: PCI root bus to wake up devices on. + */ +static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context) +{ + struct pci_bus *pci_bus = context; + + if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus) + pci_pme_wakeup_bus(pci_bus); +} + +/** + * pci_acpi_wake_dev - Wake-up notification handler for PCI devices. + * @handle: ACPI handle of a device the notification is for. + * @event: Type of the signaled event. + * @context: PCI device object to wake up. + */ +static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) +{ + struct pci_dev *pci_dev = context; + + if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) { + pci_check_pme_status(pci_dev); + pm_runtime_resume(&pci_dev->dev); + if (pci_dev->subordinate) + pci_pme_wakeup_bus(pci_dev->subordinate); + } +} + +/** + * add_pm_notifier - Register PM notifier for given ACPI device. + * @dev: ACPI device to add the notifier for. + * @context: PCI device or bus to check for PME status if an event is signaled. + * + * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of + * PM wake-up events. For example, wake-up events may be generated for bridges + * if one of the devices below the bridge is signaling PME, even if the bridge + * itself doesn't have a wake-up GPE associated with it. + */ +static acpi_status add_pm_notifier(struct acpi_device *dev, + acpi_notify_handler handler, + void *context) +{ + acpi_status status = AE_ALREADY_EXISTS; + + mutex_lock(&pci_acpi_pm_notify_mtx); + + if (dev->wakeup.flags.notifier_present) + goto out; + + status = acpi_install_notify_handler(dev->handle, + ACPI_SYSTEM_NOTIFY, + handler, context); + if (ACPI_FAILURE(status)) + goto out; + + dev->wakeup.flags.notifier_present = true; + + out: + mutex_unlock(&pci_acpi_pm_notify_mtx); + return status; +} + +/** + * remove_pm_notifier - Unregister PM notifier from given ACPI device. + * @dev: ACPI device to remove the notifier from. + */ +static acpi_status remove_pm_notifier(struct acpi_device *dev, + acpi_notify_handler handler) +{ + acpi_status status = AE_BAD_PARAMETER; + + mutex_lock(&pci_acpi_pm_notify_mtx); + + if (!dev->wakeup.flags.notifier_present) + goto out; + + status = acpi_remove_notify_handler(dev->handle, + ACPI_SYSTEM_NOTIFY, + handler); + if (ACPI_FAILURE(status)) + goto out; + + dev->wakeup.flags.notifier_present = false; + + out: + mutex_unlock(&pci_acpi_pm_notify_mtx); + return status; +} + +/** + * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. + * @dev: ACPI device to add the notifier for. + * @pci_bus: PCI bus to walk checking for PME status if an event is signaled. + */ +acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, + struct pci_bus *pci_bus) +{ + return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); +} + +/** + * pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier. + * @dev: ACPI device to remove the notifier from. + */ +acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) +{ + return remove_pm_notifier(dev, pci_acpi_wake_bus); +} + +/** + * pci_acpi_add_pm_notifier - Register PM notifier for given PCI device. + * @dev: ACPI device to add the notifier for. + * @pci_dev: PCI device to check for the PME status if an event is signaled. + */ +acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, + struct pci_dev *pci_dev) +{ + return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); +} + +/** + * pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier. + * @dev: ACPI device to remove the notifier from. + */ +acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) +{ + return remove_pm_notifier(dev, pci_acpi_wake_dev); +} + /* * _SxD returns the D-state with the highest power * (lowest D-state number) supported in the S-state "x". @@ -131,12 +267,87 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) return 0; } +/** + * acpi_dev_run_wake - Enable/disable wake-up for given device. + * @phys_dev: Device to enable/disable the platform to wake-up the system for. + * @enable: Whether enable or disable the wake-up functionality. + * + * Find the ACPI device object corresponding to @pci_dev and try to + * enable/disable the GPE associated with it. + */ +static int acpi_dev_run_wake(struct device *phys_dev, bool enable) +{ + struct acpi_device *dev; + acpi_handle handle; + int error = -ENODEV; + + if (!device_run_wake(phys_dev)) + return -EINVAL; + + handle = DEVICE_ACPI_HANDLE(phys_dev); + if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) { + dev_dbg(phys_dev, "ACPI handle has no context in %s!\n", + __func__); + return -ENODEV; + } + + if (enable) { + if (!dev->wakeup.run_wake_count++) { + acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0); + acpi_enable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, + ACPI_GPE_TYPE_RUNTIME); + } + } else if (dev->wakeup.run_wake_count > 0) { + if (!--dev->wakeup.run_wake_count) { + acpi_disable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, + ACPI_GPE_TYPE_RUNTIME); + acpi_disable_wakeup_device_power(dev); + } + } else { + error = -EALREADY; + } + + return error; +} + +static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) +{ + while (bus->parent) { + struct pci_dev *bridge = bus->self; + + if (bridge->pme_interrupt) + return; + if (!acpi_dev_run_wake(&bridge->dev, enable)) + return; + bus = bus->parent; + } + + /* We have reached the root bus. */ + if (bus->bridge) + acpi_dev_run_wake(bus->bridge, enable); +} + +static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) +{ + if (dev->pme_interrupt) + return 0; + + if (!acpi_dev_run_wake(&dev->dev, enable)) + return 0; + + acpi_pci_propagate_run_wake(dev->bus, enable); + return 0; +} + static struct pci_platform_pm_ops acpi_pci_platform_pm = { .is_manageable = acpi_pci_power_manageable, .set_state = acpi_pci_set_power_state, .choose_state = acpi_pci_choose_state, .can_wakeup = acpi_pci_can_wakeup, .sleep_wake = acpi_pci_sleep_wake, + .run_wake = acpi_pci_run_wake, }; /* ACPI bus type */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 5723446544f..df55a2f351b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "pci.h" @@ -462,6 +463,12 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; } +static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable) +{ + return pci_platform_pm ? + pci_platform_pm->run_wake(dev, enable) : -ENODEV; +} + /** * pci_raw_set_power_state - Use PCI PM registers to set the power state of * given PCI device @@ -1229,6 +1236,31 @@ bool pci_check_pme_status(struct pci_dev *dev) return ret; } +/** + * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. + * @dev: Device to handle. + * @ign: Ignored. + * + * Check if @dev has generated PME and queue a resume request for it in that + * case. + */ +static int pci_pme_wakeup(struct pci_dev *dev, void *ign) +{ + if (pci_check_pme_status(dev)) + pm_request_resume(&dev->dev); + return 0; +} + +/** + * pci_pme_wakeup_bus - Walk given bus and wake up devices on it, if necessary. + * @bus: Top bus of the subtree to walk. + */ +void pci_pme_wakeup_bus(struct pci_bus *bus) +{ + if (bus) + pci_walk_bus(bus, pci_pme_wakeup, NULL); +} + /** * pci_pme_capable - check the capability of PCI device to generate PME# * @dev: PCI device to handle. @@ -1433,6 +1465,41 @@ int pci_back_from_sleep(struct pci_dev *dev) return pci_set_power_state(dev, PCI_D0); } +/** + * pci_dev_run_wake - Check if device can generate run-time wake-up events. + * @dev: Device to check. + * + * Return true if the device itself is cabable of generating wake-up events + * (through the platform or using the native PCIe PME) or if the device supports + * PME and one of its upstream bridges can generate wake-up events. + */ +bool pci_dev_run_wake(struct pci_dev *dev) +{ + struct pci_bus *bus = dev->bus; + + if (device_run_wake(&dev->dev)) + return true; + + if (!dev->pme_support) + return false; + + while (bus->parent) { + struct pci_dev *bridge = bus->self; + + if (device_run_wake(&bridge->dev)) + return true; + + bus = bus->parent; + } + + /* We have reached the root bus. */ + if (bus->bridge) + return device_run_wake(bus->bridge); + + return false; +} +EXPORT_SYMBOL_GPL(pci_dev_run_wake); + /** * pci_pm_init - Initialize PM functions of given PCI device * @dev: PCI device to handle. diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index b95b0a077d3..286c5082194 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -35,6 +35,10 @@ int pci_probe_reset_function(struct pci_dev *dev); * * @sleep_wake: enables/disables the system wake up capability of given device * + * @run_wake: enables/disables the platform to generate run-time wake-up events + * for given device (the device's wake-up capability has to be + * enabled by @sleep_wake for this feature to work) + * * If given platform is generally capable of power managing PCI devices, all of * these callbacks are mandatory. */ @@ -44,12 +48,15 @@ struct pci_platform_pm_ops { pci_power_t (*choose_state)(struct pci_dev *dev); bool (*can_wakeup)(struct pci_dev *dev); int (*sleep_wake)(struct pci_dev *dev, bool enable); + int (*run_wake)(struct pci_dev *dev, bool enable); }; extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); extern void pci_disable_enabled_device(struct pci_dev *dev); extern bool pci_check_pme_status(struct pci_dev *dev); +extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); +extern void pci_pme_wakeup_bus(struct pci_bus *bus); extern void pci_pm_init(struct pci_dev *dev); extern void platform_pci_wakeup_init(struct pci_dev *dev); extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 60fcff41935..54508ccea02 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -243,6 +243,7 @@ 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 */ + u8 notifier_present:1; /* Wake-up notify handler has been installed */ }; struct acpi_device_wakeup_state { @@ -388,6 +389,9 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) +int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); +int acpi_disable_wakeup_device_power(struct acpi_device *dev); + #ifdef CONFIG_PM_SLEEP int acpi_pm_device_sleep_state(struct device *, int *); int acpi_pm_device_sleep_wake(struct device *, bool); diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 93a7c08f869..c8b6473c5f4 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -11,6 +11,13 @@ #include #ifdef CONFIG_ACPI +extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, + struct pci_bus *pci_bus); +extern acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev); +extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, + struct pci_dev *pci_dev); +extern acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev); + static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) { struct pci_bus *pbus = pdev->bus; diff --git a/include/linux/pci.h b/include/linux/pci.h index 9fe4b2089b7..3f787ce78bd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -782,6 +782,7 @@ int pci_wake_from_d3(struct pci_dev *dev, bool enable); pci_power_t pci_target_state(struct pci_dev *dev); int pci_prepare_to_sleep(struct pci_dev *dev); int pci_back_from_sleep(struct pci_dev *dev); +bool pci_dev_run_wake(struct pci_dev *dev); /* For use by arch with custom probe code */ void set_pcie_port_type(struct pci_dev *pdev); -- cgit v1.2.3-70-g09d2