Skip to content

Commit 4feaedf

Browse files
dlezcanorafaeljw
authored andcommitted
thermal/thresholds: Fix boundaries and detection routine
The current implementation does not work if the thermal zone is interrupt driven only. The boundaries are not correctly checked and computed as it happens only when the temperature is increasing or decreasing. The problem arises because the routine to detect when we cross a threshold is correlated with the computation of the boundaries. We assume we have to recompute the boundaries when a threshold is crossed but actually we should do that even if the it is not the case. Mixing the boundaries computation and the threshold detection for the sake of optimizing the routine is much more complex as it appears intuitively and prone to errors. This fix separates the boundaries computation and the threshold crossing detection into different routines. The result is a code much more simple to understand, thus easier to maintain. The drawback is we browse the thresholds list several time but we can consider that as neglictible because that happens when the temperature is updated. There are certainly some aeras to improve in the temperature update routine but it would be not adequate as this change aims to fix the thresholds for v6.13. Fixes: 445936f ("thermal: core: Add user thresholds support") Tested-by: Daniel Lezcano <daniel.lezcano@linaro.org> # rock5b, Lenovo x13s Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Link: https://patch.msgid.link/20241216212644.1145122-1-daniel.lezcano@linaro.org Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 65c8c78 commit 4feaedf

File tree

1 file changed

+36
-32
lines changed

1 file changed

+36
-32
lines changed

drivers/thermal/thermal_thresholds.c

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -69,58 +69,60 @@ static struct user_threshold *__thermal_thresholds_find(const struct list_head *
6969
return NULL;
7070
}
7171

72-
static bool __thermal_threshold_is_crossed(struct user_threshold *threshold, int temperature,
73-
int last_temperature, int direction,
74-
int *low, int *high)
72+
static bool thermal_thresholds_handle_raising(struct list_head *thresholds, int temperature,
73+
int last_temperature)
7574
{
75+
struct user_threshold *t;
7676

77-
if (temperature >= threshold->temperature) {
78-
if (threshold->temperature > *low &&
79-
THERMAL_THRESHOLD_WAY_DOWN & threshold->direction)
80-
*low = threshold->temperature;
77+
list_for_each_entry(t, thresholds, list_node) {
8178

82-
if (last_temperature < threshold->temperature &&
83-
threshold->direction & direction)
84-
return true;
85-
} else {
86-
if (threshold->temperature < *high && THERMAL_THRESHOLD_WAY_UP
87-
& threshold->direction)
88-
*high = threshold->temperature;
79+
if (!(t->direction & THERMAL_THRESHOLD_WAY_UP))
80+
continue;
8981

90-
if (last_temperature >= threshold->temperature &&
91-
threshold->direction & direction)
82+
if (temperature >= t->temperature &&
83+
last_temperature < t->temperature)
9284
return true;
9385
}
9486

9587
return false;
9688
}
9789

98-
static bool thermal_thresholds_handle_raising(struct list_head *thresholds, int temperature,
99-
int last_temperature, int *low, int *high)
90+
static bool thermal_thresholds_handle_dropping(struct list_head *thresholds, int temperature,
91+
int last_temperature)
10092
{
10193
struct user_threshold *t;
10294

103-
list_for_each_entry(t, thresholds, list_node) {
104-
if (__thermal_threshold_is_crossed(t, temperature, last_temperature,
105-
THERMAL_THRESHOLD_WAY_UP, low, high))
95+
list_for_each_entry_reverse(t, thresholds, list_node) {
96+
97+
if (!(t->direction & THERMAL_THRESHOLD_WAY_DOWN))
98+
continue;
99+
100+
if (temperature <= t->temperature &&
101+
last_temperature > t->temperature)
106102
return true;
107103
}
108104

109105
return false;
110106
}
111107

112-
static bool thermal_thresholds_handle_dropping(struct list_head *thresholds, int temperature,
113-
int last_temperature, int *low, int *high)
108+
static void thermal_threshold_find_boundaries(struct list_head *thresholds, int temperature,
109+
int *low, int *high)
114110
{
115111
struct user_threshold *t;
116112

117-
list_for_each_entry_reverse(t, thresholds, list_node) {
118-
if (__thermal_threshold_is_crossed(t, temperature, last_temperature,
119-
THERMAL_THRESHOLD_WAY_DOWN, low, high))
120-
return true;
113+
list_for_each_entry(t, thresholds, list_node) {
114+
if (temperature < t->temperature &&
115+
(t->direction & THERMAL_THRESHOLD_WAY_UP) &&
116+
*high > t->temperature)
117+
*high = t->temperature;
121118
}
122119

123-
return false;
120+
list_for_each_entry_reverse(t, thresholds, list_node) {
121+
if (temperature > t->temperature &&
122+
(t->direction & THERMAL_THRESHOLD_WAY_DOWN) &&
123+
*low < t->temperature)
124+
*low = t->temperature;
125+
}
124126
}
125127

126128
void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *high)
@@ -132,6 +134,8 @@ void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *hi
132134

133135
lockdep_assert_held(&tz->lock);
134136

137+
thermal_threshold_find_boundaries(thresholds, temperature, low, high);
138+
135139
/*
136140
* We need a second update in order to detect a threshold being crossed
137141
*/
@@ -151,12 +155,12 @@ void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *hi
151155
* - decreased : thresholds are crossed the way down
152156
*/
153157
if (temperature > last_temperature) {
154-
if (thermal_thresholds_handle_raising(thresholds, temperature,
155-
last_temperature, low, high))
158+
if (thermal_thresholds_handle_raising(thresholds,
159+
temperature, last_temperature))
156160
thermal_notify_threshold_up(tz);
157161
} else {
158-
if (thermal_thresholds_handle_dropping(thresholds, temperature,
159-
last_temperature, low, high))
162+
if (thermal_thresholds_handle_dropping(thresholds,
163+
temperature, last_temperature))
160164
thermal_notify_threshold_down(tz);
161165
}
162166
}

0 commit comments

Comments
 (0)