diff options
| -rw-r--r-- | drivers/base/power/main.c | 5 | ||||
| -rw-r--r-- | drivers/thermal/thermal_core.c | 60 | ||||
| -rw-r--r-- | include/linux/thermal.h | 6 |
3 files changed, 29 insertions, 42 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 189de5250f25..e1b550664bab 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -33,6 +33,7 @@ #include <trace/events/power.h> #include <linux/cpufreq.h> #include <linux/devfreq.h> +#include <linux/thermal.h> #include <linux/timer.h> #include <linux/nmi.h> @@ -1282,6 +1283,8 @@ void dpm_complete(pm_message_t state) list_splice(&list, &dpm_list); mutex_unlock(&dpm_list_mtx); + /* Start resuming thermal control */ + thermal_pm_complete(); /* Allow device probing and trigger re-probing of deferred devices */ device_unblock_probing(); trace_suspend_resume(TPS("dpm_complete"), state.event, false); @@ -2225,6 +2228,8 @@ int dpm_prepare(pm_message_t state) * instead. The normal behavior will be restored in dpm_complete(). */ device_block_probing(); + /* Suspend thermal control. */ + thermal_pm_prepare(); mutex_lock(&dpm_list_mtx); while (!list_empty(&dpm_list) && !error) { diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f0f3a628c00c..2f4e2dc46b8f 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1823,7 +1823,7 @@ static void thermal_zone_pm_prepare(struct thermal_zone_device *tz) cancel_delayed_work(&tz->poll_queue); } -static void thermal_pm_notify_prepare(void) +static void __thermal_pm_prepare(void) { struct thermal_zone_device *tz; @@ -1835,6 +1835,19 @@ static void thermal_pm_notify_prepare(void) thermal_zone_pm_prepare(tz); } +void thermal_pm_prepare(void) +{ + if (thermal_class_unavailable) + return; + + __thermal_pm_prepare(); + /* + * Allow any leftover thermal work items already on the worqueue to + * complete so they don't get in the way later. + */ + flush_workqueue(thermal_wq); +} + static void thermal_zone_pm_complete(struct thermal_zone_device *tz) { guard(thermal_zone)(tz); @@ -1851,10 +1864,13 @@ static void thermal_zone_pm_complete(struct thermal_zone_device *tz) mod_delayed_work(thermal_wq, &tz->poll_queue, 0); } -static void thermal_pm_notify_complete(void) +void thermal_pm_complete(void) { struct thermal_zone_device *tz; + if (thermal_class_unavailable) + return; + guard(mutex)(&thermal_list_lock); thermal_pm_suspended = false; @@ -1863,41 +1879,6 @@ static void thermal_pm_notify_complete(void) thermal_zone_pm_complete(tz); } -static int thermal_pm_notify(struct notifier_block *nb, - unsigned long mode, void *_unused) -{ - switch (mode) { - case PM_HIBERNATION_PREPARE: - case PM_RESTORE_PREPARE: - case PM_SUSPEND_PREPARE: - thermal_pm_notify_prepare(); - /* - * Allow any leftover thermal work items already on the - * worqueue to complete so they don't get in the way later. - */ - flush_workqueue(thermal_wq); - break; - case PM_POST_HIBERNATION: - case PM_POST_RESTORE: - case PM_POST_SUSPEND: - thermal_pm_notify_complete(); - break; - default: - break; - } - return 0; -} - -static struct notifier_block thermal_pm_nb = { - .notifier_call = thermal_pm_notify, - /* - * Run at the lowest priority to avoid interference between the thermal - * zone resume work items spawned by thermal_pm_notify() and the other - * PM notifiers. - */ - .priority = INT_MIN, -}; - static int __init thermal_init(void) { int result; @@ -1924,11 +1905,6 @@ static int __init thermal_init(void) thermal_class_unavailable = false; - result = register_pm_notifier(&thermal_pm_nb); - if (result) - pr_warn("Thermal: Can not register suspend notifier, return %d\n", - result); - return 0; unregister_governors: diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 0b5ed6821080..0ddc77aeeca2 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -273,6 +273,9 @@ bool thermal_trip_is_bound_to_cdev(struct thermal_zone_device *tz, int thermal_zone_device_enable(struct thermal_zone_device *tz); int thermal_zone_device_disable(struct thermal_zone_device *tz); void thermal_zone_device_critical(struct thermal_zone_device *tz); + +void thermal_pm_prepare(void); +void thermal_pm_complete(void); #else static inline struct thermal_zone_device *thermal_zone_device_register_with_trips( const char *type, @@ -350,6 +353,9 @@ static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) static inline int thermal_zone_device_disable(struct thermal_zone_device *tz) { return -ENODEV; } + +static inline void thermal_pm_prepare(void) {} +static inline void thermal_pm_complete(void) {} #endif /* CONFIG_THERMAL */ #endif /* __THERMAL_H__ */ |
