This is a note to let you know that I've just added the patch titled thermal/drivers/hisi: Fix multiple alarm interrupts firing to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: thermal-drivers-hisi-fix-multiple-alarm-interrupts-firing.patch and it can be found in the queue-4.9 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From db2b0332608c8e648ea1e44727d36ad37cdb56cb Mon Sep 17 00:00:00 2001 From: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx> Date: Thu, 19 Oct 2017 19:05:47 +0200 Subject: thermal/drivers/hisi: Fix multiple alarm interrupts firing From: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx> commit db2b0332608c8e648ea1e44727d36ad37cdb56cb upstream. 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@xxxxxxxxxx> Reviewed-by: Leo Yan <leo.yan@xxxxxxxxxx> Tested-by: Leo Yan <leo.yan@xxxxxxxxxx> Signed-off-by: Eduardo Valentin <edubezval@xxxxxxxxx> Signed-off-by: Kevin Wangtao <kevin.wangtao@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/thermal/hisi_thermal.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -76,6 +76,12 @@ static inline long _temp_to_step(long te return ((temp - HISI_TEMP_BASE * 1000) * 255) / 200000; } +static inline long hisi_thermal_round_temp(int temp) +{ + return hisi_thermal_step_to_temp( + hisi_thermal_temp_to_step(temp)); +} + static long hisi_thermal_get_sensor_temp(struct hisi_thermal_data *data, struct hisi_thermal_sensor *sensor) { @@ -230,7 +236,7 @@ static irqreturn_t hisi_thermal_alarm_ir sensor = &data->sensors[data->irq_bind_sensor]; dev_crit(&data->pdev->dev, "THERMAL ALARM: T > %d\n", - sensor->thres_temp / 1000); + sensor->thres_temp); mutex_unlock(&data->thermal_lock); for (i = 0; i < HISI_MAX_SENSORS; i++) { @@ -269,7 +275,7 @@ static int hisi_thermal_register_sensor( for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { if (trip[i].type == THERMAL_TRIP_PASSIVE) { - sensor->thres_temp = trip[i].temperature; + sensor->thres_temp = hisi_thermal_round_temp(trip[i].temperature); break; } } Patches currently in stable-queue which might be from daniel.lezcano@xxxxxxxxxx are queue-4.9/thermal-drivers-hisi-fix-kernel-panic-on-alarm-interrupt.patch queue-4.9/thermal-drivers-hisi-fix-multiple-alarm-interrupts-firing.patch queue-4.9/thermal-drivers-hisi-fix-missing-interrupt-enablement.patch