Skip to content

Commit ff140fe

Browse files
committed
Thermal: handle thermal zone device properly during system sleep
Current thermal code does not handle system sleep well because 1. the cooling device cooling state may be changed during suspend 2. the previous temperature reading becomes invalid after resumed because it is got before system sleep 3. updating thermal zone device during suspending/resuming is wrong because some devices may have already been suspended or may have not been resumed. Thus, the proper way to do this is to cancel all thermal zone device update requirements during suspend/resume, and after all the devices have been resumed, reset and update every registered thermal zone devices. This also fixes a regression introduced by: Commit 19593a1 ("ACPI / fan: convert to platform driver") Because, with above commit applied, all the fan devices are attached to the acpi_general_pm_domain, and they are turned on by the pm_domain automatically after resume, without the awareness of thermal core. CC: <[email protected]> #3.18+ Reference: https://bugzilla.kernel.org/show_bug.cgi?id=78201 Reference: https://bugzilla.kernel.org/show_bug.cgi?id=91411 Tested-by: Manuel Krause <[email protected]> Tested-by: szegad <[email protected]> Tested-by: prash <[email protected]> Tested-by: amish <[email protected]> Tested-by: Matthias <[email protected]> Reviewed-by: Javi Merino <[email protected]> Signed-off-by: Zhang Rui <[email protected]> Signed-off-by: Chen Yu <[email protected]>
1 parent bb431ba commit ff140fe

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

drivers/thermal/thermal_core.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <linux/of.h>
3838
#include <net/netlink.h>
3939
#include <net/genetlink.h>
40+
#include <linux/suspend.h>
4041

4142
#define CREATE_TRACE_POINTS
4243
#include <trace/events/thermal.h>
@@ -59,6 +60,8 @@ static LIST_HEAD(thermal_governor_list);
5960
static DEFINE_MUTEX(thermal_list_lock);
6061
static DEFINE_MUTEX(thermal_governor_lock);
6162

63+
static atomic_t in_suspend;
64+
6265
static struct thermal_governor *def_governor;
6366

6467
static struct thermal_governor *__find_governor(const char *name)
@@ -554,6 +557,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
554557
{
555558
int count;
556559

560+
if (atomic_read(&in_suspend))
561+
return;
562+
557563
if (!tz->ops->get_temp)
558564
return;
559565

@@ -2155,6 +2161,36 @@ static void thermal_unregister_governors(void)
21552161
thermal_gov_power_allocator_unregister();
21562162
}
21572163

2164+
static int thermal_pm_notify(struct notifier_block *nb,
2165+
unsigned long mode, void *_unused)
2166+
{
2167+
struct thermal_zone_device *tz;
2168+
2169+
switch (mode) {
2170+
case PM_HIBERNATION_PREPARE:
2171+
case PM_RESTORE_PREPARE:
2172+
case PM_SUSPEND_PREPARE:
2173+
atomic_set(&in_suspend, 1);
2174+
break;
2175+
case PM_POST_HIBERNATION:
2176+
case PM_POST_RESTORE:
2177+
case PM_POST_SUSPEND:
2178+
atomic_set(&in_suspend, 0);
2179+
list_for_each_entry(tz, &thermal_tz_list, node) {
2180+
thermal_zone_device_reset(tz);
2181+
thermal_zone_device_update(tz);
2182+
}
2183+
break;
2184+
default:
2185+
break;
2186+
}
2187+
return 0;
2188+
}
2189+
2190+
static struct notifier_block thermal_pm_nb = {
2191+
.notifier_call = thermal_pm_notify,
2192+
};
2193+
21582194
static int __init thermal_init(void)
21592195
{
21602196
int result;
@@ -2175,6 +2211,11 @@ static int __init thermal_init(void)
21752211
if (result)
21762212
goto exit_netlink;
21772213

2214+
result = register_pm_notifier(&thermal_pm_nb);
2215+
if (result)
2216+
pr_warn("Thermal: Can not register suspend notifier, return %d\n",
2217+
result);
2218+
21782219
return 0;
21792220

21802221
exit_netlink:
@@ -2194,6 +2235,7 @@ static int __init thermal_init(void)
21942235

21952236
static void __exit thermal_exit(void)
21962237
{
2238+
unregister_pm_notifier(&thermal_pm_nb);
21972239
of_thermal_destroy_zones();
21982240
genetlink_exit();
21992241
class_unregister(&thermal_class);

0 commit comments

Comments
 (0)