linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Daniel Lezcano <daniel.lezcano@linaro.org>
To: daniel.lezcano@linaro.org, rui.zhang@intel.com
Cc: amit.kucheria@verdurent.com, vincent.whitchurch@axis.com,
	linux-pm@vger.kernel.org (open list:THERMAL),
	linux-kernel@vger.kernel.org (open list)
Subject: [PATCH] thermal: core: Send a sysfs notification on trip points
Date: Thu,  2 Apr 2020 16:21:15 +0200	[thread overview]
Message-ID: <20200402142116.22869-1-daniel.lezcano@linaro.org> (raw)
In-Reply-To: <a7e8287d-72be-7ab0-697a-9de40eb3f81f@linaro.org>

Currently the userspace has no easy way to get notified when a
specific trip point was crossed. There are a couple of approaches:

- the userspace polls the sysfs temperature with usually an
  unacceptable delay between the trip temperature point crossing and
  the moment it is detected, or a high polling rate with an
  unacceptable number of wakeup events.

- the thermal zone is set to be managed by an userspace governor in
  order to receive the uevent even if the thermal zone needs to be
  managed by another governor.

These changes allow to send a sysfs notification on the
trip_point_*_temp when the temperature is getting higher than the trip
point temperature. By this way, the userspace can be notified
everytime when the trip point is crossed, this is useful for the
thermal Android HAL or for notification to be sent via d-bus.

That allows the userspace to manage the applications based on specific
alerts on different thermal zones to mitigate the skin temperature,
letting the kernel governors handle the high temperature for hardware
like the CPU, the GPU or the modem.

The temperature can be oscillating around a trip point and the event
will be sent multiple times. It is up to the userspace to deal with
this situation.

The following userspace program allows to monitor those events:

struct trip_data {
       int fd;
       int temperature;
       const char *path;
};

int main(int argc, char *argv[])
{
	int efd, i;
	struct trip_data *td;
	struct epoll_event epe;

	if (argc < 2) {
		fprintf(stderr, "%s <trip1> ... <tripn>\n", argv[0]);
		return 1;
	}

	if (argc > MAX_TRIPS) {
		fprintf(stderr, "Max trip points supported: %d\n", MAX_TRIPS);
		return 1;
	}

	efd = epoll_create(MAX_TRIPS);
	if (efd <  0) {
		fprintf(stderr, "epoll_create failed: %d\n", errno);
		return 1;
	}

	for (i = 0; i < argc - 1; i++) {

		FILE *f;
		int temperature;

		f = fopen(argv[i + 1], "r");
		if (!f) {
			fprintf(stderr, "Failed to open '%s': %d\n", argv[i + 1], errno);
			return 1;
		}

		td = malloc(sizeof(*td));
		if (!td) {
			fprintf(stderr, "Failed to allocate trip_data\n");
			return 1;
		}

		fscanf(f, "%d\n", &temperature);
		rewind(f);

		td->fd = fileno(f);
		td->path = argv[i + 1];
		td->temperature = temperature;

		epe.events = EPOLLIN | EPOLLET;
		epe.data.ptr = td;

		if (epoll_ctl(efd, EPOLL_CTL_ADD, td->fd, &epe)) {
			fprintf(stderr, "Failed to epoll_ctl: %d\n", errno);
			return 1;
		}

		printf("Set '%s' for temperature '%d'\n",
		       td->path, td->temperature);
	}

	while(1) {

		if (epoll_wait(efd, &epe, 1, -1) < 0) {
			fprintf(stderr, "Failed to epoll_wait: %d\n", errno);
			return 1;
		}

		td = epe.data.ptr;

		printf("The trip point '%s' crossed the temperature '%d'\n",
		       td->path, td->temperature);
	}

	return 0;
}

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/thermal/thermal_core.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index c06550930979..3cbdd20252ab 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -407,6 +407,19 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
 	}
 }
 
+static int thermal_trip_crossed(struct thermal_zone_device *tz, int trip)
+{
+	int trip_temp;
+
+	tz->ops->get_trip_temp(tz, trip, &trip_temp);
+
+	if (tz->last_temperature == THERMAL_TEMP_INVALID)
+		return 0;
+
+	return ((tz->last_temperature < trip_temp)) &&
+		(tz->temperature >= trip_temp));
+}
+
 static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
 {
 	enum thermal_trip_type type;
@@ -417,6 +430,16 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
 
 	tz->ops->get_trip_type(tz, trip, &type);
 
+	/*
+	 * This condition will be true everytime the temperature is
+	 * greater than the trip point and the previous temperature
+	 * was below. In this case notify the userspace via a sysfs
+	 * event on the trip point.
+	 */
+	if (thermal_trip_crossed(tz, trip))
+		sysfs_notify(&tz->device.kobj, NULL,
+			     tz->trip_temp_attrs[trip].attr.attr.name);
+
 	if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT)
 		handle_critical_trips(tz, trip, type);
 	else
-- 
2.17.1


       reply	other threads:[~2020-04-02 14:23 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <a7e8287d-72be-7ab0-697a-9de40eb3f81f@linaro.org>
2020-04-02 14:21 ` Daniel Lezcano [this message]
2020-04-03 14:40   ` [PATCH] thermal: core: Send a sysfs notification on trip points Vincent Whitchurch
2020-04-03 15:26     ` Daniel Lezcano
2020-04-06  7:45       ` Vincent Whitchurch
2020-04-06  9:45         ` Daniel Lezcano
2020-04-06  9:58           ` Vincent Whitchurch
2020-04-06  9:25   ` Amit Kucheria
2020-04-06  9:53     ` Daniel Lezcano

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=20200402142116.22869-1-daniel.lezcano@linaro.org \
    --to=daniel.lezcano@linaro.org \
    --cc=amit.kucheria@verdurent.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rui.zhang@intel.com \
    --cc=vincent.whitchurch@axis.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).