Skip to content

Commit cdf771a

Browse files
committed
thermal: core: Fix race between zone registration and system suspend
If the registration of a thermal zone takes place at the time when system suspend is started, thermal_pm_notify() can run before the new thermal zone is added to thermal_tz_list and its "suspended" flag will not be set. Consequently, if __thermal_zone_device_update() is called for that thermal zone, it will not return early as expected which may cause some destructive interference with the system suspend or resume flow to occur. To avoid that, make thermal_zone_init_complete() introduced previously set the "suspended" flag for new thermal zones if it runs during system suspend or resume. Fixes: 4e81417 ("thermal: core: Fix thermal zone suspend-resume synchronization") Signed-off-by: Rafael J. Wysocki <[email protected]> Link: https://patch.msgid.link/[email protected] Reviewed-by: Lukasz Luba <[email protected]>
1 parent 7837fa8 commit cdf771a

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

drivers/thermal/thermal_core.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ static DEFINE_MUTEX(thermal_governor_lock);
4040

4141
static struct thermal_governor *def_governor;
4242

43+
static bool thermal_pm_suspended;
44+
4345
/*
4446
* Governor section: set of functions to handle thermal governors
4547
*
@@ -1339,6 +1341,14 @@ static void thermal_zone_init_complete(struct thermal_zone_device *tz)
13391341
mutex_lock(&tz->lock);
13401342

13411343
tz->state &= ~TZ_STATE_FLAG_INIT;
1344+
/*
1345+
* If system suspend or resume is in progress at this point, the
1346+
* new thermal zone needs to be marked as suspended because
1347+
* thermal_pm_notify() has run already.
1348+
*/
1349+
if (thermal_pm_suspended)
1350+
tz->state |= TZ_STATE_FLAG_SUSPENDED;
1351+
13421352
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
13431353

13441354
mutex_unlock(&tz->lock);
@@ -1520,10 +1530,10 @@ thermal_zone_device_register_with_trips(const char *type,
15201530
list_for_each_entry(cdev, &thermal_cdev_list, node)
15211531
thermal_zone_cdev_bind(tz, cdev);
15221532

1523-
mutex_unlock(&thermal_list_lock);
1524-
15251533
thermal_zone_init_complete(tz);
15261534

1535+
mutex_unlock(&thermal_list_lock);
1536+
15271537
thermal_notify_tz_create(tz);
15281538

15291539
thermal_debug_tz_add(tz);
@@ -1746,6 +1756,8 @@ static int thermal_pm_notify(struct notifier_block *nb,
17461756
case PM_SUSPEND_PREPARE:
17471757
mutex_lock(&thermal_list_lock);
17481758

1759+
thermal_pm_suspended = true;
1760+
17491761
list_for_each_entry(tz, &thermal_tz_list, node)
17501762
thermal_zone_pm_prepare(tz);
17511763

@@ -1756,6 +1768,8 @@ static int thermal_pm_notify(struct notifier_block *nb,
17561768
case PM_POST_SUSPEND:
17571769
mutex_lock(&thermal_list_lock);
17581770

1771+
thermal_pm_suspended = false;
1772+
17591773
list_for_each_entry(tz, &thermal_tz_list, node)
17601774
thermal_zone_pm_complete(tz);
17611775

0 commit comments

Comments
 (0)