aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2017-10-19 13:05:47 -0400
committerEduardo Valentin <edubezval@gmail.com>2017-10-31 22:32:15 -0400
commitdb2b0332608c8e648ea1e44727d36ad37cdb56cb (patch)
tree283f64751488274720106352ac1c46a1d0c92fc4
parent48880b979cdc9ef5a70af020f42b8ba1e51dbd34 (diff)
thermal/drivers/hisi: Fix multiple alarm interrupts firing
The DT specifies a threshold of 65000, we setup the register with a value in the temperature resolution for the controller, 64656. When we reach 64656, the interrupt fires, the interrupt is disabled. Then the irq thread runs and calls thermal_zone_device_update() which will call in turn hisi_thermal_get_temp(). The function will look if the temperature decreased, assuming it was more than 65000, but that is not the case because the current temperature is 64656 (because of the rounding when setting the threshold). This condition being true, we re-enable the interrupt which fires immediately after exiting the irq thread. That happens again and again until the temperature goes to more than 65000. Potentially, there is here an interrupt storm if the temperature stabilizes at this temperature. A very unlikely case but possible. In any case, it does not make sense to handle dozens of alarm interrupt for nothing. Fix this by rounding the threshold value to the controller resolution so the check against the threshold is consistent with the one set in the controller. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Reviewed-by: Leo Yan <leo.yan@linaro.org> Tested-by: Leo Yan <leo.yan@linaro.org> Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
-rw-r--r--drivers/thermal/hisi_thermal.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c
index 583bc1934127..f5231974504c 100644
--- a/drivers/thermal/hisi_thermal.c
+++ b/drivers/thermal/hisi_thermal.c
@@ -90,6 +90,12 @@ static inline long hisi_thermal_temp_to_step(long temp)
90 return (temp - HISI_TEMP_BASE) / HISI_TEMP_STEP; 90 return (temp - HISI_TEMP_BASE) / HISI_TEMP_STEP;
91} 91}
92 92
93static inline long hisi_thermal_round_temp(int temp)
94{
95 return hisi_thermal_step_to_temp(
96 hisi_thermal_temp_to_step(temp));
97}
98
93static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, 99static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data,
94 struct hisi_thermal_sensor *sensor) 100 struct hisi_thermal_sensor *sensor)
95{ 101{
@@ -221,7 +227,7 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev)
221 sensor = &data->sensors; 227 sensor = &data->sensors;
222 228
223 dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", 229 dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n",
224 sensor->thres_temp / 1000); 230 sensor->thres_temp);
225 mutex_unlock(&data->thermal_lock); 231 mutex_unlock(&data->thermal_lock);
226 232
227 thermal_zone_device_update(data->sensors.tzd, 233 thermal_zone_device_update(data->sensors.tzd,
@@ -255,7 +261,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev,
255 261
256 for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { 262 for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) {
257 if (trip[i].type == THERMAL_TRIP_PASSIVE) { 263 if (trip[i].type == THERMAL_TRIP_PASSIVE) {
258 sensor->thres_temp = trip[i].temperature; 264 sensor->thres_temp = hisi_thermal_round_temp(trip[i].temperature);
259 break; 265 break;
260 } 266 }
261 } 267 }