summaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/thermal_sys.c102
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)