aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2022-07-07 19:59:38 +0200
committerDaniel Lezcano <daniel.lezcano@linaro.org>2022-07-07 19:59:38 +0200
commit8d2f47a16dfb057c99cb78df85f7d24f7975b36d (patch)
tree09f886af90c753f428e009a3d4c5c7d46e8ff7b5
parentf180a56ad98f04a224d3e16ffd73c5d082293fab (diff)
downloadlinux-thermal/debugfs-v2.tar.gz
thermal/core: Fix thermal trip cross pointthermal/debugfs-v2
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r--drivers/thermal/thermal_core.c32
-rw-r--r--include/linux/thermal.h2
2 files changed, 24 insertions, 10 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d4207805b6f670..264db84107296a 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -357,19 +357,30 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
static void handle_thermal_trip_crossed(struct thermal_zone_device *tz, int trip,
int trip_temp, int trip_hyst, enum thermal_trip_type trip_type)
{
+ int trip_low_temp = trip_temp - trip_hyst;
+
if (tz->last_temperature == THERMAL_TEMP_INVALID)
return;
- if (tz->last_temperature < trip_temp &&
- tz->temperature >= trip_temp) {
- thermal_notify_tz_trip_up(tz->id, trip,
- tz->temperature);
- }
-
- if (tz->last_temperature >= trip_temp &&
- tz->temperature < (trip_temp - trip_hyst)) {
- thermal_notify_tz_trip_down(tz->id, trip,
- tz->temperature);
+ /*
+ * Due to the hysteresis, a third information is needed to
+ * detect when the temperature is wavering between the
+ * trip_low_temp and the trip_temp. A trip point is crossed
+ * the way up only if the temperature is above it while the
+ * previous temperature was below *and* we crossed the
+ * trip_temp_low before. The previous trip point give us the
+ * previous trip point transition. The similar problem exists
+ * when crossing the way down.
+ */
+ if (tz->last_temperature < trip_temp && tz->temperature >= trip_temp &&
+ trip != tz->prev_trip) {
+ thermal_notify_tz_trip_up(tz->id, trip, tz->temperature);
+ tz->prev_trip = trip;
+
+ } else if (tz->last_temperature >= trip_low_temp && tz->temperature < trip_low_temp &&
+ trip == tz->prev_trip) {
+ thermal_notify_tz_trip_down(tz->id, trip, tz->temperature);
+ tz->prev_trip = trip - 1;
}
}
@@ -430,6 +441,7 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz)
{
struct thermal_instance *pos;
tz->temperature = THERMAL_TEMP_INVALID;
+ tz->prev_trip = -1;
tz->prev_low_trip = -INT_MAX;
tz->prev_high_trip = INT_MAX;
list_for_each_entry(pos, &tz->thermal_instances, tz_node)
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index c8528bb6c01cb8..81156c16f8bac4 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -127,6 +127,7 @@ struct thermal_cooling_device {
* @last_temperature: previous temperature read
* @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION
* @passive: 1 if you've crossed a passive trip point, 0 otherwise.
+ * @prev_trip: previous trip point the thermal zone was, -1 if below all of them
* @prev_low_trip: the low current temperature if you've crossed a passive
trip point.
* @prev_high_trip: the above current temperature if you've crossed a
@@ -162,6 +163,7 @@ struct thermal_zone_device {
int last_temperature;
int emul_temperature;
int passive;
+ int prev_trip;
int prev_low_trip;
int prev_high_trip;
atomic_t need_update;