summaryrefslogtreecommitdiff
path: root/drivers/thermal
diff options
context:
space:
mode:
authorShiju Mathew <shijum@codeaurora.org>2014-12-30 14:59:23 -0500
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:08:26 -0700
commit14b0886b043fab90050f26bee9ea0ead073f1f2b (patch)
treef12661ca53feb6b0d253569515480cbb7202f6aa /drivers/thermal
parent6a0a9b4bbfa90444635dd7fc6cab19fa96b9155b (diff)
thermal-core: Add separate threads for sysfs notify
Add separate threads for sysfs notify. This is required so that any thermal trip is not blocked while handling sysfs notify. Change-Id: Ifee206c29fd1b3c226a342b7f048250d5062397e Signed-off-by: Shiju Mathew <shijum@codeaurora.org> [imaund@codeaurora.org: Resolved context conflicts and updated a call of INIT_COMPLETION to reinit_completion] Signed-off-by: Ian Maund <imaund@codeaurora.org>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/thermal_core.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 61c87f65bc65..e66db0e030ea 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -36,6 +36,7 @@
#include <linux/reboot.h>
#include <linux/string.h>
#include <linux/of.h>
+#include <linux/kthread.h>
#include <net/netlink.h>
#include <net/genetlink.h>
@@ -366,6 +367,22 @@ static void sensor_update_work(struct work_struct *work)
mutex_unlock(&sensor->lock);
}
+static __ref int sensor_sysfs_notify(void *data)
+{
+ int ret = 0;
+ struct sensor_info *sensor = (struct sensor_info *)data;
+
+ while (!kthread_should_stop()) {
+ while (wait_for_completion_interruptible(
+ &sensor->sysfs_notify_complete) != 0)
+ ;
+ reinit_completion(&sensor->sysfs_notify_complete);
+ sysfs_notify(&sensor->tz->device.kobj, NULL,
+ THERMAL_UEVENT_DATA);
+ }
+ return ret;
+}
+
/* Should not be called in an interrupt context.
* Do NOT call sensor_set_trip from this function
*/
@@ -395,8 +412,7 @@ int thermal_sensor_trip(struct thermal_zone_device *tz,
(pos->temp <= temp))) {
if ((pos == &tz->tz_threshold[0])
|| (pos == &tz->tz_threshold[1]))
- sysfs_notify(&tz->device.kobj, NULL,
- THERMAL_UEVENT_DATA);
+ complete(&tz->sensor.sysfs_notify_complete);
pos->active = 0;
pos->notify(trip, temp, pos->data);
}
@@ -570,6 +586,14 @@ int sensor_init(struct thermal_zone_device *tz)
tz->tz_threshold[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
list_add(&sensor->sensor_list, &sensor_info_list);
INIT_WORK(&sensor->work, sensor_update_work);
+ init_completion(&sensor->sysfs_notify_complete);
+ sensor->sysfs_notify_thread = kthread_run(sensor_sysfs_notify,
+ &tz->sensor,
+ "therm_core:notify%d",
+ tz->id);
+ if (IS_ERR(sensor->sysfs_notify_thread))
+ pr_err("Failed to create notify thread %d", tz->id);
+
return 0;
}
@@ -2404,6 +2428,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
thermal_remove_hwmon_sysfs(tz);
flush_work(&tz->sensor.work);
+ kthread_stop(tz->sensor.sysfs_notify_thread);
mutex_lock(&thermal_list_lock);
list_del(&tz->sensor.sensor_list);
mutex_unlock(&thermal_list_lock);