@@ -417,10 +417,16 @@ static void handle_thermal_trip(struct thermal_zone_device *tz,
handle_non_critical_trips(tz, trip);
}
-static void update_temperature(struct thermal_zone_device *tz)
+static void update_temperature(struct thermal_zone_device *tz, bool read_temp,
+ int known_temp)
{
int temp, ret;
+ if (!read_temp) {
+ temp = known_temp;
+ goto set_temperature;
+ }
+
ret = __thermal_zone_get_temp(tz, &temp);
if (ret) {
if (ret != -EAGAIN)
@@ -430,6 +436,7 @@ static void update_temperature(struct thermal_zone_device *tz)
return;
}
+set_temperature:
tz->last_temperature = tz->temperature;
tz->temperature = temp;
@@ -449,7 +456,8 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz)
}
void __thermal_zone_device_update(struct thermal_zone_device *tz,
- enum thermal_notify_event event)
+ enum thermal_notify_event event,
+ bool read_temp, int temp)
{
struct thermal_trip *trip;
@@ -459,7 +467,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
if (!thermal_zone_device_is_enabled(tz))
return;
- update_temperature(tz);
+ update_temperature(tz, read_temp, temp);
__thermal_zone_set_trips(tz);
@@ -491,7 +499,7 @@ static int thermal_zone_device_set_mode(struct thermal_zone_device *tz,
if (!ret)
tz->mode = mode;
- __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+ __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED, true, 0);
mutex_unlock(&tz->lock);
@@ -532,11 +540,22 @@ void thermal_zone_device_update(struct thermal_zone_device *tz,
{
mutex_lock(&tz->lock);
if (thermal_zone_is_present(tz))
- __thermal_zone_device_update(tz, event);
+ __thermal_zone_device_update(tz, event, true, 0);
mutex_unlock(&tz->lock);
}
EXPORT_SYMBOL_GPL(thermal_zone_device_update);
+void thermal_zone_device_update_with_temp(struct thermal_zone_device *tz,
+ enum thermal_notify_event event,
+ int temp)
+{
+ mutex_lock(&tz->lock);
+ if (thermal_zone_is_present(tz))
+ __thermal_zone_device_update(tz, event, false, temp);
+ mutex_unlock(&tz->lock);
+}
+EXPORT_SYMBOL_GPL(thermal_zone_device_update_with_temp);
+
static void thermal_zone_device_check(struct work_struct *work)
{
struct thermal_zone_device *tz = container_of(work, struct
@@ -113,7 +113,8 @@ void thermal_unregister_governor(struct thermal_governor *);
int thermal_zone_device_set_policy(struct thermal_zone_device *, char *);
int thermal_build_list_of_policies(char *buf);
void __thermal_zone_device_update(struct thermal_zone_device *tz,
- enum thermal_notify_event event);
+ enum thermal_notify_event event,
+ bool read_temp, int temp);
void thermal_zone_device_critical_reboot(struct thermal_zone_device *tz);
void thermal_governor_update_tz(struct thermal_zone_device *tz,
enum thermal_notify_event reason);
@@ -131,7 +131,8 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
thermal_zone_set_trip_temp(tz, trip, temp);
- __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
+ __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED,
+ true, 0);
}
unlock:
@@ -256,7 +257,8 @@ emul_temp_store(struct device *dev, struct device_attribute *attr,
ret = tz->ops->set_emul_temp(tz, temperature);
if (!ret)
- __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+ __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED,
+ true, 0);
mutex_unlock(&tz->lock);
@@ -158,7 +158,7 @@ void thermal_zone_trip_updated(struct thermal_zone_device *tz,
thermal_notify_tz_trip_change(tz->id, thermal_zone_trip_id(tz, trip),
trip->type, trip->temperature,
trip->hysteresis);
- __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
+ __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED, true, 0);
}
void thermal_zone_set_trip_temp(struct thermal_zone_device *tz,
Some thermal drivers support trip point interrupts. These IRQs are triggered when the defined temperature threshold value is reached. This information is enough to say what is the temperature. Therefore, create a new API, which allows to provide temperature value as an argument and avoid reading the temperature again by in the framework function. This would also avoid scenario when the temperature which is later read via update_temperature() is different than the one which triggered the IRQ. This issue has been reported on some mainline boards. It should also improve performance in such scenario, since there is no call to __thermal_zone_get_temp() in the code path (which might be heavy, when temperature sensor is connected via slow interface). Signed-off-by: Lukasz Luba <lukasz.luba@arm.com> --- Hi all, This is a RFC with proposal to skip reading temperature using get_temp() callback when calling thermal_zone_device_update() from thermal driver IRQ hanlder. There was a discussion [1] that reading temperature after the IRQ might give different value than that IRQ trip threshold was programmed. Therefore, this proposal aims to solve the situation and feed temperature to the thermal fwk as an argument. Regards, Lukasz [1] https://lore.kernel.org/lkml/20231113130435.500353-1-m.majewski2@samsung.com/ drivers/thermal/thermal_core.c | 29 ++++++++++++++++++++++++----- drivers/thermal/thermal_core.h | 3 ++- drivers/thermal/thermal_sysfs.c | 6 ++++-- drivers/thermal/thermal_trip.c | 2 +- 4 files changed, 31 insertions(+), 9 deletions(-)