OSDN Git Service

thermal-core: Add separate threads for sysfs notify
authorShiju Mathew <shijum@codeaurora.org>
Tue, 30 Dec 2014 19:59:23 +0000 (14:59 -0500)
committerDavid Keitel <dkeitel@codeaurora.org>
Tue, 22 Mar 2016 18:08:26 +0000 (11:08 -0700)
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>
drivers/thermal/thermal_core.c
include/linux/thermal.h

index 61c87f6..e66db0e 100644 (file)
@@ -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);
index af10c70..34016d9 100644 (file)
@@ -173,6 +173,8 @@ struct sensor_info {
        struct list_head threshold_list;
        struct mutex lock;
        struct work_struct work;
+       struct task_struct *sysfs_notify_thread;
+       struct completion sysfs_notify_complete;
 };
 
 /**