diff mbox series

[RFC] thermal: Add API to update framework with known temperature

Message ID 20231221090637.1996394-1-lukasz.luba@arm.com
State New
Headers show
Series [RFC] thermal: Add API to update framework with known temperature | expand

Commit Message

Lukasz Luba Dec. 21, 2023, 9:06 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 62979c5401c3..9f25c62bd3cd 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -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
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index e6a2b6f97be8..2d73847fcfea 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -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);
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index 5abf6d136c24..9062545f314e 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -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);
 
diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c
index a1ad345c0741..77dc433e6e1c 100644
--- a/drivers/thermal/thermal_trip.c
+++ b/drivers/thermal/thermal_trip.c
@@ -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,