mirror of
https://github.com/LineageOS/android_kernel_samsung_msm8226.git
synced 2026-09-28 00:00:22 +02:00
thermal: Fix sensor thresholds not accounted correctly
Sensor threshold min and max are calculated to be binding around the current temp, but they fail if there no thresholds available with the min < curr_temp and the max > curr_temp. Fix negative temperatures handling. Change-Id: Ie4fb5ca2cdaf430b98c3665773a8d55ac9db5359 Signed-off-by: Praveen Chidambaram <pchidamb@codeaurora.org>
This commit is contained in:
committed by
Gerrit - the friendly Code Review server
parent
b4c69a8958
commit
3af26db07f
@@ -89,14 +89,30 @@ int sensor_get_id(char *name)
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_get_id);
|
||||
|
||||
static long get_min(struct sensor_info *sensor, long temp)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int min = INT_MIN;
|
||||
int max = INT_MAX;
|
||||
long min = LONG_MIN;
|
||||
long max = LONG_MAX;
|
||||
long max_of_min = LONG_MIN;
|
||||
long min_of_max = LONG_MAX;
|
||||
struct sensor_threshold *pos, *var;
|
||||
enum thermal_trip_type type;
|
||||
int i;
|
||||
unsigned long curr_temp;
|
||||
long curr_temp;
|
||||
|
||||
for (i = 0; ((sensor->max_idx == -1) || (sensor->min_idx == -1)) &&
|
||||
(sensor->tz->ops->get_trip_type) && (i < sensor->tz->trips);
|
||||
@@ -106,36 +122,58 @@ static void __update_sensor_thresholds(struct sensor_info *sensor)
|
||||
sensor->max_idx = i;
|
||||
if (type == THERMAL_TRIP_CONFIGURABLE_LOW)
|
||||
sensor->min_idx = i;
|
||||
sensor->tz->ops->get_trip_temp(sensor->tz,
|
||||
THERMAL_TRIP_CONFIGURABLE_LOW, &sensor->threshold_min);
|
||||
sensor->tz->ops->get_trip_temp(sensor->tz,
|
||||
THERMAL_TRIP_CONFIGURABLE_HI, &sensor->threshold_max);
|
||||
}
|
||||
|
||||
get_cpu();
|
||||
sensor->tz->ops->get_temp(sensor->tz, &curr_temp);
|
||||
list_for_each_entry_safe(pos, var, &sensor->threshold_list, list) {
|
||||
if ((pos->trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
|
||||
(pos->temp < (int)curr_temp))
|
||||
if (pos->temp > min)
|
||||
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->trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
|
||||
(pos->temp > (int)curr_temp))
|
||||
if (pos->temp < max)
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
pr_debug("sensor %d: min of max: %ld max of min: %ld\n",
|
||||
sensor->sensor_id, max_of_min, min_of_max);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
put_cpu();
|
||||
|
||||
if (sensor->tz->ops->set_trip_temp) {
|
||||
if (max != INT_MAX) {
|
||||
if (max != sensor->threshold_max) {
|
||||
sensor->tz->ops->set_trip_temp(sensor->tz,
|
||||
sensor->max_idx, max);
|
||||
sensor->threshold_max = max;
|
||||
}
|
||||
if (min != INT_MIN) {
|
||||
if (min != sensor->threshold_min) {
|
||||
sensor->tz->ops->set_trip_temp(sensor->tz,
|
||||
sensor->min_idx, min);
|
||||
sensor->threshold_min = min;
|
||||
}
|
||||
}
|
||||
|
||||
pr_debug("sensor %d, min: %d, max %d\n", sensor->sensor_id, min, max);
|
||||
pr_debug("sensor %d: curr_temp: %ld min: %ld max: %ld\n",
|
||||
sensor->sensor_id, curr_temp,
|
||||
sensor->threshold_min, sensor->threshold_max);
|
||||
}
|
||||
|
||||
static void sensor_update_work(struct work_struct *work)
|
||||
@@ -151,7 +189,7 @@ static void sensor_update_work(struct work_struct *work)
|
||||
* Do NOT call sensor_set_trip from this function
|
||||
*/
|
||||
int thermal_sensor_trip(struct thermal_zone_device *tz,
|
||||
enum thermal_trip_type trip, unsigned long temp)
|
||||
enum thermal_trip_type trip, long temp)
|
||||
{
|
||||
struct sensor_threshold *pos, *var;
|
||||
int ret = -ENODEV;
|
||||
@@ -168,10 +206,10 @@ int thermal_sensor_trip(struct thermal_zone_device *tz,
|
||||
continue;
|
||||
if (((trip == THERMAL_TRIP_CONFIGURABLE_LOW) &&
|
||||
(pos->temp <= tz->sensor.threshold_min) &&
|
||||
(pos->temp >= (int) temp)) ||
|
||||
(pos->temp >= temp)) ||
|
||||
((trip == THERMAL_TRIP_CONFIGURABLE_HI) &&
|
||||
(pos->temp >= tz->sensor.threshold_max) &&
|
||||
(pos->temp <= (int)temp))) {
|
||||
(pos->temp <= temp))) {
|
||||
pos->notify(trip, temp, pos->data);
|
||||
}
|
||||
}
|
||||
@@ -235,29 +273,6 @@ int sensor_cancel_trip(uint32_t sensor_id, struct sensor_threshold *threshold)
|
||||
}
|
||||
EXPORT_SYMBOL(sensor_cancel_trip);
|
||||
|
||||
static int sensor_get_trip_temp(struct thermal_zone_device *tz,
|
||||
int type, unsigned long *temp)
|
||||
{
|
||||
struct sensor_info *sensor = get_sensor(tz->id);
|
||||
|
||||
if (!sensor)
|
||||
return -EFAULT;
|
||||
|
||||
switch (type) {
|
||||
case THERMAL_TRIP_CONFIGURABLE_HI:
|
||||
*temp = tz->sensor.threshold_max;
|
||||
break;
|
||||
case THERMAL_TRIP_CONFIGURABLE_LOW:
|
||||
*temp = tz->sensor.threshold_min;
|
||||
break;
|
||||
default:
|
||||
tz->ops->get_trip_temp(tz, type, temp);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tz_notify_trip(enum thermal_trip_type type, int temp, void *data)
|
||||
{
|
||||
struct thermal_zone_device *tz = (struct thermal_zone_device *)data;
|
||||
@@ -310,7 +325,7 @@ int sensor_init(struct thermal_zone_device *tz)
|
||||
sensor->sensor_id = tz->id;
|
||||
sensor->tz = tz;
|
||||
sensor->threshold_min = 0;
|
||||
sensor->threshold_max = INT_MAX;
|
||||
sensor->threshold_max = LONG_MAX;
|
||||
sensor->max_idx = -1;
|
||||
sensor->min_idx = -1;
|
||||
mutex_init(&sensor->lock);
|
||||
@@ -511,7 +526,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
|
||||
if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip))
|
||||
return -EINVAL;
|
||||
|
||||
ret = sensor_get_trip_temp(tz, trip, &temperature);
|
||||
ret = tz->ops->get_trip_temp(tz, trip, &temperature);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -98,7 +98,7 @@ struct thermal_cooling_device {
|
||||
#define CELSIUS_TO_KELVIN(t) ((t)*10+2732)
|
||||
|
||||
struct sensor_threshold {
|
||||
int temp;
|
||||
long temp;
|
||||
enum thermal_trip_type trip;
|
||||
int (*notify)(enum thermal_trip_type type, int temp, void *data);
|
||||
void *data;
|
||||
@@ -108,8 +108,8 @@ struct sensor_threshold {
|
||||
struct sensor_info {
|
||||
uint32_t sensor_id;
|
||||
struct thermal_zone_device *tz;
|
||||
int threshold_min;
|
||||
int threshold_max;
|
||||
long threshold_min;
|
||||
long threshold_max;
|
||||
int max_idx;
|
||||
int min_idx;
|
||||
struct list_head sensor_list;
|
||||
@@ -190,7 +190,7 @@ 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 thermal_sensor_trip(struct thermal_zone_device *tz,
|
||||
enum thermal_trip_type trip, unsigned long temp);
|
||||
enum thermal_trip_type trip, long temp);
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
extern int thermal_generate_netlink_event(u32 orig, enum events event);
|
||||
|
||||
Reference in New Issue
Block a user