From cb8f51bdadb7969139c2e39c2defd4cde98c1ea8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Feb 2011 23:26:02 +0100 Subject: PM: Do not create wakeup sysfs files for devices that cannot wake up Currently, wakeup sysfs attributes are created for all devices, regardless of whether or not they are wakeup-capable. This is excessive and complicates wakeup device identification from user space (i.e. to identify wakeup-capable devices user space has to read /sys/devices/.../power/wakeup for all devices and see if they are not empty). Fix this issue by avoiding to create wakeup sysfs files for devices that cannot wake up the system from sleep states (i.e. whose power.can_wakeup flags are unset during registration) and modify device_set_wakeup_capable() so that it adds (or removes) the relevant sysfs attributes if a device's wakeup capability status is changed. Signed-off-by: Rafael J. Wysocki --- include/linux/pm_runtime.h | 6 ++++++ include/linux/pm_wakeup.h | 8 +------- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index d34f067e2a7f..8de9aa6e7def 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -87,6 +87,11 @@ static inline bool pm_runtime_enabled(struct device *dev) return !dev->power.disable_depth; } +static inline bool pm_runtime_callbacks_present(struct device *dev) +{ + return !dev->power.no_callbacks; +} + static inline void pm_runtime_mark_last_busy(struct device *dev) { ACCESS_ONCE(dev->power.last_busy) = jiffies; @@ -133,6 +138,7 @@ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } static inline void pm_runtime_no_callbacks(struct device *dev) {} static inline void pm_runtime_irq_safe(struct device *dev) {} +static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; } static inline void pm_runtime_mark_last_busy(struct device *dev) {} static inline void __pm_runtime_use_autosuspend(struct device *dev, bool use) {} diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index 03a67db03d01..a32da962d693 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h @@ -62,18 +62,11 @@ struct wakeup_source { * Changes to device_may_wakeup take effect on the next pm state change. */ -static inline void device_set_wakeup_capable(struct device *dev, bool capable) -{ - dev->power.can_wakeup = capable; -} - static inline bool device_can_wakeup(struct device *dev) { return dev->power.can_wakeup; } - - static inline bool device_may_wakeup(struct device *dev) { return dev->power.can_wakeup && !!dev->power.wakeup; @@ -88,6 +81,7 @@ extern struct wakeup_source *wakeup_source_register(const char *name); extern void wakeup_source_unregister(struct wakeup_source *ws); extern int device_wakeup_enable(struct device *dev); extern int device_wakeup_disable(struct device *dev); +extern void device_set_wakeup_capable(struct device *dev, bool capable); extern int device_init_wakeup(struct device *dev, bool val); extern int device_set_wakeup_enable(struct device *dev, bool enable); extern void __pm_stay_awake(struct wakeup_source *ws); -- cgit v1.2.3 From cd51e61cf4e8b220da37dc35e9c2dc2dc258b4de Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 11 Feb 2011 00:04:52 +0100 Subject: PM / ACPI: Remove references to pm_flags from bus.c If direct references to pm_flags are removed from drivers/acpi/bus.c, CONFIG_ACPI will not need to depend on CONFIG_PM any more. Make that happen. Signed-off-by: Rafael J. Wysocki Acked-by: Len Brown --- include/linux/suspend.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5a89e3612875..5e364db8a56a 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -272,6 +272,9 @@ extern int unregister_pm_notifier(struct notifier_block *nb); register_pm_notifier(&fn##_nb); \ } +extern bool pm_apm_enabled(void); +extern void pm_set_acpi_flag(void); + /* drivers/base/power/wakeup.c */ extern bool events_check_enabled; @@ -292,6 +295,9 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) #define pm_notifier(fn, pri) do { (void)(fn); } while (0) +static inline bool pm_apm_enabled(void) { return false; } +static inline void pm_set_acpi_flag(void) {} + static inline bool pm_wakeup_pending(void) { return false; } #endif /* !CONFIG_PM_SLEEP */ -- cgit v1.2.3 From aa33860158114d0df3c7997bc1dd41c0168e1c2a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 11 Feb 2011 00:06:54 +0100 Subject: PM: Remove CONFIG_PM_OPS After redefining CONFIG_PM to depend on (CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME) the CONFIG_PM_OPS option is redundant and can be replaced with CONFIG_PM. Signed-off-by: Rafael J. Wysocki --- include/linux/pm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/pm.h b/include/linux/pm.h index 21415cc91cbb..9279175a4557 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -267,7 +267,7 @@ const struct dev_pm_ops name = { \ * callbacks provided by device drivers supporting both the system sleep PM and * runtime PM, make the pm member point to generic_subsys_pm_ops. */ -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM extern struct dev_pm_ops generic_subsys_pm_ops; #define GENERIC_SUBSYS_PM_OPS (&generic_subsys_pm_ops) #else -- cgit v1.2.3 From 6831c6edc7b272a08dd2a6c71bb183a48fe98ae6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 15 Feb 2011 21:22:24 +0100 Subject: PM: Drop pm_flags that is not necessary The variable pm_flags is used to prevent APM from being enabled along with ACPI, which would lead to problems. However, acpi_init() is always called before apm_init() and after acpi_init() has returned, it is known whether or not ACPI will be used. Namely, if acpi_disabled is not set after acpi_init() has returned, this means that ACPI is enabled. Thus, it is sufficient to check acpi_disabled in apm_init() to prevent APM from being enabled in parallel with ACPI. Signed-off-by: Rafael J. Wysocki Acked-by: Len Brown --- include/linux/pm.h | 9 --------- include/linux/suspend.h | 6 ------ 2 files changed, 15 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pm.h b/include/linux/pm.h index 9279175a4557..1f79c98f1e56 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -565,15 +565,6 @@ enum dpm_order { DPM_ORDER_DEV_LAST, }; -/* - * Global Power Management flags - * Used to keep APM and ACPI from both being active - */ -extern unsigned int pm_flags; - -#define PM_APM 1 -#define PM_ACPI 2 - extern int pm_generic_suspend(struct device *dev); extern int pm_generic_resume(struct device *dev); extern int pm_generic_freeze(struct device *dev); diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5e364db8a56a..5a89e3612875 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -272,9 +272,6 @@ extern int unregister_pm_notifier(struct notifier_block *nb); register_pm_notifier(&fn##_nb); \ } -extern bool pm_apm_enabled(void); -extern void pm_set_acpi_flag(void); - /* drivers/base/power/wakeup.c */ extern bool events_check_enabled; @@ -295,9 +292,6 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) #define pm_notifier(fn, pri) do { (void)(fn); } while (0) -static inline bool pm_apm_enabled(void) { return false; } -static inline void pm_set_acpi_flag(void) {} - static inline bool pm_wakeup_pending(void) { return false; } #endif /* !CONFIG_PM_SLEEP */ -- cgit v1.2.3 From 7538e3db6e015e890825fbd9f8659952896ddd5b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 16 Feb 2011 21:53:17 +0100 Subject: PM: Add support for device power domains The platform bus type is often used to handle Systems-on-a-Chip (SoC) where all devices are represented by objects of type struct platform_device. In those cases the same "platform" device driver may be used with multiple different system configurations, but the actions needed to put the devices it handles into a low-power state and back into the full-power state may depend on the design of the given SoC. The driver, however, cannot possibly include all the information necessary for the power management of its device on all the systems it is used with. Moreover, the device hierarchy in its current form also is not suitable for representing this kind of information. The patch below attempts to address this problem by introducing objects of type struct dev_power_domain that can be used for representing power domains within a SoC. Every struct dev_power_domain object provides a sets of device power management callbacks that can be used to perform what's needed for device power management in addition to the operations carried out by the device's driver and subsystem. Namely, if a struct dev_power_domain object is pointed to by the pwr_domain field in a struct device, the callbacks provided by its ops member will be executed in addition to the corresponding callbacks provided by the device's subsystem and driver during all power transitions. Signed-off-by: Rafael J. Wysocki Tested-and-acked-by: Kevin Hilman --- include/linux/device.h | 1 + include/linux/pm.h | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'include/linux') diff --git a/include/linux/device.h b/include/linux/device.h index 1bf5cf0b4513..22e9a8a7e1bc 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -422,6 +422,7 @@ struct device { void *platform_data; /* Platform specific data, device core doesn't touch it */ struct dev_pm_info power; + struct dev_power_domain *pwr_domain; #ifdef CONFIG_NUMA int numa_node; /* NUMA node this device is close to */ diff --git a/include/linux/pm.h b/include/linux/pm.h index 1f79c98f1e56..6618216bb973 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -465,6 +465,14 @@ struct dev_pm_info { extern void update_pm_runtime_accounting(struct device *dev); +/* + * Power domains provide callbacks that are executed during system suspend, + * hibernation, system resume and during runtime PM transitions along with + * subsystem-level and driver-level callbacks. + */ +struct dev_power_domain { + struct dev_pm_ops ops; +}; /* * The PM_EVENT_ messages are also used by drivers implementing the legacy -- cgit v1.2.3 From 40dc166cb5dddbd36aa4ad11c03915ea538f5a61 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 15 Mar 2011 00:43:46 +0100 Subject: PM / Core: Introduce struct syscore_ops for core subsystems PM Some subsystems need to carry out suspend/resume and shutdown operations with one CPU on-line and interrupts disabled. The only way to register such operations is to define a sysdev class and a sysdev specifically for this purpose which is cumbersome and inefficient. Moreover, the arguments taken by sysdev suspend, resume and shutdown callbacks are practically never necessary. For this reason, introduce a simpler interface allowing subsystems to register operations to be executed very late during system suspend and shutdown and very early during resume in the form of strcut syscore_ops objects. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman --- include/linux/syscore_ops.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 include/linux/syscore_ops.h (limited to 'include/linux') diff --git a/include/linux/syscore_ops.h b/include/linux/syscore_ops.h new file mode 100644 index 000000000000..27b3b0bc41a9 --- /dev/null +++ b/include/linux/syscore_ops.h @@ -0,0 +1,29 @@ +/* + * syscore_ops.h - System core operations. + * + * Copyright (C) 2011 Rafael J. Wysocki , Novell Inc. + * + * This file is released under the GPLv2. + */ + +#ifndef _LINUX_SYSCORE_OPS_H +#define _LINUX_SYSCORE_OPS_H + +#include + +struct syscore_ops { + struct list_head node; + int (*suspend)(void); + void (*resume)(void); + void (*shutdown)(void); +}; + +extern void register_syscore_ops(struct syscore_ops *ops); +extern void unregister_syscore_ops(struct syscore_ops *ops); +#ifdef CONFIG_PM_SLEEP +extern int syscore_suspend(void); +extern void syscore_resume(void); +#endif +extern void syscore_shutdown(void); + +#endif -- cgit v1.2.3