diff options
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/thermal_core.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 94e5e353b40e..3ffccd73b19e 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1532,6 +1532,22 @@ exit: } EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name); +static void thermal_zone_device_resume(struct work_struct *work) +{ + struct thermal_zone_device *tz; + + tz = container_of(work, struct thermal_zone_device, poll_queue.work); + + mutex_lock(&tz->lock); + + tz->suspended = false; + + thermal_zone_device_init(tz); + __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + + mutex_unlock(&tz->lock); +} + static int thermal_pm_notify(struct notifier_block *nb, unsigned long mode, void *_unused) { @@ -1563,10 +1579,16 @@ static int thermal_pm_notify(struct notifier_block *nb, cancel_delayed_work(&tz->poll_queue); - tz->suspended = false; - - thermal_zone_device_init(tz); - __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + /* + * Replace the work function with the resume one, which + * will restore the original work function and schedule + * the polling work if needed. + */ + INIT_DELAYED_WORK(&tz->poll_queue, + thermal_zone_device_resume); + /* Queue up the work without a delay. */ + mod_delayed_work(system_freezable_power_efficient_wq, + &tz->poll_queue, 0); mutex_unlock(&tz->lock); } |