Skip to content

Commit 5a5efda

Browse files
committed
thermal: core: Resume thermal zones asynchronously
The resume of thermal zones in thermal_pm_notify() is carried out sequentially, which may be a problem if __thermal_zone_device_update() takes a significant time to run for some thermal zones, because some other thermal zones may need to wait for them to resume then and if any other PM notifiers are going to be invoked after the thermal one, they will need to wait for it either. To address this, make thermal_pm_notify() switch the poll_queue delayed work over to a one-shot thermal_zone_device_resume() work function that will restore the original one during the thermal zone resume and queue up poll_queue without a delay for each thermal zone. Link: https://lore.kernel.org/linux-pm/[email protected]/ Reported-by: Radu Solea <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 33fcb59 commit 5a5efda

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

drivers/thermal/thermal_core.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,22 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
15321532
}
15331533
EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
15341534

1535+
static void thermal_zone_device_resume(struct work_struct *work)
1536+
{
1537+
struct thermal_zone_device *tz;
1538+
1539+
tz = container_of(work, struct thermal_zone_device, poll_queue.work);
1540+
1541+
mutex_lock(&tz->lock);
1542+
1543+
tz->suspended = false;
1544+
1545+
thermal_zone_device_init(tz);
1546+
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
1547+
1548+
mutex_unlock(&tz->lock);
1549+
}
1550+
15351551
static int thermal_pm_notify(struct notifier_block *nb,
15361552
unsigned long mode, void *_unused)
15371553
{
@@ -1563,10 +1579,16 @@ static int thermal_pm_notify(struct notifier_block *nb,
15631579

15641580
cancel_delayed_work(&tz->poll_queue);
15651581

1566-
tz->suspended = false;
1567-
1568-
thermal_zone_device_init(tz);
1569-
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
1582+
/*
1583+
* Replace the work function with the resume one, which
1584+
* will restore the original work function and schedule
1585+
* the polling work if needed.
1586+
*/
1587+
INIT_DELAYED_WORK(&tz->poll_queue,
1588+
thermal_zone_device_resume);
1589+
/* Queue up the work without a delay. */
1590+
mod_delayed_work(system_freezable_power_efficient_wq,
1591+
&tz->poll_queue, 0);
15701592

15711593
mutex_unlock(&tz->lock);
15721594
}

0 commit comments

Comments
 (0)