diff options
Diffstat (limited to 'drivers/thermal/thermal_sys.c')
-rw-r--r-- | drivers/thermal/thermal_sys.c | 102 |
1 files changed, 76 insertions, 26 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 0cf3dce5546..735e6e6daad 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -1076,6 +1076,81 @@ void thermal_cooling_device_unregister(struct } EXPORT_SYMBOL(thermal_cooling_device_unregister); +/* + * Cooling algorithm for active trip points + * + * 1. if the temperature is higher than a trip point, + * a. if the trend is THERMAL_TREND_RAISING, use higher cooling + * state for this trip point + * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling + * state for this trip point + * + * 2. if the temperature is lower than a trip point, use lower + * cooling state for this trip point + * + * Note that this behaves the same as the previous passive cooling + * algorithm. + */ + +static void thermal_zone_trip_update(struct thermal_zone_device *tz, + int trip, long temp) +{ + struct thermal_cooling_device_instance *instance; + struct thermal_cooling_device *cdev = NULL; + unsigned long cur_state, max_state; + long trip_temp; + enum thermal_trend trend; + + tz->ops->get_trip_temp(tz, trip, &trip_temp); + + if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { + /* + * compare the current temperature and previous temperature + * to get the thermal trend, if no special requirement + */ + if (tz->temperature > tz->last_temperature) + trend = THERMAL_TREND_RAISING; + else if (tz->temperature < tz->last_temperature) + trend = THERMAL_TREND_DROPPING; + else + trend = THERMAL_TREND_STABLE; + } + + if (temp >= trip_temp) { + list_for_each_entry(instance, &tz->cooling_devices, node) { + if (instance->trip != trip) + continue; + + cdev = instance->cdev; + + cdev->ops->get_cur_state(cdev, &cur_state); + cdev->ops->get_max_state(cdev, &max_state); + + if (trend == THERMAL_TREND_RAISING) { + cur_state = cur_state < instance->upper ? + (cur_state + 1) : instance->upper; + } else if (trend == THERMAL_TREND_DROPPING) { + cur_state = cur_state > instance->lower ? + (cur_state - 1) : instance->lower; + } + cdev->ops->set_cur_state(cdev, cur_state); + } + } else { /* below trip */ + list_for_each_entry(instance, &tz->cooling_devices, node) { + if (instance->trip != trip) + continue; + + cdev = instance->cdev; + cdev->ops->get_cur_state(cdev, &cur_state); + + cur_state = cur_state > instance->lower ? + (cur_state - 1) : instance->lower; + cdev->ops->set_cur_state(cdev, cur_state); + } + } + + return; +} /** * thermal_zone_device_update - force an update of a thermal zone's state * @ttz: the thermal zone to update @@ -1086,9 +1161,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) int count, ret = 0; long temp, trip_temp; enum thermal_trip_type trip_type; - struct thermal_cooling_device_instance *instance; - struct thermal_cooling_device *cdev; - unsigned long cur_state, max_state; mutex_lock(&tz->lock); @@ -1124,29 +1196,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) tz->ops->notify(tz, count, trip_type); break; case THERMAL_TRIP_ACTIVE: - list_for_each_entry(instance, &tz->cooling_devices, - node) { - if (instance->trip != count) - continue; - - cdev = instance->cdev; - - cdev->ops->get_cur_state(cdev, &cur_state); - cdev->ops->get_max_state(cdev, &max_state); - - if (temp >= trip_temp) - cur_state = - cur_state < instance->upper ? - (cur_state + 1) : - instance->upper; - else - cur_state = - cur_state > instance->lower ? - (cur_state - 1) : - instance->lower; - - cdev->ops->set_cur_state(cdev, cur_state); - } + thermal_zone_trip_update(tz, count, temp); break; case THERMAL_TRIP_PASSIVE: if (temp >= trip_temp || tz->passive) |