OSDN Git Service

thermal: Add Support for enabling and disabling tsens trip
authorRam Chandrasekar <rkumbako@codeaurora.org>
Wed, 2 Oct 2013 18:23:27 +0000 (12:23 -0600)
committerDavid Keitel <dkeitel@codeaurora.org>
Tue, 22 Mar 2016 18:08:20 +0000 (11:08 -0700)
Add new API to enable or disable the kernel client's trip
threshold request. The enable or disable trip threshold requests
from different kernel clients and userspace client will
activate/deactivate the corresponding clients threshold request.

Modify thermal sys framework to include only the active
thresholds from clients to determine the current trip
thresholds for tsens.

CRs-Fixed: 561775
Change-Id: I304ac00daa8a0a1a68b60153c29ee6cb5c3507b1
Signed-off-by: Ram Chandrasekar <rkumbako@codeaurora.org>
[joshc: drop msm_thermal chunk]
Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
drivers/thermal/thermal_core.c
include/linux/thermal.h

index 1bad1ed..7b7bd1c 100644 (file)
@@ -232,30 +232,21 @@ int sensor_get_id(char *name)
 }
 EXPORT_SYMBOL(sensor_get_id);
 
-static long get_min(struct sensor_info *sensor, long temp)
+static int __update_sensor_thresholds(struct sensor_info *sensor)
 {
-       long min = LONG_MIN;
-       struct sensor_threshold *pos, *var;
-
-       list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
-               if (pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW)
-                       if (pos->temp < temp && pos->temp > min)
-                               min = pos->temp;
-       }
-
-       return min;
-}
-
-static void __update_sensor_thresholds(struct sensor_info *sensor)
-{
-       long min = LONG_MIN;
-       long max = LONG_MAX;
-       long max_of_min = LONG_MIN;
-       long min_of_max = LONG_MAX;
+       long max_of_low_thresh = LONG_MIN;
+       long min_of_high_thresh = LONG_MAX;
        struct sensor_threshold *pos, *var;
        enum thermal_trip_type type;
-       int i;
-       long curr_temp;
+       int i, ret = 0;
+
+       if (!sensor->tz->ops->set_trip_temp ||
+               !sensor->tz->ops->activate_trip_type ||
+               !sensor->tz->ops->get_trip_type ||
+               !sensor->tz->ops->get_trip_temp) {
+               ret = -ENODEV;
+               goto update_done;
+       }
 
        for (i = 0; ((sensor->max_idx == -1) || (sensor->min_idx == -1)) &&
                (sensor->tz->ops->get_trip_type) && (i < sensor->tz->trips);
@@ -271,60 +262,85 @@ static void __update_sensor_thresholds(struct sensor_info *sensor)
                        THERMAL_TRIP_CONFIGURABLE_HI, &sensor->threshold_max);
        }
 
-       sensor->tz->ops->get_temp(sensor->tz, &curr_temp);
        list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
+               if (!pos->active)
+                       continue;
                if (pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW) {
-                       if (pos->temp > max_of_min)
-                               max_of_min = pos->temp;
-                       if (pos->temp < curr_temp && pos->temp > min)
-                               min = pos->temp;
+                       if (pos->temp > max_of_low_thresh)
+                               max_of_low_thresh = pos->temp;
                }
                if (pos->trip == THERMAL_TRIP_CONFIGURABLE_HI) {
-                       if (pos->temp < min_of_max)
-                               min_of_max = pos->temp;
-                       if (pos->temp > curr_temp && pos->temp < max)
-                               max = pos->temp;
+                       if (pos->temp < min_of_high_thresh)
+                               min_of_high_thresh = pos->temp;
                }
        }
 
-       pr_debug("sensor %d: min of max: %ld max of min: %ld\n",
-                       sensor->sensor_id, max_of_min, min_of_max);
+       pr_debug("sensor %d: Thresholds: max of low: %ld min of high: %ld\n",
+                       sensor->sensor_id, max_of_low_thresh,
+                       min_of_high_thresh);
 
-       /* If we haven't found a max and min bounding the curr_temp,
-        * use the min of max and max of min instead.
-        */
-       if (max == LONG_MAX)
-               max = min_of_max;
-       if (min == LONG_MIN) {
-               min = get_min(sensor, max);
-               if (min == LONG_MIN)
-                       min = max_of_min;
-       }
-
-       if (sensor->tz->ops->set_trip_temp) {
-               if (max != sensor->threshold_max) {
-                       sensor->tz->ops->set_trip_temp(sensor->tz,
-                               sensor->max_idx, max);
-                       sensor->threshold_max = max;
+       if ((min_of_high_thresh != sensor->threshold_max) &&
+               (min_of_high_thresh != LONG_MAX)) {
+               ret = sensor->tz->ops->set_trip_temp(sensor->tz,
+                       sensor->max_idx, min_of_high_thresh);
+               if (ret) {
+                       pr_err("sensor %d: Unable to set high threshold %d",
+                                       sensor->sensor_id, ret);
+                       goto update_done;
                }
-               if (min != sensor->threshold_min) {
-                       sensor->tz->ops->set_trip_temp(sensor->tz,
-                               sensor->min_idx, min);
-                       sensor->threshold_min = min;
+               sensor->threshold_max = min_of_high_thresh;
+       }
+       ret = sensor->tz->ops->activate_trip_type(sensor->tz,
+               sensor->max_idx,
+               (min_of_high_thresh == LONG_MAX) ?
+               THERMAL_TRIP_ACTIVATION_DISABLED :
+               THERMAL_TRIP_ACTIVATION_ENABLED);
+       if (ret) {
+               pr_err("sensor %d: Unable to activate high threshold %d",
+                       sensor->sensor_id, ret);
+               goto update_done;
+       }
+
+       if ((max_of_low_thresh != sensor->threshold_min) &&
+               (max_of_low_thresh != LONG_MIN)) {
+               ret = sensor->tz->ops->set_trip_temp(sensor->tz,
+                       sensor->min_idx, max_of_low_thresh);
+               if (ret) {
+                       pr_err("sensor %d: Unable to set low threshold %d",
+                               sensor->sensor_id, ret);
+                       goto update_done;
                }
+               sensor->threshold_min = max_of_low_thresh;
+       }
+       ret = sensor->tz->ops->activate_trip_type(sensor->tz,
+               sensor->min_idx,
+               (max_of_low_thresh == LONG_MIN) ?
+               THERMAL_TRIP_ACTIVATION_DISABLED :
+               THERMAL_TRIP_ACTIVATION_ENABLED);
+       if (ret) {
+               pr_err("sensor %d: Unable to activate low threshold %d",
+                       sensor->sensor_id, ret);
+               goto update_done;
        }
 
-       pr_debug("sensor %d: curr_temp: %ld min: %ld max: %ld\n",
-               sensor->sensor_id, curr_temp,
+       pr_debug("sensor %d: low: %ld high: %ld\n",
+               sensor->sensor_id,
                sensor->threshold_min, sensor->threshold_max);
+
+update_done:
+       return ret;
 }
 
 static void sensor_update_work(struct work_struct *work)
 {
        struct sensor_info *sensor = container_of(work, struct sensor_info,
                                                work);
+       int ret = 0;
        mutex_lock(&sensor->lock);
-       __update_sensor_thresholds(sensor);
+       ret = __update_sensor_thresholds(sensor);
+       if (ret)
+               pr_err("sensor %d: Error %d setting threshold\n",
+                       sensor->sensor_id, ret);
        mutex_unlock(&sensor->lock);
 }
 
@@ -345,7 +361,7 @@ int thermal_sensor_trip(struct thermal_zone_device *tz,
                return 0;
 
        list_for_each_entry_safe(pos, var, &tz->sensor.threshold_list, list) {
-               if (pos->trip != trip)
+               if ((pos->trip != trip) || (!pos->active))
                        continue;
                if (((trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
                        (pos->temp <= tz->sensor.threshold_min) &&
@@ -353,6 +369,7 @@ int thermal_sensor_trip(struct thermal_zone_device *tz,
                        ((trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
                                (pos->temp >= tz->sensor.threshold_max) &&
                                (pos->temp <= temp))) {
+                       pos->active = 0;
                        pos->notify(trip, temp, pos->data);
                }
        }
@@ -363,6 +380,29 @@ int thermal_sensor_trip(struct thermal_zone_device *tz,
 }
 EXPORT_SYMBOL(thermal_sensor_trip);
 
+int sensor_activate_trip(uint32_t sensor_id,
+       struct sensor_threshold *threshold, bool enable)
+{
+       struct sensor_info *sensor = get_sensor(sensor_id);
+       int ret = 0;
+
+       if (!sensor || !threshold) {
+               pr_err("%s: uninitialized data\n",
+                       KBUILD_MODNAME);
+               ret = -ENODEV;
+               goto activate_trip_exit;
+       }
+
+       mutex_lock(&sensor->lock);
+       threshold->active = (enable) ? 1 : 0;
+       ret = __update_sensor_thresholds(sensor);
+       mutex_unlock(&sensor->lock);
+
+activate_trip_exit:
+       return ret;
+}
+EXPORT_SYMBOL(sensor_activate_trip);
+
 int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
 {
        struct sensor_threshold *pos, *var;
@@ -384,8 +424,8 @@ int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
                INIT_LIST_HEAD(&threshold->list);
                list_add(&threshold->list, &sensor->threshold_list);
        }
+       threshold->active = 0; /* Do not allow active threshold right away */
 
-       __update_sensor_thresholds(sensor);
        mutex_unlock(&sensor->lock);
 
        return 0;
@@ -397,6 +437,7 @@ int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
 {
        struct sensor_threshold *pos, *var;
        struct sensor_info *sensor = get_sensor(sensor_id);
+       int ret = 0;
 
        if (!sensor)
                return -ENODEV;
@@ -404,15 +445,16 @@ int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
        mutex_lock(&sensor->lock);
        list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
                if (pos == threshold) {
+                       pos->active = 0;
                        list_del(&pos->list);
                        break;
                }
        }
 
-       __update_sensor_thresholds(sensor);
+       ret = __update_sensor_thresholds(sensor);
        mutex_unlock(&sensor->lock);
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(sensor_cancel_trip);
 
@@ -426,36 +468,36 @@ static int tz_notify_trip(enum thermal_trip_type type, int temp, void *data)
        return 0;
 }
 
+static void get_trip_threshold(struct thermal_zone_device *tz, int trip,
+       struct sensor_threshold **threshold)
+{
+       enum thermal_trip_type type;
+
+       tz->ops->get_trip_type(tz, trip, &type);
+
+       if (type == THERMAL_TRIP_CONFIGURABLE_HI)
+               *threshold = &tz->tz_threshold[0];
+       else if (type == THERMAL_TRIP_CONFIGURABLE_LOW)
+               *threshold = &tz->tz_threshold[1];
+       else
+               *threshold = NULL;
+}
+
 int sensor_set_trip_temp(struct thermal_zone_device *tz,
                int trip, long temp)
 {
        int ret = 0;
-       enum thermal_trip_type type;
+       struct sensor_threshold *threshold = NULL;
 
        if (!tz->ops->get_trip_type)
                return -EPERM;
 
-       tz->ops->get_trip_type(tz, trip, &type);
-       switch (type) {
-       case THERMAL_TRIP_CONFIGURABLE_HI:
-               tz->tz_threshold[0].temp = temp;
-               tz->tz_threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
-               tz->tz_threshold[0].notify = tz_notify_trip;
-               tz->tz_threshold[0].data = tz;
-               ret = sensor_set_trip(tz->sensor.sensor_id,
-                                       &tz->tz_threshold[0]);
-               break;
-       case THERMAL_TRIP_CONFIGURABLE_LOW:
-               tz->tz_threshold[1].temp = temp;
-               tz->tz_threshold[1].trip = THERMAL_TRIP_CONFIGURABLE_LOW;
-               tz->tz_threshold[1].notify = tz_notify_trip;
-               tz->tz_threshold[1].data = tz;
-               ret = sensor_set_trip(tz->sensor.sensor_id,
-                                       &tz->tz_threshold[1]);
-               break;
-       default:
+       get_trip_threshold(tz, trip, &threshold);
+       if (threshold) {
+               threshold->temp = temp;
+               ret = sensor_set_trip(tz->sensor.sensor_id, threshold);
+       } else {
                ret = tz->ops->set_trip_temp(tz, trip, temp);
-               break;
        }
 
        return ret;
@@ -476,10 +518,12 @@ int sensor_init(struct thermal_zone_device *tz)
        INIT_LIST_HEAD(&sensor->threshold_list);
        INIT_LIST_HEAD(&tz->tz_threshold[0].list);
        INIT_LIST_HEAD(&tz->tz_threshold[1].list);
-       tz->tz_threshold[0].notify = NULL;
-       tz->tz_threshold[0].data = NULL;
-       tz->tz_threshold[1].notify = NULL;
-       tz->tz_threshold[1].data = NULL;
+       tz->tz_threshold[0].notify = tz_notify_trip;
+       tz->tz_threshold[0].data = tz;
+       tz->tz_threshold[0].trip = THERMAL_TRIP_CONFIGURABLE_HI;
+       tz->tz_threshold[1].notify = tz_notify_trip;
+       tz->tz_threshold[1].data = 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);
 
@@ -961,23 +1005,40 @@ trip_point_type_activate(struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
 {
        struct thermal_zone_device *tz = to_thermal_zone(dev);
-       int trip, result;
+       int trip, result = 0;
+       bool activate;
+       struct sensor_threshold *threshold = NULL;
+
+       if (!tz->ops->get_trip_type ||
+               !tz->ops->activate_trip_type) {
+               result = -EPERM;
+               goto trip_activate_exit;
+       }
 
-       if (!tz->ops->activate_trip_type)
-               return -EPERM;
+       if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) {
+               result = -EINVAL;
+               goto trip_activate_exit;
+       }
 
-       if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip))
-               return -EINVAL;
+       if (!strcmp(buf, "enabled")) {
+               activate = true;
+       } else if (!strcmp(buf, "disabled")) {
+               activate = false;
+       } else {
+               result = -EINVAL;
+               goto trip_activate_exit;
+       }
 
-       if (!strncmp(buf, "enabled", sizeof("enabled")))
-               result = tz->ops->activate_trip_type(tz, trip,
-                                       THERMAL_TRIP_ACTIVATION_ENABLED);
-       else if (!strncmp(buf, "disabled", sizeof("disabled")))
-               result = tz->ops->activate_trip_type(tz, trip,
-                                       THERMAL_TRIP_ACTIVATION_DISABLED);
+       get_trip_threshold(tz, trip, &threshold);
+       if (threshold)
+               result = sensor_activate_trip(tz->sensor.sensor_id,
+                       threshold, activate);
        else
-               result = -EINVAL;
+               result = tz->ops->activate_trip_type(tz, trip,
+                       activate ? THERMAL_TRIP_ACTIVATION_ENABLED :
+                       THERMAL_TRIP_ACTIVATION_DISABLED);
 
+trip_activate_exit:
        if (result)
                return result;
 
index 2bab7a2..89de2ca 100644 (file)
@@ -158,6 +158,7 @@ struct sensor_threshold {
        enum thermal_trip_type trip;
        int (*notify)(enum thermal_trip_type type, int temp, void *data);
        void *data;
+       uint8_t active;
        struct list_head list;
 };
 
@@ -449,6 +450,8 @@ void thermal_notify_framework(struct thermal_zone_device *, int);
 int sensor_get_id(char *name);
 int sensor_set_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
 int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold);
+int sensor_activate_trip(uint32_t sensor_id, struct sensor_threshold *threshold,
+               bool enable);
 int thermal_sensor_trip(struct thermal_zone_device *tz,
                enum thermal_trip_type trip, long temp);