All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukasz Luba <lukasz.luba@arm.com>
To: linux-kernel@vger.kernel.org, rafael@kernel.org
Cc: linux-pm@vger.kernel.org, daniel.lezcano@linaro.org,
	rui.zhang@intel.com, lukasz.luba@arm.com,
	m.majewski2@samsung.com, bzolnier@gmail.com,
	m.szyprowski@samsung.com, krzysztof.kozlowski@linaro.org,
	linux-samsung-soc@vger.kernel.org
Subject: [RFC PATCH] thermal: Add API to update framework with known temperature
Date: Thu, 21 Dec 2023 09:06:37 +0000	[thread overview]
Message-ID: <20231221090637.1996394-1-lukasz.luba@arm.com> (raw)

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 --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,
-- 
2.25.1


                 reply	other threads:[~2023-12-21  9:05 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231221090637.1996394-1-lukasz.luba@arm.com \
    --to=lukasz.luba@arm.com \
    --cc=bzolnier@gmail.com \
    --cc=daniel.lezcano@linaro.org \
    --cc=krzysztof.kozlowski@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=m.majewski2@samsung.com \
    --cc=m.szyprowski@samsung.com \
    --cc=rafael@kernel.org \
    --cc=rui.zhang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.