From 0d4b54c6fee87ff60b0bc1007ca487449698468d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 18 Nov 2017 15:31:49 +0100 Subject: PM / core: Add LEAVE_SUSPENDED driver flag Define and document a new driver flag, DPM_FLAG_LEAVE_SUSPENDED, to instruct the PM core and middle-layer (bus type, PM domain, etc.) code that it is desirable to leave the device in runtime suspend after system-wide transitions to the working state (for example, the device may be slow to resume and it may be better to avoid resuming it right away). Generally, the middle-layer code involved in the handling of the device is expected to indicate to the PM core whether or not the device may be left in suspend with the help of the device's power.may_skip_resume status bit. That has to happen in the "noirq" phase of the preceding system suspend (or analogous) transition. The middle layer is then responsible for handling the device as appropriate in its "noirq" resume callback which is executed regardless of whether or not the device may be left suspended, but the other resume callbacks (except for ->complete) will be skipped automatically by the core if the device really can be left in suspend. The additional power.must_resume status bit introduced for the implementation of this mechanisn is used internally by the PM core to track the requirement to resume the device (which may depend on its children etc). Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Reviewed-by: Ulf Hansson --- include/linux/pm.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pm.h b/include/linux/pm.h index 65d39115f06d..b5a40b713e9e 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -556,9 +556,10 @@ struct pm_subsys_data { * These flags can be set by device drivers at the probe time. They need not be * cleared by the drivers as the driver core will take care of that. * - * NEVER_SKIP: Do not skip system suspend/resume callbacks for the device. + * NEVER_SKIP: Do not skip all system suspend/resume callbacks for the device. * SMART_PREPARE: Check the return value of the driver's ->prepare callback. * SMART_SUSPEND: No need to resume the device from runtime suspend. + * LEAVE_SUSPENDED: Avoid resuming the device during system resume if possible. * * Setting SMART_PREPARE instructs bus types and PM domains which may want * system suspend/resume callbacks to be skipped for the device to return 0 from @@ -572,10 +573,14 @@ struct pm_subsys_data { * necessary from the driver's perspective. It also may cause them to skip * invocations of the ->suspend_late and ->suspend_noirq callbacks provided by * the driver if they decide to leave the device in runtime suspend. + * + * Setting LEAVE_SUSPENDED informs the PM core and middle-layer code that the + * driver prefers the device to be left in suspend after system resume. */ -#define DPM_FLAG_NEVER_SKIP BIT(0) -#define DPM_FLAG_SMART_PREPARE BIT(1) -#define DPM_FLAG_SMART_SUSPEND BIT(2) +#define DPM_FLAG_NEVER_SKIP BIT(0) +#define DPM_FLAG_SMART_PREPARE BIT(1) +#define DPM_FLAG_SMART_SUSPEND BIT(2) +#define DPM_FLAG_LEAVE_SUSPENDED BIT(3) struct dev_pm_info { pm_message_t power_state; @@ -597,6 +602,8 @@ struct dev_pm_info { bool wakeup_path:1; bool syscore:1; bool no_pm_callbacks:1; /* Owned by the PM core */ + unsigned int must_resume:1; /* Owned by the PM core */ + unsigned int may_skip_resume:1; /* Set by subsystems */ #else unsigned int should_wakeup:1; #endif @@ -765,6 +772,7 @@ extern int pm_generic_poweroff_late(struct device *dev); extern int pm_generic_poweroff(struct device *dev); extern void pm_generic_complete(struct device *dev); +extern bool dev_pm_may_skip_resume(struct device *dev); extern bool dev_pm_smart_suspend_and_suspended(struct device *dev); #else /* !CONFIG_PM_SLEEP */ -- cgit v1.2.3 From 57044031b0cb11325e1034394a4721484f9dc9fe Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 15 Nov 2017 02:16:55 +0100 Subject: ACPI / PM: Make it possible to ignore the system sleep blacklist The ACPI code supporting system transitions to sleep states uses an internal blacklist to apply special handling to some machines reported to behave incorrectly in some ways. However, some entries of that blacklist cover problematic as well as non-problematic systems, so give the users of the latter a chance to ignore the blacklist and run their systems in the default way by adding acpi_sleep=nobl to the kernel command line. For example, that allows the users of Dell XPS13 9360 systems not affected by the issue that caused the blacklist entry for this machine to be added by commit 71630b7a832f (ACPI / PM: Blacklist Low Power S0 Idle _DSM for Dell XPS13 9360) to use suspend-to-idle with the Low Power S0 Idle _DSM interface which in principle should be more energy-efficient than S3 on them. Signed-off-by: Rafael J. Wysocki --- include/linux/acpi.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/acpi.h b/include/linux/acpi.h index dc1ebfeeb5ec..699655a9618b 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -451,6 +451,7 @@ void __init acpi_no_s4_hw_signature(void); void __init acpi_old_suspend_ordering(void); void __init acpi_nvs_nosave(void); void __init acpi_nvs_nosave_s3(void); +void __init acpi_sleep_no_blacklist(void); #endif /* CONFIG_PM_SLEEP */ struct acpi_osc_context { -- cgit v1.2.3 From f5f263fed66f75a4482d7ad49392b4283a05885a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 5 Dec 2017 11:02:43 +0530 Subject: cpu_cooling: Make of_cpufreq_power_cooling_register() parse DT All the callers of of_cpufreq_power_cooling_register() have almost identical code and it makes more sense to move that code into the helper as its all about reading DT properties. This got rid of lot of redundant code. Acked-by: Eduardo Valentin Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpu_cooling.h | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h index d4292ebc5c8b..f09d4feb34f4 100644 --- a/include/linux/cpu_cooling.h +++ b/include/linux/cpu_cooling.h @@ -56,10 +56,7 @@ of_cpufreq_cooling_register(struct device_node *np, struct cpufreq_policy *policy); struct thermal_cooling_device * -of_cpufreq_power_cooling_register(struct device_node *np, - struct cpufreq_policy *policy, - u32 capacitance, - get_static_t plat_static_func); +of_cpufreq_power_cooling_register(struct cpufreq_policy *policy); #else static inline struct thermal_cooling_device * of_cpufreq_cooling_register(struct device_node *np, @@ -69,10 +66,7 @@ of_cpufreq_cooling_register(struct device_node *np, } static inline struct thermal_cooling_device * -of_cpufreq_power_cooling_register(struct device_node *np, - struct cpufreq_policy *policy, - u32 capacitance, - get_static_t plat_static_func) +of_cpufreq_power_cooling_register(struct cpufreq_policy *policy) { return NULL; } @@ -105,10 +99,7 @@ of_cpufreq_cooling_register(struct device_node *np, } static inline struct thermal_cooling_device * -of_cpufreq_power_cooling_register(struct device_node *np, - struct cpufreq_policy *policy, - u32 capacitance, - get_static_t plat_static_func) +of_cpufreq_power_cooling_register(struct cpufreq_policy *policy) { return NULL; } -- cgit v1.2.3 From ba0966da208ef0793486502a0e6b929fbd6d4223 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 5 Dec 2017 11:02:44 +0530 Subject: cpu_cooling: Remove unused cpufreq_power_cooling_register() It isn't used by anyone, drop it. Acked-by: Eduardo Valentin Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpu_cooling.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h index f09d4feb34f4..c35778960a9c 100644 --- a/include/linux/cpu_cooling.h +++ b/include/linux/cpu_cooling.h @@ -41,10 +41,6 @@ typedef int (*get_static_t)(cpumask_t *cpumask, int interval, struct thermal_cooling_device * cpufreq_cooling_register(struct cpufreq_policy *policy); -struct thermal_cooling_device * -cpufreq_power_cooling_register(struct cpufreq_policy *policy, - u32 capacitance, get_static_t plat_static_func); - /** * of_cpufreq_cooling_register - create cpufreq cooling device based on DT. * @np: a valid struct device_node to the cooling device device tree node. @@ -84,12 +80,6 @@ cpufreq_cooling_register(struct cpufreq_policy *policy) { return ERR_PTR(-ENOSYS); } -static inline struct thermal_cooling_device * -cpufreq_power_cooling_register(struct cpufreq_policy *policy, - u32 capacitance, get_static_t plat_static_func) -{ - return NULL; -} static inline struct thermal_cooling_device * of_cpufreq_cooling_register(struct device_node *np, -- cgit v1.2.3 From 3ebb62ffc4e4817c3288cdf7ed67ccaf453385e3 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 5 Dec 2017 11:02:45 +0530 Subject: cpu_cooling: Keep only one of_cpufreq*cooling_register() helper of_cpufreq_cooling_register() isn't used by anyone and so can be removed, but then we would be left with two routines: cpufreq_cooling_register() and of_cpufreq_power_cooling_register() that would look odd. Remove current implementation of of_cpufreq_cooling_register() and rename of_cpufreq_power_cooling_register() as of_cpufreq_cooling_register(). This simplifies lots of stuff. Acked-by: Eduardo Valentin Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpu_cooling.h | 53 ++++++++++++--------------------------------- 1 file changed, 14 insertions(+), 39 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h index c35778960a9c..fd0ea8ddca93 100644 --- a/include/linux/cpu_cooling.h +++ b/include/linux/cpu_cooling.h @@ -41,33 +41,6 @@ typedef int (*get_static_t)(cpumask_t *cpumask, int interval, struct thermal_cooling_device * cpufreq_cooling_register(struct cpufreq_policy *policy); -/** - * of_cpufreq_cooling_register - create cpufreq cooling device based on DT. - * @np: a valid struct device_node to the cooling device device tree node. - * @policy: cpufreq policy. - */ -#ifdef CONFIG_THERMAL_OF -struct thermal_cooling_device * -of_cpufreq_cooling_register(struct device_node *np, - struct cpufreq_policy *policy); - -struct thermal_cooling_device * -of_cpufreq_power_cooling_register(struct cpufreq_policy *policy); -#else -static inline struct thermal_cooling_device * -of_cpufreq_cooling_register(struct device_node *np, - struct cpufreq_policy *policy) -{ - return ERR_PTR(-ENOSYS); -} - -static inline struct thermal_cooling_device * -of_cpufreq_power_cooling_register(struct cpufreq_policy *policy) -{ - return NULL; -} -#endif - /** * cpufreq_cooling_unregister - function to remove cpufreq cooling device. * @cdev: thermal cooling device pointer. @@ -81,24 +54,26 @@ cpufreq_cooling_register(struct cpufreq_policy *policy) return ERR_PTR(-ENOSYS); } -static inline struct thermal_cooling_device * -of_cpufreq_cooling_register(struct device_node *np, - struct cpufreq_policy *policy) +static inline +void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) { - return ERR_PTR(-ENOSYS); + return; } +#endif /* CONFIG_CPU_THERMAL */ +#if defined(CONFIG_THERMAL_OF) && defined(CONFIG_CPU_THERMAL) +/** + * of_cpufreq_cooling_register - create cpufreq cooling device based on DT. + * @policy: cpufreq policy. + */ +struct thermal_cooling_device * +of_cpufreq_cooling_register(struct cpufreq_policy *policy); +#else static inline struct thermal_cooling_device * -of_cpufreq_power_cooling_register(struct cpufreq_policy *policy) +of_cpufreq_cooling_register(struct cpufreq_policy *policy) { return NULL; } - -static inline -void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) -{ - return; -} -#endif /* CONFIG_CPU_THERMAL */ +#endif /* defined(CONFIG_THERMAL_OF) && defined(CONFIG_CPU_THERMAL) */ #endif /* __CPU_COOLING_H__ */ -- cgit v1.2.3 From 84fe2cab48590e4373978e4ef2031c977de98995 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 5 Dec 2017 11:02:46 +0530 Subject: cpu_cooling: Drop static-power related stuff No one has used it for the last two and half years (since it was introduced by commit c36cf0717631 (thermal: cpu_cooling: implement the power cooling device API), get rid of it. Acked-by: Eduardo Valentin Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpu_cooling.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpu_cooling.h b/include/linux/cpu_cooling.h index fd0ea8ddca93..de0dafb9399d 100644 --- a/include/linux/cpu_cooling.h +++ b/include/linux/cpu_cooling.h @@ -30,9 +30,6 @@ struct cpufreq_policy; -typedef int (*get_static_t)(cpumask_t *cpumask, int interval, - unsigned long voltage, u32 *power); - #ifdef CONFIG_CPU_THERMAL /** * cpufreq_cooling_register - function to create cpufreq cooling device. -- cgit v1.2.3 From cf04ce7841fabc7af0d6ee273711ec29658bee7b Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 2 Jan 2018 17:08:52 +0100 Subject: PM / wakeup: Add device_set_wakeup_path() helper to control wakeup path During system suspend, a driver may find that the wakeup setting is enabled for its device and therefore configures it to deliver system wakeup signals. Additionally, sometimes the driver and its device, relies on some further consumed resource, like an irqchip or a phy for example, to stay powered on, as to be able to deliver system wakeup signals. In general the driver deals with this, via raising an "enable count" of the consumed resource or via a subsystem specific API, like irq_set_irq_wake() or enable|disable_irq_wake() for an irqchip. However, this may not be sufficient in cases when the resource's device may be attached to a PM domain (genpd for example) or is handled by a non-trivial middle layer (PCI for example). To address cases like these, the existing ->dev.power.wakeup_path status flag is there to help. As a matter of fact, genpd already monitors the flag during system suspend and acts accordingly. However, so far it has not been clear, if anybody else but the PM core is allowed to set the ->dev.power.wakeup_path status flag, which is required to make this work. For this reason, introduce a new helper function, device_set_wakeup_path() for that. Typically, a driver that manages a resource needed in the wakeup path should call device_set_wakeup_path() from its ->suspend() or ->suspend_late() callback. Signed-off-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- include/linux/pm_wakeup.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index 4c2cba7ec1d4..4238dde0aaf0 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h @@ -88,6 +88,11 @@ static inline bool device_may_wakeup(struct device *dev) return dev->power.can_wakeup && !!dev->power.wakeup; } +static inline void device_set_wakeup_path(struct device *dev) +{ + dev->power.wakeup_path = true; +} + /* drivers/base/power/wakeup.c */ extern void wakeup_source_prepare(struct wakeup_source *ws, const char *name); extern struct wakeup_source *wakeup_source_create(const char *name); @@ -174,6 +179,8 @@ static inline bool device_may_wakeup(struct device *dev) return dev->power.can_wakeup && dev->power.should_wakeup; } +static inline void device_set_wakeup_path(struct device *dev) {} + static inline void __pm_stay_awake(struct wakeup_source *ws) {} static inline void pm_stay_awake(struct device *dev) {} -- cgit v1.2.3 From 4bf236a3330e97d275e5848420f7e31948fef07a Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 5 Jan 2018 09:19:08 -0800 Subject: PM / sleep: Make lock/unlock_system_sleep() available to kernel modules Since pm_mutex is not exported using lock/unlock_system_sleep() from inside a kernel module causes a "pm_mutex undefined" linker error. Hence move lock/unlock_system_sleep() into kernel/power/main.c and export these. Signed-off-by: Bart Van Assche Signed-off-by: Rafael J. Wysocki --- include/linux/suspend.h | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/include/linux/suspend.h b/include/linux/suspend.h index d60b0f5c38d5..cc22a24516d6 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -443,32 +443,8 @@ extern bool pm_save_wakeup_count(unsigned int count); extern void pm_wakep_autosleep_enabled(bool set); extern void pm_print_active_wakeup_sources(void); -static inline void lock_system_sleep(void) -{ - current->flags |= PF_FREEZER_SKIP; - mutex_lock(&pm_mutex); -} - -static inline void unlock_system_sleep(void) -{ - /* - * Don't use freezer_count() because we don't want the call to - * try_to_freeze() here. - * - * Reason: - * Fundamentally, we just don't need it, because freezing condition - * doesn't come into effect until we release the pm_mutex lock, - * since the freezer always works with pm_mutex held. - * - * More importantly, in the case of hibernation, - * unlock_system_sleep() gets called in snapshot_read() and - * snapshot_write() when the freezing condition is still in effect. - * Which means, if we use try_to_freeze() here, it would make them - * enter the refrigerator, thus causing hibernation to lockup. - */ - current->flags &= ~PF_FREEZER_SKIP; - mutex_unlock(&pm_mutex); -} +extern void lock_system_sleep(void); +extern void unlock_system_sleep(void); #else /* !CONFIG_PM_SLEEP */ -- cgit v1.2.3