diff options
author | Zhang Rui <rui.zhang@intel.com> | 2015-10-30 04:31:47 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2015-12-29 02:59:44 -0500 |
commit | bb431ba26c5cd0a17c941ca6c3a195a3a6d5d461 (patch) | |
tree | 10368cd1731f1856bade627fa1f38acd9150d3a5 | |
parent | 74bf8efb5fa6e958d2d7c7917b8bb672085ec0c6 (diff) |
Thermal: initialize thermal zone device correctly
After thermal zone device registered, as we have not read any
temperature before, thus tz->temperature should not be 0,
which actually means 0C, and thermal trend is not available.
In this case, we need specially handling for the first
thermal_zone_device_update().
Both thermal core framework and step_wise governor is
enhanced to handle this. And since the step_wise governor
is the only one that uses trends, so it's the only thermal
governor that needs to be updated.
CC: <stable@vger.kernel.org> #3.18+
Tested-by: Manuel Krause <manuelkrause@netscape.net>
Tested-by: szegad <szegadlo@poczta.onet.pl>
Tested-by: prash <prash.n.rao@gmail.com>
Tested-by: amish <ammdispose-arch@yahoo.com>
Tested-by: Matthias <morpheusxyz123@yahoo.de>
Reviewed-by: Javi Merino <javi.merino@arm.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
-rw-r--r-- | drivers/thermal/step_wise.c | 17 | ||||
-rw-r--r-- | drivers/thermal/thermal_core.c | 19 | ||||
-rw-r--r-- | drivers/thermal/thermal_core.h | 1 | ||||
-rw-r--r-- | include/linux/thermal.h | 3 |
4 files changed, 36 insertions, 4 deletions
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c index 2f9f7086ac3d..ea9366ad3e6b 100644 --- a/drivers/thermal/step_wise.c +++ b/drivers/thermal/step_wise.c | |||
@@ -63,6 +63,19 @@ static unsigned long get_target_state(struct thermal_instance *instance, | |||
63 | next_target = instance->target; | 63 | next_target = instance->target; |
64 | dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state); | 64 | dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state); |
65 | 65 | ||
66 | if (!instance->initialized) { | ||
67 | if (throttle) { | ||
68 | next_target = (cur_state + 1) >= instance->upper ? | ||
69 | instance->upper : | ||
70 | ((cur_state + 1) < instance->lower ? | ||
71 | instance->lower : (cur_state + 1)); | ||
72 | } else { | ||
73 | next_target = THERMAL_NO_TARGET; | ||
74 | } | ||
75 | |||
76 | return next_target; | ||
77 | } | ||
78 | |||
66 | switch (trend) { | 79 | switch (trend) { |
67 | case THERMAL_TREND_RAISING: | 80 | case THERMAL_TREND_RAISING: |
68 | if (throttle) { | 81 | if (throttle) { |
@@ -149,7 +162,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) | |||
149 | dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", | 162 | dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", |
150 | old_target, (int)instance->target); | 163 | old_target, (int)instance->target); |
151 | 164 | ||
152 | if (old_target == instance->target) | 165 | if (instance->initialized && old_target == instance->target) |
153 | continue; | 166 | continue; |
154 | 167 | ||
155 | /* Activate a passive thermal instance */ | 168 | /* Activate a passive thermal instance */ |
@@ -161,7 +174,7 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) | |||
161 | instance->target == THERMAL_NO_TARGET) | 174 | instance->target == THERMAL_NO_TARGET) |
162 | update_passive_instance(tz, trip_type, -1); | 175 | update_passive_instance(tz, trip_type, -1); |
163 | 176 | ||
164 | 177 | instance->initialized = true; | |
165 | instance->cdev->updated = false; /* cdev needs update */ | 178 | instance->cdev->updated = false; /* cdev needs update */ |
166 | } | 179 | } |
167 | 180 | ||
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d9e525cc9c1c..682bc1ef9c37 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c | |||
@@ -532,8 +532,22 @@ static void update_temperature(struct thermal_zone_device *tz) | |||
532 | mutex_unlock(&tz->lock); | 532 | mutex_unlock(&tz->lock); |
533 | 533 | ||
534 | trace_thermal_temperature(tz); | 534 | trace_thermal_temperature(tz); |
535 | dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", | 535 | if (tz->last_temperature == THERMAL_TEMP_INVALID) |
536 | tz->last_temperature, tz->temperature); | 536 | dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n", |
537 | tz->temperature); | ||
538 | else | ||
539 | dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n", | ||
540 | tz->last_temperature, tz->temperature); | ||
541 | } | ||
542 | |||
543 | static void thermal_zone_device_reset(struct thermal_zone_device *tz) | ||
544 | { | ||
545 | struct thermal_instance *pos; | ||
546 | |||
547 | tz->temperature = THERMAL_TEMP_INVALID; | ||
548 | tz->passive = 0; | ||
549 | list_for_each_entry(pos, &tz->thermal_instances, tz_node) | ||
550 | pos->initialized = false; | ||
537 | } | 551 | } |
538 | 552 | ||
539 | void thermal_zone_device_update(struct thermal_zone_device *tz) | 553 | void thermal_zone_device_update(struct thermal_zone_device *tz) |
@@ -1900,6 +1914,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1900 | 1914 | ||
1901 | INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); | 1915 | INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); |
1902 | 1916 | ||
1917 | thermal_zone_device_reset(tz); | ||
1903 | thermal_zone_device_update(tz); | 1918 | thermal_zone_device_update(tz); |
1904 | 1919 | ||
1905 | return tz; | 1920 | return tz; |
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index d7ac1fccd659..749d41abfbab 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h | |||
@@ -41,6 +41,7 @@ struct thermal_instance { | |||
41 | struct thermal_zone_device *tz; | 41 | struct thermal_zone_device *tz; |
42 | struct thermal_cooling_device *cdev; | 42 | struct thermal_cooling_device *cdev; |
43 | int trip; | 43 | int trip; |
44 | bool initialized; | ||
44 | unsigned long upper; /* Highest cooling state for this trip point */ | 45 | unsigned long upper; /* Highest cooling state for this trip point */ |
45 | unsigned long lower; /* Lowest cooling state for this trip point */ | 46 | unsigned long lower; /* Lowest cooling state for this trip point */ |
46 | unsigned long target; /* expected cooling state */ | 47 | unsigned long target; /* expected cooling state */ |
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 613c29bd6baf..103fcbe6bdaf 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
@@ -43,6 +43,9 @@ | |||
43 | /* Default weight of a bound cooling device */ | 43 | /* Default weight of a bound cooling device */ |
44 | #define THERMAL_WEIGHT_DEFAULT 0 | 44 | #define THERMAL_WEIGHT_DEFAULT 0 |
45 | 45 | ||
46 | /* use value, which < 0K, to indicate an invalid/uninitialized temperature */ | ||
47 | #define THERMAL_TEMP_INVALID -274000 | ||
48 | |||
46 | /* Unit conversion macros */ | 49 | /* Unit conversion macros */ |
47 | #define DECI_KELVIN_TO_CELSIUS(t) ({ \ | 50 | #define DECI_KELVIN_TO_CELSIUS(t) ({ \ |
48 | long _t = (t); \ | 51 | long _t = (t); \ |