summaryrefslogtreecommitdiff
path: root/drivers/thermal/thermal_trip.c
AgeCommit message (Collapse)AuthorFilesLines
2023-10-20thermal: core: Don't update trip points inside the hysteresis rangeNĂ­colas F. R. A. Prado1-2/+17
When searching for the trip points that need to be set, the nearest higher trip point's temperature is used for the high trip, while the nearest lower trip point's temperature minus the hysteresis is used for the low trip. The issue with this logic is that when the current temperature is inside a trip point's hysteresis range, both high and low trips will come from the same trip point. As a consequence instability can still occur like this: * the temperature rises slightly and enters the hysteresis range of a trip point * polling happens and updates the trip points to the hysteresis range * the temperature falls slightly, exiting the hysteresis range, crossing the trip point and triggering an IRQ, the trip points are updated * repeat So even though the current hysteresis implementation prevents instability from happening due to IRQs triggering on the same temperature value, both ways, it doesn't prevent it from happening due to an IRQ on one way and polling on the other. To properly implement a hysteresis behavior, when inside the hysteresis range, don't update the trip points. This way, the previously set trip points will stay in effect, which will in a way remember the previous state (if the temperature signal came from above or below the range) and therefore have the right trip point already set. The exception is if there was no previous trip point set, in which case a previous state doesn't exist, and so it's sensible to allow the hysteresis range as trip points. The following logs show the current behavior when running on a real machine: [ 202.524658] thermal thermal_zone0: new temperature boundaries: -2147483647 < x < 40000 203.562817: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=36986 temp=37979 [ 203.562845] thermal thermal_zone0: new temperature boundaries: 37000 < x < 40000 204.176059: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=37979 temp=40028 [ 204.176089] thermal thermal_zone0: new temperature boundaries: 37000 < x < 100000 205.226813: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=40028 temp=38652 [ 205.226842] thermal thermal_zone0: new temperature boundaries: 37000 < x < 40000 And with this patch applied: [ 184.933415] thermal thermal_zone0: new temperature boundaries: -2147483647 < x < 40000 185.981182: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=36986 temp=37872 186.744685: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=37872 temp=40058 [ 186.744716] thermal thermal_zone0: new temperature boundaries: 37000 < x < 100000 187.773284: thermal_temperature: thermal_zone=vpu0-thermal id=0 temp_prev=40058 temp=38698 Fixes: 060c034a9741 ("thermal: Add support for hardware-tracked trip points") Signed-off-by: NĂ­colas F. R. A. Prado <nfraprado@collabora.com> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Co-developed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2023-10-20thermal: trip: Define for_each_trip() macroRafael J. Wysocki1-3/+4
Define a new macro for_each_trip() to be used by the thermal core code and thermal governors for walking trips in a given thermal zone. Modify for_each_thermal_trip() to use this macro instead of an open- coded loop over trips. No intentional functional impact. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
2023-10-20thermal: trip: Simplify computing trip indicesRafael J. Wysocki1-8/+5
A trip index can be computed right away as a difference between the value of a trip pointer pointing to the given trip object and the start of the trips[] table in the given thermal zone, so change thermal_zone_trip_id() accordingly. No intentional functional impact (except for some speedup). Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Reviewed-by: Lukasz Luba <lukasz.luba@arm.com> Tested-by: Lukasz Luba <lukasz.luba@arm.com>
2023-10-11thermal: trip: Drop lockdep assertion from thermal_zone_trip_id()Rafael J. Wysocki1-2/+0
The lockdep assertion in thermal_zone_trip_id() triggers when the trip point sysfs attribute of a thermal instance is read, because there is no thermal zone locking in that code path. This is not verly useful, though, because there is no mechanism by which the location of the trips[] table in a thermal zone or its size can change after binding cooling devices to the trips in that thermal zone and before those cooling devices are unbound from them. Thus it is not in fact necessary to hold the thermal zone lock when thermal_zone_trip_id() is called from trip_point_show() and so the lockdep asserion in the former is invalid. Accordingly, drop that lockdep assertion. Fixes: 2c7b4bfadef0 ("thermal: core: Store trip pointer in struct thermal_instance") Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2023-10-07thermal: trip: Remove lockdep assertion from for_each_thermal_trip()Rafael J. Wysocki1-2/+0
The lockdep assertion in for_each_thermal_trip() was added to possibly catch incorrect usage of that function without the thermal zone lock. However, it turns out that the ACPI thermal driver has a legitimate reason to call for_each_thermal_trip() without locking. Namely, it is called by acpi_thermal_bind_unbind_cdev() in the thermal zone registration and unregistration paths. That function cannot acquire the thermal zone lock by itself, because it calls functions that acquire it, thermal_bind_cdev_to_trip() or thermal_unbind_cdev_from_trip(). However, it is invoked when the ACPI notify handler for the thermal zone in question has not been registered yet (in the registration path) or after that handler has been unregistered (in the unregistration path). Therefore, when for_each_thermal_trip() is called by acpi_thermal_bind_unbind_cdev(), thermal trip changes induced by the platform firmware cannot take place and so the thermal zone's trips[] table is effectively immutable. Hence, it is valid to call for_each_thermal_trip() from acpi_thermal_bind_unbind_cdev() without locking and the lockdep assertion in the former is in fact incorrect, so remove it. Fixes: d5ea889246b1 ("ACPI: thermal: Do not use trip indices for cooling device binding") Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2023-10-05thermal: core: Add function to walk trips under zone lockRafael J. Wysocki1-0/+14
Add a wrapper around for_each_thermal_trip(), called thermal_zone_for_each_trip(), that will invoke the former under the thermal zone lock and pass its return value to the caller. Two drivers will be modified subsequently to use this new function. No functional impact. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
2023-09-28thermal: core: Store trip pointer in struct thermal_instanceRafael J. Wysocki1-0/+15
Replace the integer trip number stored in struct thermal_instance with a pointer to the relevant trip and adjust the code using the structure in question accordingly. The main reason for making this change is to allow the trip point to cooling device binding code more straightforward, as illustrated by subsequent modifications of the ACPI thermal driver, but it also helps to clarify the overall design and allows the governor code overhead to be reduced (through subsequent modifications). The only case in which it adds complexity is trip_point_show() that needs to walk the trips[] table to find the index of the given trip point, but this is not a critical path and the interface that trip_point_show() belongs to is problematic anyway (for instance, it doesn't cover the case when the same cooling devices is associated with multiple trip points). This is a preliminary change and the affected code will be refined by a series of subsequent modifications of thermal governors, the core and the ACPI thermal driver. The general functionality is not expected to be affected by this change. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
2023-09-26thermal: trip: Drop redundant trips check from for_each_thermal_trip()Rafael J. Wysocki1-3/+0
It is invalid to call for_each_thermal_trip() on an unregistered thermal zone anyway, and as per thermal_zone_device_register_with_trips(), the trips[] table must be present if num_trips is greater than zero for the given thermal zone. Hence, the trips check in for_each_thermal_trip() is redundant and so it can be dropped. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
2023-08-29thermal: core: Drop unused .get_trip_*() callbacksRafael J. Wysocki1-21/+3
After recent changes in the ACPI thermal driver and in the Intel DTS IOSF thermal driver, all thermal zone drivers are expected to use trip tables for initialization and none of them should implement .get_trip_type(), .get_trip_temp() or .get_trip_hyst() callbacks, so drop these callbacks entirely from the core. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2023-08-17thermal: core: Rework and rename __for_each_thermal_trip()Rafael J. Wysocki1-10/+8
Rework the currently unused __for_each_thermal_trip() to pass original pointers to struct thermal_trip objects to the callback, so it can be used for updating trip data (e.g. temperatures), rename it to for_each_thermal_trip() and make it available to modular drivers. Suggested-by: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2023-01-25thermal/core: Move the thermal trip code to a dedicated fileDaniel Lezcano1-0/+182
The thermal_core.c files contains a lot of functions handling different thermal components like the governors, the trip points, the cooling device, the OF cooling device, etc ... This organization does not help to migrate to a more sane code where there is a better self-encapsulation as all the components' internals can be directly accessed from a single file. For the sake of clarity, let's move the thermal trip points code in a dedicated thermal_trip.c file and add a function to browse all the trip points like we do with the thermal zones, the govenors and the cooling devices. The same can be done for the cooling devices and the governor code but that will come later as the current work in the thermal framework is to fix the trip point handling and use a generic trip point structure. No functional changes intended. Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Reviewed-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>