diff options
| author | Ram Chandrasekar <rkumbako@codeaurora.org> | 2017-02-10 14:58:30 -0700 |
|---|---|---|
| committer | Ram Chandrasekar <rkumbako@codeaurora.org> | 2017-02-15 12:05:11 -0700 |
| commit | 4a86c2f3ccbb861cc50778cc4b67af153e99bf24 (patch) | |
| tree | 5a10e761dd5afdc275cd7d54ae30c5d6f1e83def | |
| parent | 487ff740cb8a0111016b0da2616aa8104cb0d440 (diff) | |
drivers: thermal: Exit sysfs notify kthread when sensor unregisters
When a thermal zone unregisters, it initiates a blocking call
kthread_stop for the sysfs notify kthread to exit. But the sysfs notify
kthread is blocked on a completion event, which may not be triggered after
the sensor driver initiates a thermal zone unregister call. So, the
kthread_stop will be blocked forever.
As a part of thermal zone unregister, set a thermal zone unregister flag
and send a completion event before calling kthread_stop. Make the sysfs
notify kthread to be aware of thermal zone unregister flag and exit
after the completion event is triggered.
Change-Id: Icf045e0ad6e28135cd3a54c15d9923f095a286ff
Signed-off-by: Ram Chandrasekar <rkumbako@codeaurora.org>
| -rw-r--r-- | drivers/thermal/thermal_core.c | 13 | ||||
| -rw-r--r-- | include/linux/thermal.h | 1 |
2 files changed, 10 insertions, 4 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 2b49608756a0..04cf31c119ef 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -4,7 +4,7 @@ * Copyright (C) 2008 Intel Corp * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com> * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com> - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -382,9 +382,11 @@ static __ref int sensor_sysfs_notify(void *data) struct sensor_info *sensor = (struct sensor_info *)data; while (!kthread_should_stop()) { - while (wait_for_completion_interruptible( - &sensor->sysfs_notify_complete) != 0) - ; + if (wait_for_completion_interruptible( + &sensor->sysfs_notify_complete) != 0) + continue; + if (sensor->deregister_active) + return ret; reinit_completion(&sensor->sysfs_notify_complete); sysfs_notify(&sensor->tz->device.kobj, NULL, THERMAL_UEVENT_DATA); @@ -580,6 +582,7 @@ int sensor_init(struct thermal_zone_device *tz) sensor->threshold_max = INT_MAX; sensor->max_idx = -1; sensor->min_idx = -1; + sensor->deregister_active = false; mutex_init(&sensor->lock); INIT_LIST_HEAD_RCU(&sensor->sensor_list); INIT_LIST_HEAD_RCU(&sensor->threshold_list); @@ -2471,6 +2474,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) thermal_remove_hwmon_sysfs(tz); flush_work(&tz->sensor.work); + tz->sensor.deregister_active = true; + complete(&tz->sensor.sysfs_notify_complete); kthread_stop(tz->sensor.sysfs_notify_thread); mutex_lock(&thermal_list_lock); list_del_rcu(&tz->sensor.sensor_list); diff --git a/include/linux/thermal.h b/include/linux/thermal.h index b90f8f5c663d..4d2cf47aba27 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -178,6 +178,7 @@ struct sensor_info { struct work_struct work; struct task_struct *sysfs_notify_thread; struct completion sysfs_notify_complete; + bool deregister_active; }; /** |
