lkml.org 
[lkml]   [2022]   [Feb]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
SubjectRe: [PATCH] tools/lib/thermal: Add a thermal library
From

Hi Srinivas,

On 04/02/2022 20:32, srinivas pandruvada wrote:
> On Fri, 2022-02-04 at 18:11 +0100, Rafael J. Wysocki wrote:
>> CC Rui and Srinivas
>>
>> On Fri, Feb 4, 2022 at 5:15 PM Daniel Lezcano
>> <daniel.lezcano@linaro.org> wrote:
>>>
>>> The thermal framework implements a netlink notification mechanism
>>> to
>>> be used by the userspace to have a thermal configuration discovery,
>>> trip point changes or violation, cooling device changes
>>> notifications,
>>> etc...
>>>
>>> This library provides a level of abstraction for the thermal
>>> netlink
>>> notification allowing the userspace to connect to the notification
>>> mechanism more easily. The library is callback oriented.
>>>
>>> As it is the very first iteration, the API may be subject to
>>> changes. For this reason, the documentation will be provided after
>>> those are stabilized.
>>
>> So shouldn't this be an RFC?
>>
>> Also, I would prefer documentation to be provided or at least some
>> intended usage examples to be given.
>>
>>> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
>>> ---
>>>  tools/Makefile                           |  14 +-
>>>  tools/include/uapi/linux/thermal.h       |  91 ++++++
> This is duplicating the file at include/uapi/linux. I know this is done
> for other tools also. In my use I am copying and using symbolic link.

Why copy and symbolic link ? Should it be create a symbolic link only ?

> BTW I have potential usage of netlink targeted for next release in
> linux tools.
>
> https://github.com/spandruvada/linux-kernel/blob/intel-sst/tools/power/x86/intel-speed-select/hfi-events.c
>
> I can replace with libthermal calls once ready. I will check the code
> below next week.

Great, thanks!

In attachment a test file as an example of the library usage.


--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <thermal.h>

#define MAX_EVENTS 10

static int show_trip(struct thermal_trip *tt, void *arg)
{
printf("trip id=%d, type=%d, temp=%d, hyst=%d\n",
tt->id, tt->type, tt->temp, tt->hyst);

return 0;
}

static int show_temp(struct thermal_zone *tz, void *arg)
{
thermal_cmd_get_temp(arg, tz);

printf("temperature: %d\n", tz->temp);

return 0;
}

static int show_governor(struct thermal_zone *tz, void *arg)
{
thermal_cmd_get_governor(arg, tz);

printf("governor: '%s'\n", tz->governor);

return 0;
}

static int show_tz(struct thermal_zone *tz, void *arg)
{
printf("thermal zone '%s', id=%d\n", tz->name, tz->id);

for_each_thermal_trip(tz->trip, show_trip, NULL);

show_temp(tz, arg);

show_governor(tz, arg);

return 0;
}

static int tz_create(const char *name, int tz_id, void *arg)
{
printf("Thermal zone '%s'/%d created\n", name, tz_id);

return 0;
}

static int tz_delete(int tz_id, void *arg)
{
printf("Thermal zone %d deleted\n", tz_id);

return 0;
}

static int tz_disable(int tz_id, void *arg)
{
printf("Thermal zone %d disabled\n", tz_id);

return 0;
}

static int tz_enable(int tz_id, void *arg)
{
printf("Thermal zone %d enabled\n", tz_id);

return 0;
}

static int tz_temp(int tz_id, int temp, void *arg)
{
printf("Thermal zone %d temperature: %d\n", tz_id, temp);

return 0;
}

static int trip_high(int tz_id, int trip_id, int temp, void *arg)
{
printf("Thermal zone %d: trip point %d crossed way up with %d °C\n",
tz_id, trip_id, temp);

return 0;
}

static int trip_low(int tz_id, int trip_id, int temp, void *arg)
{
printf("Thermal zone %d: trip point %d crossed way down with %d °C\n",
tz_id, trip_id, temp);

return 0;
}

static int trip_add(int tz_id, int trip_id, int type, int temp, int hyst, void *arg)
{
printf("Trip point added %d: id=%d, type=%d, temp=%d, hyst=%d\n",
tz_id, trip_id, type, temp, hyst);

return 0;
}

static int trip_delete(int tz_id, int trip_id, void *arg)
{
printf("Trip point deleted %d: id=%d\n", tz_id, trip_id);

return 0;
}

static int trip_change(int tz_id, int trip_id, int type, int temp, int hyst, void *arg)
{
printf("Trip point changed %d: id=%d, type=%d, temp=%d, hyst=%d\n",
tz_id, trip_id, type, temp, hyst);

return 0;
}

static int cdev_add(const char *name, int cdev_id, int max_state, void *arg)
{
printf("Cooling device '%s'/%d (max state=%d) added",
name, cdev_id, max_state);

return 0;
}

static int cdev_delete(int cdev_id, void *arg)
{
printf("Cooling device %d deleted", cdev_id);

return 0;
}

static int cdev_update(int cdev_id, int cur_state, void *arg)
{
printf("cdev:%d state:%d\n", cdev_id, cur_state);

return 0;
}

static int gov_change(int tz_id, const char *name, void *arg)
{
printf("tz %d, governor=%s\n", tz_id, name);

return 0;
}

static struct thermal_ops ops = {
.sampling.tz_temp = tz_temp,
.events.tz_create = tz_create,
.events.tz_delete = tz_delete,
.events.tz_disable = tz_disable,
.events.tz_enable = tz_enable,
.events.trip_high = trip_high,
.events.trip_low = trip_low,
.events.trip_add = trip_add,
.events.trip_delete = trip_delete,
.events.trip_change = trip_change,
.events.cdev_add = cdev_add,
.events.cdev_delete = cdev_delete,
.events.cdev_update = cdev_update,
.events.gov_change = gov_change
};

static int stop = 0;

static void sighandler(int sig)
{
stop = 1;
};

static int thermal_netlink_get_temp_bench(struct thermal_handler *th,
struct thermal_zone *tz)
{
int nr_messages = 0;
int nr_secs = 5;
unsigned long long sum = 0;

printf("Benchmarking netlink... wait %d secs\n", nr_secs);

signal(SIGALRM, sighandler);
alarm(nr_secs);
while (!stop) {
thermal_cmd_get_temp(th, tz);
sum += tz->temp;
nr_messages++;
}

printf("Temperature reading %d msg/sec (%llu usec/msg), avg temp=%llu\n",
nr_messages / nr_secs, 1000000ULL / (nr_messages / nr_secs),
sum / nr_messages);

return 0;
}

static int thermal_sysfs_get_temp_bench(struct thermal_zone *tz)
{
int nr_messages = 0;
int nr_secs = 5;
unsigned long long sum = 0;
char path[PATH_MAX];
int fd;

snprintf(path, PATH_MAX,
"/sys/class/thermal/thermal_zone%d/temp", tz->id);

fd = open(path, O_RDONLY);
if (fd < 0)
return -1;

printf("Benchmarking sysfs... wait %d secs\n", nr_secs);

signal(SIGALRM, sighandler);
alarm(nr_secs);
stop = 0;
while (!stop) {
char buffer[128] = { 0 };

pread(fd, buffer, 127, 0);
sum += atoi(buffer);
nr_messages++;
}

if (!nr_messages) {
fprintf(stderr, "No message read\n");
return -1;
}

printf("Temperature reading %d msg/sec (%llu usec/msg), avg temp=%llu\n",
nr_messages / nr_secs, 1000000ULL / (nr_messages / nr_secs),
sum / nr_messages);

close(fd);

return 0;
}

int main(void)
{
struct thermal_zone *tz;
struct thermal_handler *th;
struct epoll_event ev;
struct epoll_event events[MAX_EVENTS];
int epollfd;
int nfds;
int i;

th = thermal_init(&ops);
if (!th)
return -1;

tz = thermal_zone_discover(th);
if (!tz)
return -1;

thermal_netlink_get_temp_bench(th, tz);

thermal_sysfs_get_temp_bench(tz);

for_each_thermal_zone(tz, show_tz, th);

epollfd = epoll_create1(0);
if (epollfd < 0)
return -1;

ev.events = EPOLLIN;
ev.data.ptr = thermal_events_handle;

if (epoll_ctl(epollfd, EPOLL_CTL_ADD, thermal_events_fd(th), &ev) == -1)
return -1;

ev.events = EPOLLIN;
ev.data.ptr = thermal_sampling_handle;

if (epoll_ctl(epollfd, EPOLL_CTL_ADD, thermal_sampling_fd(th), &ev) == -1)
return -1;

while (1) {

nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
for (i = 0; i < nfds; i++) {
if (events[i].data.ptr == thermal_events_handle) {
thermal_events_handle(th, NULL);
} else if (events[i].data.ptr == thermal_sampling_handle) {
thermal_sampling_handle(th, NULL);
}
}
}

return 0;
}
\
 
 \ /
  Last update: 2022-02-04 23:16    [W:2.128 / U:0.612 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site