* [PATCH v1 0/4] Thermal library and tools
@ 2022-02-18 12:53 Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 1/4] tools/lib/thermal: Add a thermal library Daniel Lezcano
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Daniel Lezcano @ 2022-02-18 12:53 UTC (permalink / raw)
To: daniel.lezcano, rafael; +Cc: srinivas.pandruvada, linux-kernel, linux-pm
This series provides a thermal library providing the basic callback oriented
netlink communication and events with the thermal framework, a temperature
capture tool and a thermal monitoring skeleton using the thermal library.
Changelog:
- V1:
- Took into account RFC comments (unsubscribe, error enum, thermal daemon
renamed to thermal-engine)
Daniel Lezcano (4):
tools/lib/thermal: Add a thermal library
tools/thermal: Add util library
tools/thermal: A temperature capture tool
tools/thermal: Add thermal daemon skeleton
tools/Makefile | 36 +-
tools/lib/thermal/.gitignore | 2 +
tools/lib/thermal/Build | 5 +
tools/lib/thermal/Makefile | 165 ++++++++
tools/lib/thermal/commands.c | 351 ++++++++++++++++
tools/lib/thermal/events.c | 164 ++++++++
tools/lib/thermal/include/thermal.h | 141 +++++++
tools/lib/thermal/libthermal.map | 25 ++
tools/lib/thermal/libthermal.pc.template | 12 +
tools/lib/thermal/sampling.c | 75 ++++
tools/lib/thermal/thermal.c | 126 ++++++
tools/lib/thermal/thermal_nl.c | 215 ++++++++++
tools/lib/thermal/thermal_nl.h | 46 ++
tools/thermal/lib/Build | 3 +
tools/thermal/lib/Makefile | 158 +++++++
.../thermal/lib/libthermal_tools.pc.template | 12 +
tools/thermal/lib/log.c | 77 ++++
tools/thermal/lib/log.h | 31 ++
tools/thermal/lib/mainloop.c | 135 ++++++
tools/thermal/lib/mainloop.h | 14 +
tools/thermal/lib/thermal-tools.h | 10 +
tools/thermal/lib/uptimeofday.c | 40 ++
tools/thermal/lib/uptimeofday.h | 12 +
tools/thermal/thermal-engine/Build | 2 +
tools/thermal/thermal-engine/Makefile | 27 ++
tools/thermal/thermal-engine/thermal-engine.c | 287 +++++++++++++
tools/thermal/thermometer/Build | 2 +
tools/thermal/thermometer/Makefile | 23 +
tools/thermal/thermometer/thermometer.c | 393 ++++++++++++++++++
tools/thermal/thermometer/thermometer.conf | 5 +
30 files changed, 2591 insertions(+), 3 deletions(-)
create mode 100644 tools/lib/thermal/.gitignore
create mode 100644 tools/lib/thermal/Build
create mode 100644 tools/lib/thermal/Makefile
create mode 100644 tools/lib/thermal/commands.c
create mode 100644 tools/lib/thermal/events.c
create mode 100644 tools/lib/thermal/include/thermal.h
create mode 100644 tools/lib/thermal/libthermal.map
create mode 100644 tools/lib/thermal/libthermal.pc.template
create mode 100644 tools/lib/thermal/sampling.c
create mode 100644 tools/lib/thermal/thermal.c
create mode 100644 tools/lib/thermal/thermal_nl.c
create mode 100644 tools/lib/thermal/thermal_nl.h
create mode 100644 tools/thermal/lib/Build
create mode 100644 tools/thermal/lib/Makefile
create mode 100644 tools/thermal/lib/libthermal_tools.pc.template
create mode 100644 tools/thermal/lib/log.c
create mode 100644 tools/thermal/lib/log.h
create mode 100644 tools/thermal/lib/mainloop.c
create mode 100644 tools/thermal/lib/mainloop.h
create mode 100644 tools/thermal/lib/thermal-tools.h
create mode 100644 tools/thermal/lib/uptimeofday.c
create mode 100644 tools/thermal/lib/uptimeofday.h
create mode 100644 tools/thermal/thermal-engine/Build
create mode 100644 tools/thermal/thermal-engine/Makefile
create mode 100644 tools/thermal/thermal-engine/thermal-engine.c
create mode 100644 tools/thermal/thermometer/Build
create mode 100644 tools/thermal/thermometer/Makefile
create mode 100644 tools/thermal/thermometer/thermometer.c
create mode 100644 tools/thermal/thermometer/thermometer.conf
--
2.25.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v1 1/4] tools/lib/thermal: Add a thermal library
2022-02-18 12:53 [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
@ 2022-02-18 12:53 ` Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 2/4] tools/thermal: Add util library Daniel Lezcano
` (3 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Daniel Lezcano @ 2022-02-18 12:53 UTC (permalink / raw)
To: daniel.lezcano, rafael
Cc: srinivas.pandruvada, linux-kernel, linux-pm, Sasha Levin,
William Breathitt Gray, Jonathan Cameron
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.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
tools/Makefile | 14 +-
tools/lib/thermal/.gitignore | 2 +
tools/lib/thermal/Build | 5 +
tools/lib/thermal/Makefile | 165 +++++++++++
tools/lib/thermal/commands.c | 351 +++++++++++++++++++++++
tools/lib/thermal/events.c | 164 +++++++++++
tools/lib/thermal/include/thermal.h | 141 +++++++++
tools/lib/thermal/libthermal.map | 25 ++
tools/lib/thermal/libthermal.pc.template | 12 +
tools/lib/thermal/sampling.c | 75 +++++
tools/lib/thermal/thermal.c | 126 ++++++++
tools/lib/thermal/thermal_nl.c | 215 ++++++++++++++
tools/lib/thermal/thermal_nl.h | 46 +++
13 files changed, 1339 insertions(+), 2 deletions(-)
create mode 100644 tools/lib/thermal/.gitignore
create mode 100644 tools/lib/thermal/Build
create mode 100644 tools/lib/thermal/Makefile
create mode 100644 tools/lib/thermal/commands.c
create mode 100644 tools/lib/thermal/events.c
create mode 100644 tools/lib/thermal/include/thermal.h
create mode 100644 tools/lib/thermal/libthermal.map
create mode 100644 tools/lib/thermal/libthermal.pc.template
create mode 100644 tools/lib/thermal/sampling.c
create mode 100644 tools/lib/thermal/thermal.c
create mode 100644 tools/lib/thermal/thermal_nl.c
create mode 100644 tools/lib/thermal/thermal_nl.h
diff --git a/tools/Makefile b/tools/Makefile
index db2f7b8ebed5..c253cbd27c06 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -31,6 +31,7 @@ help:
@echo ' bootconfig - boot config tool'
@echo ' spi - spi tools'
@echo ' tmon - thermal monitoring and tuning tool'
+ @echo ' thermal - thermal library'
@echo ' tracing - misc tracing tools'
@echo ' turbostat - Intel CPU idle stats and freq reporting tool'
@echo ' usb - USB testing tools'
@@ -85,6 +86,9 @@ perf: FORCE
selftests: FORCE
$(call descend,testing/$@)
+thermal: FORCE
+ $(call descend,lib/$@)
+
turbostat x86_energy_perf_policy intel-speed-select: FORCE
$(call descend,power/x86/$@)
@@ -101,7 +105,7 @@ all: acpi cgroup counter cpupower gpio hv firewire \
perf selftests bootconfig spi turbostat usb \
virtio vm bpf x86_energy_perf_policy \
tmon freefall iio objtool kvm_stat wmi \
- pci debugging tracing
+ pci debugging tracing thermal
acpi_install:
$(call descend,power/$(@:_install=),install)
@@ -115,6 +119,9 @@ cgroup_install counter_install firewire_install gpio_install hv_install iio_inst
selftests_install:
$(call descend,testing/$(@:_install=),install)
+thermal_install:
+ $(call descend,lib/$(@:_install=),install)
+
turbostat_install x86_energy_perf_policy_install intel-speed-select_install:
$(call descend,power/x86/$(@:_install=),install)
@@ -160,6 +167,9 @@ perf_clean:
selftests_clean:
$(call descend,testing/$(@:_clean=),clean)
+thermal_clean:
+ $(call descend,lib/thermal,clean)
+
turbostat_clean x86_energy_perf_policy_clean intel-speed-select_clean:
$(call descend,power/x86/$(@:_clean=),clean)
@@ -177,6 +187,6 @@ clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_cl
vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean \
gpio_clean objtool_clean leds_clean wmi_clean pci_clean firmware_clean debugging_clean \
- intel-speed-select_clean tracing_clean
+ intel-speed-select_clean tracing_clean thermal_clean
.PHONY: FORCE
diff --git a/tools/lib/thermal/.gitignore b/tools/lib/thermal/.gitignore
new file mode 100644
index 000000000000..5d2aeda80fea
--- /dev/null
+++ b/tools/lib/thermal/.gitignore
@@ -0,0 +1,2 @@
+libthermal.so*
+libthermal.pc
diff --git a/tools/lib/thermal/Build b/tools/lib/thermal/Build
new file mode 100644
index 000000000000..4a892d9e24f9
--- /dev/null
+++ b/tools/lib/thermal/Build
@@ -0,0 +1,5 @@
+libthermal-y += commands.o
+libthermal-y += events.o
+libthermal-y += thermal_nl.o
+libthermal-y += sampling.o
+libthermal-y += thermal.o
diff --git a/tools/lib/thermal/Makefile b/tools/lib/thermal/Makefile
new file mode 100644
index 000000000000..606295e64440
--- /dev/null
+++ b/tools/lib/thermal/Makefile
@@ -0,0 +1,165 @@
+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+# Most of this file is copied from tools/lib/perf/Makefile
+
+LIBTHERMAL_VERSION = 0
+LIBTHERMAL_PATCHLEVEL = 0
+LIBTHERMAL_EXTRAVERSION = 1
+
+MAKEFLAGS += --no-print-directory
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+# $(info Determined 'srctree' to be $(srctree))
+endif
+
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+include $(srctree)/tools/scripts/Makefile.include
+include $(srctree)/tools/scripts/Makefile.arch
+
+ifeq ($(LP64), 1)
+ libdir_relative = lib64
+else
+ libdir_relative = lib
+endif
+
+prefix ?=
+libdir = $(prefix)/$(libdir_relative)
+
+# Shell quotes
+libdir_SQ = $(subst ','\'',$(libdir))
+libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
+
+ifeq ("$(origin V)", "command line")
+ VERBOSE = $(V)
+endif
+ifndef VERBOSE
+ VERBOSE = 0
+endif
+
+ifeq ($(VERBOSE),1)
+ Q =
+else
+ Q = @
+endif
+
+# Set compile option CFLAGS
+ifdef EXTRA_CFLAGS
+ CFLAGS := $(EXTRA_CFLAGS)
+else
+ CFLAGS := -g -Wall
+endif
+
+INCLUDES = \
+-I/usr/include/libnl3 \
+-I$(srctree)/tools/lib/thermal/include \
+-I$(srctree)/tools/lib/ \
+-I$(srctree)/tools/include \
+-I$(srctree)/tools/arch/$(SRCARCH)/include/ \
+-I$(srctree)/tools/arch/$(SRCARCH)/include/uapi \
+-I$(srctree)/tools/include/uapi
+
+# Append required CFLAGS
+override CFLAGS += $(EXTRA_WARNINGS)
+override CFLAGS += -Werror -Wall
+override CFLAGS += -fPIC
+override CFLAGS += $(INCLUDES)
+override CFLAGS += -fvisibility=hidden
+override CFGLAS += -Wl,-L.
+override CFGLAS += -Wl,-lthermal
+
+all:
+
+export srctree OUTPUT CC LD CFLAGS V
+export DESTDIR DESTDIR_SQ
+
+include $(srctree)/tools/build/Makefile.include
+
+VERSION_SCRIPT := libthermal.map
+
+PATCHLEVEL = $(LIBTHERMAL_PATCHLEVEL)
+EXTRAVERSION = $(LIBTHERMAL_EXTRAVERSION)
+VERSION = $(LIBTHERMAL_VERSION).$(LIBTHERMAL_PATCHLEVEL).$(LIBTHERMAL_EXTRAVERSION)
+
+LIBTHERMAL_SO := $(OUTPUT)libthermal.so.$(VERSION)
+LIBTHERMAL_A := $(OUTPUT)libthermal.a
+LIBTHERMAL_IN := $(OUTPUT)libthermal-in.o
+LIBTHERMAL_PC := $(OUTPUT)libthermal.pc
+LIBTHERMAL_ALL := $(LIBTHERMAL_A) $(OUTPUT)libthermal.so*
+
+THERMAL_UAPI := include/uapi/linux/thermal.h
+
+$(THERMAL_UAPI): FORCE
+ ln -sf $(srctree)/$@ $(srctree)/tools/$@
+
+$(LIBTHERMAL_IN): FORCE
+ $(Q)$(MAKE) $(build)=libthermal
+
+$(LIBTHERMAL_A): $(LIBTHERMAL_IN)
+ $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBTHERMAL_IN)
+
+$(LIBTHERMAL_SO): $(LIBTHERMAL_IN)
+ $(QUIET_LINK)$(CC) --shared -Wl,-soname,libthermal.so \
+ -Wl,--version-script=$(VERSION_SCRIPT) $^ -o $@
+ @ln -sf $(@F) $(OUTPUT)libthermal.so
+ @ln -sf $(@F) $(OUTPUT)libthermal.so.$(LIBTHERMAL_VERSION)
+
+
+libs: $(THERMAL_UAPI) $(LIBTHERMAL_A) $(LIBTHERMAL_SO) $(LIBTHERMAL_PC)
+
+all: fixdep
+ $(Q)$(MAKE) libs
+
+clean:
+ $(call QUIET_CLEAN, libthermal) $(RM) $(LIBTHERMAL_A) \
+ *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBTHERMAL_VERSION) .*.d .*.cmd LIBTHERMAL-CFLAGS $(LIBTHERMAL_PC)
+
+$(LIBTHERMAL_PC):
+ $(QUIET_GEN)sed -e "s|@PREFIX@|$(prefix)|" \
+ -e "s|@LIBDIR@|$(libdir_SQ)|" \
+ -e "s|@VERSION@|$(VERSION)|" \
+ < libthermal.pc.template > $@
+
+define do_install_mkdir
+ if [ ! -d '$(DESTDIR_SQ)$1' ]; then \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \
+ fi
+endef
+
+define do_install
+ if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
+ fi; \
+ $(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: libs
+ $(call QUIET_INSTALL, $(LIBTHERMAL_ALL)) \
+ $(call do_install_mkdir,$(libdir_SQ)); \
+ cp -fpR $(LIBTHERMAL_ALL) $(DESTDIR)$(libdir_SQ)
+
+install_headers:
+ $(call QUIET_INSTALL, headers) \
+ $(call do_install,include/thermal.h,$(prefix)/include/thermal,644); \
+
+install_pkgconfig: $(LIBTHERMAL_PC)
+ $(call QUIET_INSTALL, $(LIBTHERMAL_PC)) \
+ $(call do_install,$(LIBTHERMAL_PC),$(libdir_SQ)/pkgconfig,644)
+
+install_doc:
+ $(Q)$(MAKE) -C Documentation install-man install-html install-examples
+
+install: install_lib install_headers install_pkgconfig
+
+FORCE:
+
+.PHONY: all install clean FORCE
diff --git a/tools/lib/thermal/commands.c b/tools/lib/thermal/commands.c
new file mode 100644
index 000000000000..93283c1dff27
--- /dev/null
+++ b/tools/lib/thermal/commands.c
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#define _GNU_SOURCE
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <thermal.h>
+#include "thermal_nl.h"
+
+static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = {
+ /* Thermal zone */
+ [THERMAL_GENL_ATTR_TZ] = { .type = NLA_NESTED },
+ [THERMAL_GENL_ATTR_TZ_ID] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_TZ_TEMP] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_TZ_TRIP] = { .type = NLA_NESTED },
+ [THERMAL_GENL_ATTR_TZ_TRIP_ID] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_TZ_TRIP_TEMP] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_TZ_TRIP_TYPE] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_TZ_TRIP_HYST] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_TZ_MODE] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_TZ_NAME] = { .type = NLA_STRING },
+
+ /* Governor(s) */
+ [THERMAL_GENL_ATTR_TZ_GOV] = { .type = NLA_NESTED },
+ [THERMAL_GENL_ATTR_TZ_GOV_NAME] = { .type = NLA_STRING },
+
+ /* Cooling devices */
+ [THERMAL_GENL_ATTR_CDEV] = { .type = NLA_NESTED },
+ [THERMAL_GENL_ATTR_CDEV_ID] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_CDEV_CUR_STATE] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_CDEV_MAX_STATE] = { .type = NLA_U32 },
+ [THERMAL_GENL_ATTR_CDEV_NAME] = { .type = NLA_STRING },
+};
+
+static int parse_tz_get(struct genl_info *info, struct thermal_zone **tz)
+{
+ struct nlattr *attr;
+ struct thermal_zone *__tz = NULL;
+ size_t size = 0;
+ int rem;
+
+ nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_TZ], rem) {
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_ID) {
+
+ size++;
+
+ __tz = realloc(__tz, sizeof(*__tz) * (size + 2));
+ if (!__tz)
+ return THERMAL_ERROR;
+
+ __tz[size - 1].id = nla_get_u32(attr);
+ }
+
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_NAME)
+ nla_strlcpy(__tz[size - 1].name, attr,
+ THERMAL_NAME_LENGTH);
+ }
+
+ /*
+ * We end the array of thermal zones
+ */
+ __tz[size].id = -1;
+
+ *tz = __tz;
+
+ return THERMAL_SUCCESS;
+}
+
+static int parse_cdev_get(struct genl_info *info, struct thermal_cdev **cdev)
+{
+ struct nlattr *attr;
+ struct thermal_cdev *__cdev = NULL;
+ size_t size = 0;
+ int rem;
+
+ nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_CDEV], rem) {
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_ID) {
+
+ size++;
+
+ __cdev = realloc(__cdev, sizeof(*__cdev) * (size + 2));
+ if (!__cdev)
+ return THERMAL_ERROR;
+
+ __cdev[size - 1].id = nla_get_u32(attr);
+ }
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_NAME) {
+ nla_strlcpy(__cdev[size - 1].name, attr,
+ THERMAL_NAME_LENGTH);
+ }
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_CUR_STATE) {
+ __cdev[size - 1].cur_state = nla_get_u32(attr);
+ }
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_MAX_STATE) {
+ __cdev[size - 1].max_state = nla_get_u32(attr);
+ }
+ }
+
+ __cdev[size].id = -1;
+
+ *cdev = __cdev;
+
+ return THERMAL_SUCCESS;
+}
+
+static int parse_tz_get_trip(struct genl_info *info, struct thermal_zone *tz)
+{
+ struct nlattr *attr;
+ struct thermal_trip *__tt = NULL;
+ size_t size = 0;
+ int rem;
+
+ nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_TZ_TRIP], rem) {
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_ID) {
+
+ size++;
+
+ __tt = realloc(__tt, sizeof(*__tt) * (size + 2));
+ if (!__tt)
+ return THERMAL_ERROR;
+
+ __tt[size - 1].id = nla_get_u32(attr);
+ }
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_TYPE)
+ __tt[size - 1].type = nla_get_u32(attr);
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_TEMP)
+ __tt[size - 1].temp = nla_get_u32(attr);
+
+ if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_HYST)
+ __tt[size - 1].hyst = nla_get_u32(attr);
+ }
+
+ __tt[size].id = -1;
+
+ tz->trip = __tt;
+
+ return THERMAL_SUCCESS;
+}
+
+static int parse_tz_get_temp(struct genl_info *info, struct thermal_zone *tz)
+{
+ int id = -1;
+
+ if (info->attrs[THERMAL_GENL_ATTR_TZ_ID])
+ id = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_ID]);
+
+ if (tz->id != id)
+ return THERMAL_ERROR;
+
+ if (info->attrs[THERMAL_GENL_ATTR_TZ_TEMP])
+ tz->temp = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_TEMP]);
+
+ return THERMAL_SUCCESS;
+}
+
+static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz)
+{
+ int id = -1;
+
+ if (info->attrs[THERMAL_GENL_ATTR_TZ_ID])
+ id = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_ID]);
+
+ if (tz->id != id)
+ return THERMAL_ERROR;
+
+ if (info->attrs[THERMAL_GENL_ATTR_TZ_GOV_NAME]) {
+ nla_strlcpy(tz->governor,
+ info->attrs[THERMAL_GENL_ATTR_TZ_GOV_NAME],
+ THERMAL_NAME_LENGTH);
+ }
+
+ return THERMAL_SUCCESS;
+}
+
+static int handle_netlink(struct nl_cache_ops *unused,
+ struct genl_cmd *cmd,
+ struct genl_info *info, void *arg)
+{
+ int ret;
+
+ switch (cmd->c_id) {
+
+ case THERMAL_GENL_CMD_TZ_GET_ID:
+ ret = parse_tz_get(info, arg);
+ break;
+
+ case THERMAL_GENL_CMD_CDEV_GET:
+ ret = parse_cdev_get(info, arg);
+ break;
+
+ case THERMAL_GENL_CMD_TZ_GET_TEMP:
+ ret = parse_tz_get_temp(info, arg);
+ break;
+
+ case THERMAL_GENL_CMD_TZ_GET_TRIP:
+ ret = parse_tz_get_trip(info, arg);
+ break;
+
+ case THERMAL_GENL_CMD_TZ_GET_GOV:
+ ret = parse_tz_get_gov(info, arg);
+ break;
+
+ default:
+ return THERMAL_ERROR;
+ };
+
+ return ret;
+}
+
+static struct genl_cmd thermal_cmds[] = {
+ {
+ .c_id = THERMAL_GENL_CMD_TZ_GET_ID,
+ .c_name = (char *)"List thermal zones",
+ .c_msg_parser = handle_netlink,
+ .c_maxattr = THERMAL_GENL_ATTR_MAX,
+ .c_attr_policy = thermal_genl_policy,
+ },
+ {
+ .c_id = THERMAL_GENL_CMD_TZ_GET_GOV,
+ .c_name = (char *)"Get governor",
+ .c_msg_parser = handle_netlink,
+ .c_maxattr = THERMAL_GENL_ATTR_MAX,
+ .c_attr_policy = thermal_genl_policy,
+ },
+ {
+ .c_id = THERMAL_GENL_CMD_TZ_GET_TEMP,
+ .c_name = (char *)"Get thermal zone temperature",
+ .c_msg_parser = handle_netlink,
+ .c_maxattr = THERMAL_GENL_ATTR_MAX,
+ .c_attr_policy = thermal_genl_policy,
+ },
+ {
+ .c_id = THERMAL_GENL_CMD_TZ_GET_TRIP,
+ .c_name = (char *)"Get thermal zone trip points",
+ .c_msg_parser = handle_netlink,
+ .c_maxattr = THERMAL_GENL_ATTR_MAX,
+ .c_attr_policy = thermal_genl_policy,
+ },
+ {
+ .c_id = THERMAL_GENL_CMD_CDEV_GET,
+ .c_name = (char *)"Get cooling devices",
+ .c_msg_parser = handle_netlink,
+ .c_maxattr = THERMAL_GENL_ATTR_MAX,
+ .c_attr_policy = thermal_genl_policy,
+ },
+};
+
+static struct genl_ops thermal_cmd_ops = {
+ .o_name = (char *)"thermal",
+ .o_cmds = thermal_cmds,
+ .o_ncmds = ARRAY_SIZE(thermal_cmds),
+};
+
+static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int cmd,
+ int flags, void *arg)
+{
+ struct nl_msg *msg;
+ void *hdr;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return THERMAL_ERROR;
+
+ hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, thermal_cmd_ops.o_id,
+ 0, flags, cmd, THERMAL_GENL_VERSION);
+ if (!hdr)
+ return THERMAL_ERROR;
+
+ if (id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id))
+ return THERMAL_ERROR;
+
+ if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg))
+ return THERMAL_ERROR;
+
+ nlmsg_free(msg);
+
+ return THERMAL_SUCCESS;
+}
+
+thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz)
+{
+ return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_TZ_GET_ID,
+ NLM_F_DUMP | NLM_F_ACK, tz);
+}
+
+thermal_error_t thermal_cmd_get_cdev(struct thermal_handler *th, struct thermal_cdev **tc)
+{
+ return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_CDEV_GET,
+ NLM_F_DUMP | NLM_F_ACK, tc);
+}
+
+thermal_error_t thermal_cmd_get_trip(struct thermal_handler *th, struct thermal_zone *tz)
+{
+ return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TRIP,
+ 0, tz);
+}
+
+thermal_error_t thermal_cmd_get_governor(struct thermal_handler *th, struct thermal_zone *tz)
+{
+ return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz);
+}
+
+thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz)
+{
+ return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz);
+}
+
+thermal_error_t thermal_cmd_exit(struct thermal_handler *th)
+{
+ if (genl_unregister_family(&thermal_cmd_ops))
+ return THERMAL_ERROR;
+
+ nl_thermal_disconnect(th->sk_cmd, th->cb_cmd);
+
+ return THERMAL_SUCCESS;
+}
+
+thermal_error_t thermal_cmd_init(struct thermal_handler *th)
+{
+ int ret;
+ int family;
+
+ if (nl_thermal_connect(&th->sk_cmd, &th->cb_cmd))
+ return THERMAL_ERROR;
+
+ ret = genl_register_family(&thermal_cmd_ops);
+ if (ret)
+ return THERMAL_ERROR;
+
+ ret = genl_ops_resolve(th->sk_cmd, &thermal_cmd_ops);
+ if (ret)
+ return THERMAL_ERROR;
+
+ family = genl_ctrl_resolve(th->sk_cmd, "nlctrl");
+ if (family != GENL_ID_CTRL)
+ return THERMAL_ERROR;
+
+ return THERMAL_SUCCESS;
+}
diff --git a/tools/lib/thermal/events.c b/tools/lib/thermal/events.c
new file mode 100644
index 000000000000..84960642ca33
--- /dev/null
+++ b/tools/lib/thermal/events.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#include <linux/netlink.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#include <thermal.h>
+#include "thermal_nl.h"
+
+/*
+ * Optimization: fill this array to tell which event we do want to pay
+ * attention to. That happens at init time with the ops
+ * structure. Each ops will enable the event and the general handler
+ * will be able to discard the event if there is not ops associated
+ * with it.
+ */
+static int enabled_ops[__THERMAL_GENL_EVENT_MAX];
+
+static int handle_thermal_event(struct nl_msg *n, void *arg)
+{
+ struct nlmsghdr *nlh = nlmsg_hdr(n);
+ struct genlmsghdr *genlhdr = genlmsg_hdr(nlh);
+ struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
+ struct thermal_handler_param *thp = arg;
+ struct thermal_events_ops *ops = &thp->th->ops->events;
+
+ genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
+
+ arg = thp->arg;
+
+ /*
+ * This is an event we don't care of, bail out.
+ */
+ if (!enabled_ops[genlhdr->cmd])
+ return THERMAL_SUCCESS;
+
+ switch (genlhdr->cmd) {
+
+ case THERMAL_GENL_EVENT_TZ_CREATE:
+ return ops->tz_create(nla_get_string(attrs[THERMAL_GENL_ATTR_TZ_NAME]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_DELETE:
+ return ops->tz_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_ENABLE:
+ return ops->tz_enable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_DISABLE:
+ return ops->tz_disable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_TRIP_CHANGE:
+ return ops->trip_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_TRIP_ADD:
+ return ops->trip_add(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_TRIP_DELETE:
+ return ops->trip_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_TRIP_UP:
+ return ops->trip_high(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_TRIP_DOWN:
+ return ops->trip_low(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
+
+ case THERMAL_GENL_EVENT_CDEV_ADD:
+ return ops->cdev_add(nla_get_string(attrs[THERMAL_GENL_ATTR_CDEV_NAME]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE]), arg);
+
+ case THERMAL_GENL_EVENT_CDEV_DELETE:
+ return ops->cdev_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]), arg);
+
+ case THERMAL_GENL_EVENT_CDEV_STATE_UPDATE:
+ return ops->cdev_update(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE]), arg);
+
+ case THERMAL_GENL_EVENT_TZ_GOV_CHANGE:
+ return ops->gov_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
+ nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]), arg);
+ default:
+ return -1;
+ }
+}
+
+static void thermal_events_ops_init(struct thermal_events_ops *ops)
+{
+ enabled_ops[THERMAL_GENL_EVENT_TZ_CREATE] = !!ops->tz_create;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_DELETE] = !!ops->tz_delete;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_DISABLE] = !!ops->tz_disable;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_ENABLE] = !!ops->tz_enable;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_UP] = !!ops->trip_high;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = !!ops->trip_low;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = !!ops->trip_change;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_ADD] = !!ops->trip_add;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = !!ops->trip_delete;
+ enabled_ops[THERMAL_GENL_EVENT_CDEV_ADD] = !!ops->cdev_add;
+ enabled_ops[THERMAL_GENL_EVENT_CDEV_DELETE] = !!ops->cdev_delete;
+ enabled_ops[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = !!ops->cdev_update;
+ enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = !!ops->gov_change;
+}
+
+thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg)
+{
+ struct thermal_handler_param thp = { .th = th, .arg = arg };
+
+ if (!th)
+ return THERMAL_ERROR;
+
+ if (nl_cb_set(th->cb_event, NL_CB_VALID, NL_CB_CUSTOM,
+ handle_thermal_event, &thp))
+ return THERMAL_ERROR;
+
+ return nl_recvmsgs(th->sk_event, th->cb_event);
+}
+
+int thermal_events_fd(struct thermal_handler *th)
+{
+ if (!th)
+ return -1;
+
+ return nl_socket_get_fd(th->sk_event);
+}
+
+thermal_error_t thermal_events_exit(struct thermal_handler *th)
+{
+ if (nl_unsubscribe_thermal(th->sk_event, th->cb_event,
+ THERMAL_GENL_EVENT_GROUP_NAME))
+ return THERMAL_ERROR;
+
+ nl_thermal_disconnect(th->sk_event, th->cb_event);
+
+ return THERMAL_SUCCESS;
+}
+
+thermal_error_t thermal_events_init(struct thermal_handler *th)
+{
+ thermal_events_ops_init(&th->ops->events);
+
+ if (nl_thermal_connect(&th->sk_event, &th->cb_event))
+ return THERMAL_ERROR;
+
+ if (nl_subscribe_thermal(th->sk_event, th->cb_event,
+ THERMAL_GENL_EVENT_GROUP_NAME))
+ return THERMAL_ERROR;
+
+ return THERMAL_SUCCESS;
+}
diff --git a/tools/lib/thermal/include/thermal.h b/tools/lib/thermal/include/thermal.h
new file mode 100644
index 000000000000..4fdcdf09ffad
--- /dev/null
+++ b/tools/lib/thermal/include/thermal.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/* Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org> */
+#ifndef __LIBTHERMAL_H
+#define __LIBTHERMAL_H
+
+#include <linux/thermal.h>
+
+#ifndef LIBTHERMAL_API
+#define LIBTHERMAL_API __attribute__((visibility("default")))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct thermal_sampling_ops {
+ int (*tz_temp)(int tz_id, int temp, void *arg);
+};
+
+struct thermal_events_ops {
+ int (*tz_create)(const char *name, int tz_id, void *arg);
+ int (*tz_delete)(int tz_id, void *arg);
+ int (*tz_enable)(int tz_id, void *arg);
+ int (*tz_disable)(int tz_id, void *arg);
+ int (*trip_high)(int tz_id, int trip_id, int temp, void *arg);
+ int (*trip_low)(int tz_id, int trip_id, int temp, void *arg);
+ int (*trip_add)(int tz_id, int trip_id, int type, int temp, int hyst, void *arg);
+ int (*trip_change)(int tz_id, int trip_id, int type, int temp, int hyst, void *arg);
+ int (*trip_delete)(int tz_id, int trip_id, void *arg);
+ int (*cdev_add)(const char *name, int cdev_id, int max_state, void *arg);
+ int (*cdev_delete)(int cdev_id, void *arg);
+ int (*cdev_update)(int cdev_id, int cur_state, void *arg);
+ int (*gov_change)(int tz_id, const char *gov_name, void *arg);
+};
+
+struct thermal_ops {
+ struct thermal_sampling_ops sampling;
+ struct thermal_events_ops events;
+};
+
+struct thermal_trip {
+ int id;
+ int type;
+ int temp;
+ int hyst;
+};
+
+struct thermal_zone {
+ int id;
+ int temp;
+ char name[THERMAL_NAME_LENGTH];
+ char governor[THERMAL_NAME_LENGTH];
+ struct thermal_trip *trip;
+};
+
+struct thermal_cdev {
+ int id;
+ char name[THERMAL_NAME_LENGTH];
+ int max_state;
+ int min_state;
+ int cur_state;
+};
+
+typedef enum {
+ THERMAL_ERROR = -1,
+ THERMAL_SUCCESS = 0,
+} thermal_error_t;
+
+struct thermal_handler;
+
+typedef int (*cb_tz_t)(struct thermal_zone *, void *);
+
+typedef int (*cb_tt_t)(struct thermal_trip *, void *);
+
+typedef int (*cb_tc_t)(struct thermal_cdev *, void *);
+
+LIBTHERMAL_API int for_each_thermal_zone(struct thermal_zone *tz, cb_tz_t cb, void *arg);
+
+LIBTHERMAL_API int for_each_thermal_trip(struct thermal_trip *tt, cb_tt_t cb, void *arg);
+
+LIBTHERMAL_API int for_each_thermal_cdev(struct thermal_cdev *cdev, cb_tc_t cb, void *arg);
+
+LIBTHERMAL_API struct thermal_zone *thermal_zone_find_by_name(struct thermal_zone *tz,
+ const char *name);
+
+LIBTHERMAL_API struct thermal_zone *thermal_zone_find_by_id(struct thermal_zone *tz, int id);
+
+LIBTHERMAL_API struct thermal_zone *thermal_zone_discover(struct thermal_handler *th);
+
+LIBTHERMAL_API struct thermal_handler *thermal_init(struct thermal_ops *ops);
+
+LIBTHERMAL_API void thermal_exit(struct thermal_handler *th);
+
+/*
+ * Netlink thermal events
+ */
+LIBTHERMAL_API thermal_error_t thermal_events_exit(struct thermal_handler *th);
+
+LIBTHERMAL_API thermal_error_t thermal_events_init(struct thermal_handler *th);
+
+LIBTHERMAL_API thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg);
+
+LIBTHERMAL_API int thermal_events_fd(struct thermal_handler *th);
+
+/*
+ * Netlink thermal commands
+ */
+LIBTHERMAL_API thermal_error_t thermal_cmd_exit(struct thermal_handler *th);
+
+LIBTHERMAL_API thermal_error_t thermal_cmd_init(struct thermal_handler *th);
+
+LIBTHERMAL_API thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th,
+ struct thermal_zone **tz);
+
+LIBTHERMAL_API thermal_error_t thermal_cmd_get_cdev(struct thermal_handler *th,
+ struct thermal_cdev **tc);
+
+LIBTHERMAL_API thermal_error_t thermal_cmd_get_trip(struct thermal_handler *th,
+ struct thermal_zone *tz);
+
+LIBTHERMAL_API thermal_error_t thermal_cmd_get_governor(struct thermal_handler *th,
+ struct thermal_zone *tz);
+
+LIBTHERMAL_API thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz);
+
+/*
+ * Netlink thermal samples
+ */
+LIBTHERMAL_API thermal_error_t thermal_sampling_exit(struct thermal_handler *th);
+
+LIBTHERMAL_API thermal_error_t thermal_sampling_init(struct thermal_handler *th);
+
+LIBTHERMAL_API thermal_error_t thermal_sampling_handle(struct thermal_handler *th, void *arg);
+
+LIBTHERMAL_API int thermal_sampling_fd(struct thermal_handler *th);
+
+#endif /* __LIBTHERMAL_H */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tools/lib/thermal/libthermal.map b/tools/lib/thermal/libthermal.map
new file mode 100644
index 000000000000..d5e77738c7a4
--- /dev/null
+++ b/tools/lib/thermal/libthermal.map
@@ -0,0 +1,25 @@
+LIBTHERMAL_0.0.1 {
+ global:
+ thermal_init;
+ for_each_thermal_zone;
+ for_each_thermal_trip;
+ for_each_thermal_cdev;
+ thermal_zone_find_by_name;
+ thermal_zone_find_by_id;
+ thermal_zone_discover;
+ thermal_init;
+ thermal_events_init;
+ thermal_events_handle;
+ thermal_events_fd;
+ thermal_cmd_init;
+ thermal_cmd_get_tz;
+ thermal_cmd_get_cdev;
+ thermal_cmd_get_trip;
+ thermal_cmd_get_governor;
+ thermal_cmd_get_temp;
+ thermal_sampling_init;
+ thermal_sampling_handle;
+ thermal_sampling_fd;
+local:
+ *;
+};
diff --git a/tools/lib/thermal/libthermal.pc.template b/tools/lib/thermal/libthermal.pc.template
new file mode 100644
index 000000000000..6f3769731b59
--- /dev/null
+++ b/tools/lib/thermal/libthermal.pc.template
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+
+prefix=@PREFIX@
+libdir=@LIBDIR@
+includedir=${prefix}/include
+
+Name: libthermal
+Description: thermal library
+Requires: libnl-3.0 libnl-genl-3.0
+Version: @VERSION@
+Libs: -L${libdir} -lnl-genl-3 -lnl-3
+Cflags: -I${includedir} -I{include}/libnl3
diff --git a/tools/lib/thermal/sampling.c b/tools/lib/thermal/sampling.c
new file mode 100644
index 000000000000..ee818f4e9654
--- /dev/null
+++ b/tools/lib/thermal/sampling.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <thermal.h>
+#include "thermal_nl.h"
+
+static int handle_thermal_sample(struct nl_msg *n, void *arg)
+{
+ struct nlmsghdr *nlh = nlmsg_hdr(n);
+ struct genlmsghdr *genlhdr = genlmsg_hdr(nlh);
+ struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
+ struct thermal_handler_param *thp = arg;
+ struct thermal_handler *th = thp->th;
+
+ genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
+
+ switch (genlhdr->cmd) {
+
+ case THERMAL_GENL_SAMPLING_TEMP:
+ return th->ops->sampling.tz_temp(
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
+ nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
+ default:
+ return THERMAL_ERROR;
+ }
+}
+
+thermal_error_t thermal_sampling_handle(struct thermal_handler *th, void *arg)
+{
+ struct thermal_handler_param thp = { .th = th, .arg = arg };
+
+ if (!th)
+ return THERMAL_ERROR;
+
+ if (nl_cb_set(th->cb_sampling, NL_CB_VALID, NL_CB_CUSTOM,
+ handle_thermal_sample, &thp))
+ return THERMAL_ERROR;
+
+ return nl_recvmsgs(th->sk_sampling, th->cb_sampling);
+}
+
+int thermal_sampling_fd(struct thermal_handler *th)
+{
+ if (!th)
+ return -1;
+
+ return nl_socket_get_fd(th->sk_sampling);
+}
+
+thermal_error_t thermal_sampling_exit(struct thermal_handler *th)
+{
+ if (nl_unsubscribe_thermal(th->sk_sampling, th->cb_sampling,
+ THERMAL_GENL_EVENT_GROUP_NAME))
+ return THERMAL_ERROR;
+
+ nl_thermal_disconnect(th->sk_sampling, th->cb_sampling);
+
+ return THERMAL_SUCCESS;
+}
+
+thermal_error_t thermal_sampling_init(struct thermal_handler *th)
+{
+ if (nl_thermal_connect(&th->sk_sampling, &th->cb_sampling))
+ return THERMAL_ERROR;
+
+ if (nl_subscribe_thermal(th->sk_sampling, th->cb_sampling,
+ THERMAL_GENL_SAMPLING_GROUP_NAME))
+ return THERMAL_ERROR;
+
+ return THERMAL_SUCCESS;
+}
diff --git a/tools/lib/thermal/thermal.c b/tools/lib/thermal/thermal.c
new file mode 100644
index 000000000000..419bb343da4e
--- /dev/null
+++ b/tools/lib/thermal/thermal.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#include <stdio.h>
+#include <thermal.h>
+
+#include "thermal_nl.h"
+
+int for_each_thermal_cdev(struct thermal_cdev *cdev, cb_tc_t cb, void *arg)
+{
+ int i, ret = 0;
+
+ for (i = 0; cdev[i].id != -1; i++)
+ ret |= cb(&cdev[i], arg);
+
+ return ret;
+}
+
+int for_each_thermal_trip(struct thermal_trip *tt, cb_tt_t cb, void *arg)
+{
+ int i, ret = 0;
+
+ for (i = 0; tt[i].id != -1; i++)
+ ret |= cb(&tt[i], arg);
+
+ return ret;
+}
+
+int for_each_thermal_zone(struct thermal_zone *tz, cb_tz_t cb, void *arg)
+{
+ int i, ret = 0;
+
+ for (i = 0; tz[i].id != -1; i++)
+ ret |= cb(&tz[i], arg);
+
+ return ret;
+}
+
+struct thermal_zone *thermal_zone_find_by_name(struct thermal_zone *tz,
+ const char *name)
+{
+ int i;
+
+ if (!name)
+ return NULL;
+
+ for (i = 0; tz[i].id != -1; i++) {
+ if (!strcmp(tz[i].name, name))
+ return &tz[i];
+ }
+
+ return NULL;
+}
+
+struct thermal_zone *thermal_zone_find_by_id(struct thermal_zone *tz, int id)
+{
+ int i;
+
+ if (id < 0)
+ return NULL;
+
+ for (i = 0; tz[i].id != -1; i++) {
+ if (tz[i].id == id)
+ return &tz[i];
+ }
+
+ return NULL;
+}
+
+static int __thermal_zone_discover(struct thermal_zone *tz, void *th)
+{
+ if (thermal_cmd_get_trip(th, tz) < 0)
+ return -1;
+
+ if (thermal_cmd_get_governor(th, tz))
+ return -1;
+
+ return 0;
+}
+
+struct thermal_zone *thermal_zone_discover(struct thermal_handler *th)
+{
+ struct thermal_zone *tz;
+
+ if (thermal_cmd_get_tz(th, &tz) < 0)
+ return NULL;
+
+ if (for_each_thermal_zone(tz, __thermal_zone_discover, th))
+ return NULL;
+
+ return tz;
+}
+
+void thermal_exit(struct thermal_handler *th)
+{
+ thermal_cmd_exit(th);
+ thermal_events_exit(th);
+ thermal_sampling_exit(th);
+
+ free(th);
+}
+
+struct thermal_handler *thermal_init(struct thermal_ops *ops)
+{
+ struct thermal_handler *th;
+
+ th = malloc(sizeof(*th));
+ if (!th)
+ return NULL;
+ th->ops = ops;
+
+ if (thermal_events_init(th))
+ goto out_free;
+
+ if (thermal_sampling_init(th))
+ goto out_free;
+
+ if (thermal_cmd_init(th))
+ goto out_free;
+
+ return th;
+
+out_free:
+ free(th);
+
+ return NULL;
+}
diff --git a/tools/lib/thermal/thermal_nl.c b/tools/lib/thermal/thermal_nl.c
new file mode 100644
index 000000000000..a079334a6b61
--- /dev/null
+++ b/tools/lib/thermal/thermal_nl.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <thermal.h>
+#include "thermal_nl.h"
+
+struct handler_args {
+ const char *group;
+ int id;
+};
+
+static __thread int err;
+static __thread int done;
+
+static int nl_seq_check_handler(struct nl_msg *msg, void *arg)
+{
+ return NL_OK;
+}
+
+static int nl_error_handler(struct sockaddr_nl *nla, struct nlmsgerr *nl_err,
+ void *arg)
+{
+ int *ret = arg;
+
+ if (ret)
+ *ret = nl_err->error;
+
+ return NL_STOP;
+}
+
+static int nl_finish_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+
+ if (ret)
+ *ret = 1;
+
+ return NL_OK;
+}
+
+static int nl_ack_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+
+ if (ret)
+ *ret = 1;
+
+ return NL_OK;
+}
+
+int nl_send_msg(struct nl_sock *sock, struct nl_cb *cb, struct nl_msg *msg,
+ int (*rx_handler)(struct nl_msg *, void *), void *data)
+{
+ if (!rx_handler)
+ return THERMAL_ERROR;
+
+ err = nl_send_auto_complete(sock, msg);
+ if (err < 0)
+ return err;
+
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, rx_handler, data);
+
+ err = done = 0;
+
+ while (err == 0 && done == 0)
+ nl_recvmsgs(sock, cb);
+
+ return err;
+}
+
+static int nl_family_handler(struct nl_msg *msg, void *arg)
+{
+ struct handler_args *grp = arg;
+ struct nlattr *tb[CTRL_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *mcgrp;
+ int rem_mcgrp;
+
+ nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!tb[CTRL_ATTR_MCAST_GROUPS])
+ return THERMAL_ERROR;
+
+ nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) {
+
+ struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
+
+ nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
+ nla_data(mcgrp), nla_len(mcgrp), NULL);
+
+ if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] ||
+ !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
+ continue;
+
+ if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
+ grp->group,
+ nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])))
+ continue;
+
+ grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
+
+ break;
+ }
+
+ return THERMAL_SUCCESS;
+}
+
+static int nl_get_multicast_id(struct nl_sock *sock, struct nl_cb *cb,
+ const char *family, const char *group)
+{
+ struct nl_msg *msg;
+ int ret = 0, ctrlid;
+ struct handler_args grp = {
+ .group = group,
+ .id = -ENOENT,
+ };
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return THERMAL_ERROR;
+
+ ctrlid = genl_ctrl_resolve(sock, "nlctrl");
+
+ genlmsg_put(msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
+
+ nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family);
+
+ ret = nl_send_msg(sock, cb, msg, nl_family_handler, &grp);
+ if (ret)
+ goto nla_put_failure;
+
+ ret = grp.id;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+}
+
+int nl_thermal_connect(struct nl_sock **nl_sock, struct nl_cb **nl_cb)
+{
+ struct nl_cb *cb;
+ struct nl_sock *sock;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ return THERMAL_ERROR;
+
+ sock = nl_socket_alloc();
+ if (!sock)
+ goto out_cb_free;
+
+ if (genl_connect(sock))
+ goto out_socket_free;
+
+ if (nl_cb_err(cb, NL_CB_CUSTOM, nl_error_handler, &err) ||
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl_finish_handler, &done) ||
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl_ack_handler, &done) ||
+ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nl_seq_check_handler, &done))
+ return THERMAL_ERROR;
+
+ *nl_sock = sock;
+ *nl_cb = cb;
+
+ return THERMAL_SUCCESS;
+
+out_socket_free:
+ nl_socket_free(sock);
+out_cb_free:
+ nl_cb_put(cb);
+ return THERMAL_ERROR;
+}
+
+void nl_thermal_disconnect(struct nl_sock *nl_sock, struct nl_cb *nl_cb)
+{
+ nl_close(nl_sock);
+ nl_socket_free(nl_sock);
+ nl_cb_put(nl_cb);
+}
+
+int nl_unsubscribe_thermal(struct nl_sock *nl_sock, struct nl_cb *nl_cb,
+ const char *group)
+{
+ int mcid;
+
+ mcid = nl_get_multicast_id(nl_sock, nl_cb, THERMAL_GENL_FAMILY_NAME,
+ group);
+ if (mcid < 0)
+ return THERMAL_ERROR;
+
+ if (nl_socket_drop_membership(nl_sock, mcid))
+ return THERMAL_ERROR;
+
+ return THERMAL_SUCCESS;
+}
+
+int nl_subscribe_thermal(struct nl_sock *nl_sock, struct nl_cb *nl_cb,
+ const char *group)
+{
+ int mcid;
+
+ mcid = nl_get_multicast_id(nl_sock, nl_cb, THERMAL_GENL_FAMILY_NAME,
+ group);
+ if (mcid < 0)
+ return THERMAL_ERROR;
+
+ if (nl_socket_add_membership(nl_sock, mcid))
+ return THERMAL_ERROR;
+
+ return THERMAL_SUCCESS;
+}
diff --git a/tools/lib/thermal/thermal_nl.h b/tools/lib/thermal/thermal_nl.h
new file mode 100644
index 000000000000..ddf635642f07
--- /dev/null
+++ b/tools/lib/thermal/thermal_nl.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/* Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org> */
+#ifndef __THERMAL_H
+#define __THERMAL_H
+
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/mngt.h>
+#include <netlink/genl/ctrl.h>
+
+struct thermal_handler {
+ int done;
+ int error;
+ struct thermal_ops *ops;
+ struct nl_msg *msg;
+ struct nl_sock *sk_event;
+ struct nl_sock *sk_sampling;
+ struct nl_sock *sk_cmd;
+ struct nl_cb *cb_cmd;
+ struct nl_cb *cb_event;
+ struct nl_cb *cb_sampling;
+};
+
+struct thermal_handler_param {
+ struct thermal_handler *th;
+ void *arg;
+};
+
+/*
+ * Low level netlink
+ */
+extern int nl_subscribe_thermal(struct nl_sock *nl_sock, struct nl_cb *nl_cb,
+ const char *group);
+
+extern int nl_unsubscribe_thermal(struct nl_sock *nl_sock, struct nl_cb *nl_cb,
+ const char *group);
+
+extern int nl_thermal_connect(struct nl_sock **nl_sock, struct nl_cb **nl_cb);
+
+extern void nl_thermal_disconnect(struct nl_sock *nl_sock, struct nl_cb *nl_cb);
+
+extern int nl_send_msg(struct nl_sock *sock, struct nl_cb *nl_cb, struct nl_msg *msg,
+ int (*rx_handler)(struct nl_msg *, void *),
+ void *data);
+
+#endif /* __THERMAL_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v1 2/4] tools/thermal: Add util library
2022-02-18 12:53 [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 1/4] tools/lib/thermal: Add a thermal library Daniel Lezcano
@ 2022-02-18 12:53 ` Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 3/4] tools/thermal: A temperature capture tool Daniel Lezcano
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Daniel Lezcano @ 2022-02-18 12:53 UTC (permalink / raw)
To: daniel.lezcano, rafael
Cc: srinivas.pandruvada, linux-kernel, linux-pm, Amit Kucheria, Zhang Rui
The next changes will provide a couple of tools using some common
functions provided by this library.
It provides basic wrappers for:
- mainloop
- logging
- timestamp
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
tools/thermal/lib/Build | 3 +
tools/thermal/lib/Makefile | 158 ++++++++++++++++++
.../thermal/lib/libthermal_tools.pc.template | 12 ++
tools/thermal/lib/log.c | 77 +++++++++
tools/thermal/lib/log.h | 31 ++++
tools/thermal/lib/mainloop.c | 135 +++++++++++++++
tools/thermal/lib/mainloop.h | 14 ++
tools/thermal/lib/thermal-tools.h | 10 ++
tools/thermal/lib/uptimeofday.c | 40 +++++
tools/thermal/lib/uptimeofday.h | 12 ++
10 files changed, 492 insertions(+)
create mode 100644 tools/thermal/lib/Build
create mode 100644 tools/thermal/lib/Makefile
create mode 100644 tools/thermal/lib/libthermal_tools.pc.template
create mode 100644 tools/thermal/lib/log.c
create mode 100644 tools/thermal/lib/log.h
create mode 100644 tools/thermal/lib/mainloop.c
create mode 100644 tools/thermal/lib/mainloop.h
create mode 100644 tools/thermal/lib/thermal-tools.h
create mode 100644 tools/thermal/lib/uptimeofday.c
create mode 100644 tools/thermal/lib/uptimeofday.h
diff --git a/tools/thermal/lib/Build b/tools/thermal/lib/Build
new file mode 100644
index 000000000000..06f22760a272
--- /dev/null
+++ b/tools/thermal/lib/Build
@@ -0,0 +1,3 @@
+libthermal_tools-y += mainloop.o
+libthermal_tools-y += log.o
+libthermal_tools-y += uptimeofday.o
diff --git a/tools/thermal/lib/Makefile b/tools/thermal/lib/Makefile
new file mode 100644
index 000000000000..bdf4659adfeb
--- /dev/null
+++ b/tools/thermal/lib/Makefile
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+# Most of this file is copied from tools/lib/perf/Makefile
+
+LIBTHERMAL_TOOLS_VERSION = 0
+LIBTHERMAL_TOOLS_PATCHLEVEL = 0
+LIBTHERMAL_TOOLS_EXTRAVERSION = 1
+
+MAKEFLAGS += --no-print-directory
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+# $(info Determined 'srctree' to be $(srctree))
+endif
+
+INSTALL = install
+
+# Use DESTDIR for installing into a different root directory.
+# This is useful for building a package. The program will be
+# installed in this directory as if it was the root directory.
+# Then the build tool can move it later.
+DESTDIR ?=
+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
+
+include $(srctree)/tools/scripts/Makefile.include
+include $(srctree)/tools/scripts/Makefile.arch
+
+ifeq ($(LP64), 1)
+ libdir_relative = lib64
+else
+ libdir_relative = lib
+endif
+
+prefix ?=
+libdir = $(prefix)/$(libdir_relative)
+
+# Shell quotes
+libdir_SQ = $(subst ','\'',$(libdir))
+libdir_relative_SQ = $(subst ','\'',$(libdir_relative))
+
+ifeq ("$(origin V)", "command line")
+ VERBOSE = $(V)
+endif
+ifndef VERBOSE
+ VERBOSE = 0
+endif
+
+ifeq ($(VERBOSE),1)
+ Q =
+else
+ Q = @
+endif
+
+# Set compile option CFLAGS
+ifdef EXTRA_CFLAGS
+ CFLAGS := $(EXTRA_CFLAGS)
+else
+ CFLAGS := -g -Wall
+endif
+
+INCLUDES = \
+-I/usr/include/libnl3 \
+-I$(srctree)/tools/lib/thermal/include \
+-I$(srctree)/tools/lib/ \
+-I$(srctree)/tools/include \
+-I$(srctree)/tools/arch/$(SRCARCH)/include/ \
+-I$(srctree)/tools/arch/$(SRCARCH)/include/uapi \
+-I$(srctree)/tools/include/uapi
+
+# Append required CFLAGS
+override CFLAGS += $(EXTRA_WARNINGS)
+override CFLAGS += -Werror -Wall
+override CFLAGS += -fPIC
+override CFLAGS += $(INCLUDES)
+override CFGLAS += -Wl,-L.
+override CFGLAS += -Wl,-lthermal
+
+all:
+
+export srctree OUTPUT CC LD CFLAGS V
+export DESTDIR DESTDIR_SQ
+
+include $(srctree)/tools/build/Makefile.include
+
+PATCHLEVEL = $(LIBTHERMAL_TOOLS_PATCHLEVEL)
+EXTRAVERSION = $(LIBTHERMAL_TOOLS_EXTRAVERSION)
+VERSION = $(LIBTHERMAL_TOOLS_VERSION).$(LIBTHERMAL_TOOLS_PATCHLEVEL).$(LIBTHERMAL_TOOLS_EXTRAVERSION)
+
+LIBTHERMAL_TOOLS_SO := $(OUTPUT)libthermal_tools.so.$(VERSION)
+LIBTHERMAL_TOOLS_A := $(OUTPUT)libthermal_tools.a
+LIBTHERMAL_TOOLS_IN := $(OUTPUT)libthermal_tools-in.o
+LIBTHERMAL_TOOLS_PC := $(OUTPUT)libthermal_tools.pc
+
+LIBTHERMAL_TOOLS_ALL := $(LIBTHERMAL_TOOLS_A) $(OUTPUT)libthermal_tools.so*
+
+$(LIBTHERMAL_TOOLS_IN): FORCE
+ $(Q)$(MAKE) $(build)=libthermal_tools
+
+$(LIBTHERMAL_TOOLS_A): $(LIBTHERMAL_TOOLS_IN)
+ $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBTHERMAL_TOOLS_IN)
+
+$(LIBTHERMAL_TOOLS_SO): $(LIBTHERMAL_TOOLS_IN)
+ $(QUIET_LINK)$(CC) --shared -Wl,-soname,libthermal_tools.so $^ -o $@
+ @ln -sf $(@F) $(OUTPUT)libthermal_tools.so
+ @ln -sf $(@F) $(OUTPUT)libthermal_tools.so.$(LIBTHERMAL_TOOLS_VERSION)
+
+
+libs: $(LIBTHERMAL_TOOLS_A) $(LIBTHERMAL_TOOLS_SO) $(LIBTHERMAL_TOOLS_PC)
+
+all: fixdep
+ $(Q)$(MAKE) libs
+
+clean:
+ $(call QUIET_CLEAN, libthermal_tools) $(RM) $(LIBTHERMAL_TOOLS_A) \
+ *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBTHERMAL_TOOLS_VERSION) .*.d .*.cmd LIBTHERMAL_TOOLS-CFLAGS $(LIBTHERMAL_TOOLS_PC)
+
+$(LIBTHERMAL_TOOLS_PC):
+ $(QUIET_GEN)sed -e "s|@PREFIX@|$(prefix)|" \
+ -e "s|@LIBDIR@|$(libdir_SQ)|" \
+ -e "s|@VERSION@|$(VERSION)|" \
+ < libthermal_tools.pc.template > $@
+
+define do_install_mkdir
+ if [ ! -d '$(DESTDIR_SQ)$1' ]; then \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$1'; \
+ fi
+endef
+
+define do_install
+ if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
+ fi; \
+ $(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR_SQ)$2'
+endef
+
+install_lib: libs
+ $(call QUIET_INSTALL, $(LIBTHERMAL_TOOLS_ALL)) \
+ $(call do_install_mkdir,$(libdir_SQ)); \
+ cp -fpR $(LIBTHERMAL_TOOLS_ALL) $(DESTDIR)$(libdir_SQ)
+
+install_headers:
+ $(call QUIET_INSTALL, headers) \
+ $(call do_install,include/thermal.h,$(prefix)/include/thermal,644); \
+
+install_pkgconfig: $(LIBTHERMAL_TOOLS_PC)
+ $(call QUIET_INSTALL, $(LIBTHERMAL_TOOLS_PC)) \
+ $(call do_install,$(LIBTHERMAL_TOOLS_PC),$(libdir_SQ)/pkgconfig,644)
+
+install_doc:
+ $(Q)$(MAKE) -C Documentation install-man install-html install-examples
+
+#install: install_lib install_headers install_pkgconfig install_doc
+install: install_lib install_headers install_pkgconfig
+
+FORCE:
+
+.PHONY: all install clean FORCE
diff --git a/tools/thermal/lib/libthermal_tools.pc.template b/tools/thermal/lib/libthermal_tools.pc.template
new file mode 100644
index 000000000000..6f3769731b59
--- /dev/null
+++ b/tools/thermal/lib/libthermal_tools.pc.template
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
+
+prefix=@PREFIX@
+libdir=@LIBDIR@
+includedir=${prefix}/include
+
+Name: libthermal
+Description: thermal library
+Requires: libnl-3.0 libnl-genl-3.0
+Version: @VERSION@
+Libs: -L${libdir} -lnl-genl-3 -lnl-3
+Cflags: -I${includedir} -I{include}/libnl3
diff --git a/tools/thermal/lib/log.c b/tools/thermal/lib/log.c
new file mode 100644
index 000000000000..620df5b3220f
--- /dev/null
+++ b/tools/thermal/lib/log.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include "log.h"
+
+static const char *__ident = "unknown";
+static int __options = 0;
+
+static const char *loglvl[] = {
+ [LOG_DEBUG] = "DEBUG",
+ [LOG_INFO] = "INFO",
+ [LOG_NOTICE] = "NOTICE",
+ [LOG_WARNING] = "WARN",
+ [LOG_ERR] = "ERROR",
+ [LOG_CRIT] = "CRITICAL",
+ [LOG_ALERT] = "ALERT",
+ [LOG_EMERG] = "EMERG",
+};
+
+int log_str2level(const char *lvl)
+{
+ int i;
+
+ for (i = 0; i < sizeof(loglvl) / sizeof(loglvl[LOG_DEBUG]); i++)
+ if (!strcmp(lvl, loglvl[i]))
+ return i;
+
+ return LOG_DEBUG;
+}
+
+extern void logit(int level, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+
+ if (__options & TO_SYSLOG)
+ vsyslog(level, format, args);
+
+ if (__options & TO_STDERR)
+ vfprintf(stderr, format, args);
+
+ if (__options & TO_STDOUT)
+ vfprintf(stdout, format, args);
+
+ va_end(args);
+}
+
+int log_init(int level, const char *ident, int options)
+{
+ if (!options)
+ return -1;
+
+ if (level > LOG_DEBUG)
+ return -1;
+
+ if (!ident)
+ return -1;
+
+ __ident = ident;
+ __options = options;
+
+ if (options & TO_SYSLOG) {
+ openlog(__ident, options | LOG_NDELAY, LOG_USER);
+ setlogmask(LOG_UPTO(level));
+ }
+
+ return 0;
+}
+
+void log_exit(void)
+{
+ closelog();
+}
diff --git a/tools/thermal/lib/log.h b/tools/thermal/lib/log.h
new file mode 100644
index 000000000000..9ee945e0af57
--- /dev/null
+++ b/tools/thermal/lib/log.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/* Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org> */
+#ifndef __THERMAL_TOOLS_LOG_H
+#define __THERMAL_TOOLS_LOG_H
+
+#include <syslog.h>
+
+#ifndef __maybe_unused
+#define __maybe_unused __attribute__((__unused__))
+#endif
+
+#define TO_SYSLOG 0x1
+#define TO_STDOUT 0x2
+#define TO_STDERR 0x4
+
+extern void logit(int level, const char *format, ...);
+
+#define DEBUG(fmt, ...) logit(LOG_DEBUG, "%s(%d): " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define INFO(fmt, ...) logit(LOG_INFO, fmt, ##__VA_ARGS__)
+#define NOTICE(fmt, ...) logit(LOG_NOTICE, fmt, ##__VA_ARGS__)
+#define WARN(fmt, ...) logit(LOG_WARNING, fmt, ##__VA_ARGS__)
+#define ERROR(fmt, ...) logit(LOG_ERR, fmt, ##__VA_ARGS__)
+#define CRITICAL(fmt, ...) logit(LOG_CRIT, fmt, ##__VA_ARGS__)
+#define ALERT(fmt, ...) logit(LOG_ALERT, fmt, ##__VA_ARGS__)
+#define EMERG(fmt, ...) logit(LOG_EMERG, fmt, ##__VA_ARGS__)
+
+int log_init(int level, const char *ident, int options);
+int log_str2level(const char *lvl);
+void log_exit(void);
+
+#endif
diff --git a/tools/thermal/lib/mainloop.c b/tools/thermal/lib/mainloop.c
new file mode 100644
index 000000000000..182a9533445b
--- /dev/null
+++ b/tools/thermal/lib/mainloop.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/epoll.h>
+#include "mainloop.h"
+#include "log.h"
+
+static int epfd = -1;
+static unsigned short nrhandler;
+static sig_atomic_t exit_mainloop = 0;
+
+struct mainloop_data {
+ mainloop_callback_t cb;
+ void *data;
+ int fd;
+};
+
+static struct mainloop_data **mds;
+
+#define MAX_EVENTS 10
+
+static void sig_exit(__maybe_unused int sig)
+{
+ exit_mainloop = 1;
+}
+
+int mainloop(unsigned int timeout)
+{
+ int i, nfds;
+ struct epoll_event events[MAX_EVENTS];
+ struct mainloop_data *md;
+
+ if (epfd < 0)
+ return -1;
+
+ for (;;) {
+
+ nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
+
+ if (exit_mainloop)
+ return 0;
+
+ if (nfds < 0) {
+ if (errno == EINTR)
+ continue;
+ return -1;
+ }
+
+ /*
+ * A timeout occured. Let's send to ourself a SIGWINCH
+ * so the window get refreshed automatically. No need
+ * to use exported functions and this code stay self
+ * contained.
+ */
+ if (!nfds) {
+ kill(getpid(), SIGWINCH);
+ continue;
+ }
+
+ for (i = 0; i < nfds; i++) {
+ md = events[i].data.ptr;
+
+ if (md->cb(md->fd, md->data) > 0)
+ return 0;
+ }
+
+ }
+}
+
+int mainloop_add(int fd, mainloop_callback_t cb, void *data)
+{
+ struct epoll_event ev = {
+ .events = EPOLLIN,
+ };
+
+ struct mainloop_data *md;
+
+ if (fd >= nrhandler) {
+ mds = realloc(mds, sizeof(*mds) * (fd + 1));
+ if (!mds)
+ return -1;
+ nrhandler = fd + 1;
+ }
+
+ md = malloc(sizeof(*md));
+ if (!md)
+ return -1;
+
+ md->data = data;
+ md->cb = cb;
+ md->fd = fd;
+
+ mds[fd] = md;
+ ev.data.ptr = md;
+
+ if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
+ free(md);
+ return -1;
+ }
+
+ return 0;
+}
+
+int mainloop_del(int fd)
+{
+ if (fd >= nrhandler)
+ return -1;
+
+ if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0)
+ return -1;
+
+ free(mds[fd]);
+
+ return 0;
+}
+
+int mainloop_init(void)
+{
+ epfd = epoll_create(2);
+ if (epfd < 0)
+ return -1;
+
+ signal(SIGINT, sig_exit);
+ signal(SIGTERM, sig_exit);
+
+ return 0;
+}
+
+void mainloop_fini(void)
+{
+ close(epfd);
+}
diff --git a/tools/thermal/lib/mainloop.h b/tools/thermal/lib/mainloop.h
new file mode 100644
index 000000000000..eb37977a83e7
--- /dev/null
+++ b/tools/thermal/lib/mainloop.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/* Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org> */
+#ifndef __THERMAL_TOOLS_MAINLOOP_H
+#define __THERMAL_TOOLS_MAINLOOP_H
+
+typedef int (*mainloop_callback_t)(int fd, void *data);
+
+extern int mainloop(unsigned int timeout);
+extern int mainloop_add(int fd, mainloop_callback_t cb, void *data);
+extern int mainloop_del(int fd);
+extern int mainloop_init(void);
+extern void mainloop_fini(void);
+
+#endif
diff --git a/tools/thermal/lib/thermal-tools.h b/tools/thermal/lib/thermal-tools.h
new file mode 100644
index 000000000000..f43939a468a3
--- /dev/null
+++ b/tools/thermal/lib/thermal-tools.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/* Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org> */
+#ifndef __THERMAL_TOOLS
+#define __THERMAL_TOOLS
+
+#include "log.h"
+#include "mainloop.h"
+#include "uptimeofday.h"
+
+#endif
diff --git a/tools/thermal/lib/uptimeofday.c b/tools/thermal/lib/uptimeofday.c
new file mode 100644
index 000000000000..7ccbb272debd
--- /dev/null
+++ b/tools/thermal/lib/uptimeofday.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: LGPL-2.1+
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#include <stdio.h>
+#include <sys/time.h>
+#include <linux/sysinfo.h>
+#include "thermal-tools.h"
+
+static unsigned long __offset;
+static struct timeval __tv;
+
+int uptimeofday_init(void)
+{
+ struct sysinfo info;
+
+ if (sysinfo(&info))
+ return -1;
+
+ gettimeofday(&__tv, NULL);
+
+ __offset = __tv.tv_sec - info.uptime;
+
+ return 0;
+}
+
+unsigned long getuptimeofday_ms(void)
+{
+ gettimeofday(&__tv, NULL);
+
+ return ((__tv.tv_sec - __offset) * 1000) + (__tv.tv_usec / 1000);
+}
+
+struct timespec msec_to_timespec(int msec)
+{
+ struct timespec tv = {
+ .tv_sec = (time_t)(msec / 1000),
+ .tv_nsec = (msec - tv.tv_sec) * 1000000,
+ };
+
+ return tv;
+}
diff --git a/tools/thermal/lib/uptimeofday.h b/tools/thermal/lib/uptimeofday.h
new file mode 100644
index 000000000000..c0da5de41325
--- /dev/null
+++ b/tools/thermal/lib/uptimeofday.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/* Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org> */
+#ifndef __THERMAL_TOOLS_UPTIMEOFDAY_H
+#define __THERMAL_TOOLS_UPTIMEOFDAY_H
+#include <sys/sysinfo.h>
+#include <sys/time.h>
+
+int uptimeofday_init(void);
+unsigned long getuptimeofday_ms(void);
+struct timespec msec_to_timespec(int msec);
+
+#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v1 3/4] tools/thermal: A temperature capture tool
2022-02-18 12:53 [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 1/4] tools/lib/thermal: Add a thermal library Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 2/4] tools/thermal: Add util library Daniel Lezcano
@ 2022-02-18 12:53 ` Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 4/4] tools/thermal: Add thermal daemon skeleton Daniel Lezcano
2022-02-24 21:41 ` [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
4 siblings, 0 replies; 10+ messages in thread
From: Daniel Lezcano @ 2022-02-18 12:53 UTC (permalink / raw)
To: daniel.lezcano, rafael
Cc: srinivas.pandruvada, linux-kernel, linux-pm, Amit Kucheria,
Zhang Rui, Jonathan Cameron, William Breathitt Gray, Sasha Levin
The 'thermometer' tool allows to capture the temperature of a set of
thermal zones defined in a configuration file at a specified rate.
It is designed to have the lowest possible overhead. It will write the
captured temperature per thermal zone per file so making easier to
write a gnuplot script.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
tools/Makefile | 16 +-
tools/thermal/thermometer/Build | 2 +
tools/thermal/thermometer/Makefile | 23 ++
tools/thermal/thermometer/thermometer.c | 393 +++++++++++++++++++++
tools/thermal/thermometer/thermometer.conf | 5 +
5 files changed, 436 insertions(+), 3 deletions(-)
create mode 100644 tools/thermal/thermometer/Build
create mode 100644 tools/thermal/thermometer/Makefile
create mode 100644 tools/thermal/thermometer/thermometer.c
create mode 100644 tools/thermal/thermometer/thermometer.conf
diff --git a/tools/Makefile b/tools/Makefile
index c253cbd27c06..78615f8cb463 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -31,6 +31,7 @@ help:
@echo ' bootconfig - boot config tool'
@echo ' spi - spi tools'
@echo ' tmon - thermal monitoring and tuning tool'
+ @echo ' thermometer - temperature capture tool'
@echo ' thermal - thermal library'
@echo ' tracing - misc tracing tools'
@echo ' turbostat - Intel CPU idle stats and freq reporting tool'
@@ -95,6 +96,9 @@ turbostat x86_energy_perf_policy intel-speed-select: FORCE
tmon: FORCE
$(call descend,thermal/$@)
+thermometer: FORCE
+ $(call descend,thermal/$@)
+
freefall: FORCE
$(call descend,laptop/$@)
@@ -105,7 +109,7 @@ all: acpi cgroup counter cpupower gpio hv firewire \
perf selftests bootconfig spi turbostat usb \
virtio vm bpf x86_energy_perf_policy \
tmon freefall iio objtool kvm_stat wmi \
- pci debugging tracing thermal
+ pci debugging tracing thermal thermometer
acpi_install:
$(call descend,power/$(@:_install=),install)
@@ -128,6 +132,9 @@ turbostat_install x86_energy_perf_policy_install intel-speed-select_install:
tmon_install:
$(call descend,thermal/$(@:_install=),install)
+thermometer_install:
+ $(call descend,thermal/$(@:_install=),install)
+
freefall_install:
$(call descend,laptop/$(@:_install=),install)
@@ -140,7 +147,7 @@ install: acpi_install cgroup_install counter_install cpupower_install gpio_insta
virtio_install vm_install bpf_install x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install kvm_stat_install \
wmi_install pci_install debugging_install intel-speed-select_install \
- tracing_install
+ tracing_install thermometer_install
acpi_clean:
$(call descend,power/acpi,clean)
@@ -173,6 +180,9 @@ thermal_clean:
turbostat_clean x86_energy_perf_policy_clean intel-speed-select_clean:
$(call descend,power/x86/$(@:_clean=),clean)
+thermometer_clean:
+ $(call descend,thermal/thermometer,clean)
+
tmon_clean:
$(call descend,thermal/tmon,clean)
@@ -187,6 +197,6 @@ clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_cl
vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean \
gpio_clean objtool_clean leds_clean wmi_clean pci_clean firmware_clean debugging_clean \
- intel-speed-select_clean tracing_clean thermal_clean
+ intel-speed-select_clean tracing_clean thermal_clean thermometer_clean
.PHONY: FORCE
diff --git a/tools/thermal/thermometer/Build b/tools/thermal/thermometer/Build
new file mode 100644
index 000000000000..2531dda4acdd
--- /dev/null
+++ b/tools/thermal/thermometer/Build
@@ -0,0 +1,2 @@
+thermometer-y += thermometer.o
+
diff --git a/tools/thermal/thermometer/Makefile b/tools/thermal/thermometer/Makefile
new file mode 100644
index 000000000000..7d08661b3472
--- /dev/null
+++ b/tools/thermal/thermometer/Makefile
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for cgroup tools
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+# $(info Determined 'srctree' to be $(srctree))
+endif
+
+CFLAGS = -Wall -Wextra
+CFLAGS += -I$(srctree)/tools/thermal/lib
+
+LDFLAGS = -L$(srctree)/tools/thermal/lib
+LDFLAGS += -lthermal_tools
+LDFLAGS += -lconfig
+
+all: thermometer
+%: %.c
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+clean:
+ $(RM) thermometer
diff --git a/tools/thermal/thermometer/thermometer.c b/tools/thermal/thermometer/thermometer.c
new file mode 100644
index 000000000000..966961ef21cb
--- /dev/null
+++ b/tools/thermal/thermometer/thermometer.c
@@ -0,0 +1,393 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
+#define _GNU_SOURCE
+#include <dirent.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/timerfd.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <linux/thermal.h>
+
+#include <libconfig.h>
+#include "thermal-tools.h"
+
+#define CLASS_THERMAL "/sys/class/thermal"
+
+enum {
+ THERMOMETER_SUCCESS = 0,
+ THERMOMETER_OPTION_ERROR,
+ THERMOMETER_LOG_ERROR,
+ THERMOMETER_CONFIG_ERROR,
+ THERMOMETER_TIME_ERROR,
+ THERMOMETER_INIT_ERROR,
+ THERMOMETER_RUNTIME_ERROR
+};
+
+struct options {
+ int loglvl;
+ int logopt;
+ int overwrite;
+ const char *config;
+ char postfix[PATH_MAX];
+ char output[PATH_MAX];
+};
+
+struct tz_regex {
+ regex_t regex;
+ int polling;
+};
+
+struct configuration {
+ struct tz_regex *tz_regex;
+ int nr_tz_regex;
+
+};
+
+struct tz {
+ FILE *file_out;
+ int fd_temp;
+ int fd_timer;
+ int polling;
+ const char *name;
+};
+
+struct thermometer {
+ struct tz *tz;
+ int nr_tz;
+};
+
+static struct tz_regex *configuration_tz_match(const char *expr,
+ struct configuration *config)
+{
+ int i;
+
+ for (i = 0; i < config->nr_tz_regex; i++) {
+
+ if (!regexec(&config->tz_regex[i].regex, expr, 0, NULL, 0))
+ return &config->tz_regex[i];
+ }
+
+ return NULL;
+}
+
+static int configuration_init(const char *path, struct configuration *config)
+{
+ config_t cfg;
+
+ config_setting_t *tz;
+ int i, length;
+
+ config_init(&cfg);
+
+ if (!config_read_file(&cfg, path)) {
+ ERROR("Failed to parse %s:%d - %s\n", config_error_file(&cfg),
+ config_error_line(&cfg), config_error_text(&cfg));
+
+ return -1;
+ }
+
+ tz = config_lookup(&cfg, "thermal-zones");
+ if (!tz) {
+ ERROR("No thermal zone configured to be monitored\n");
+ return -1;
+ }
+
+ length = config_setting_length(tz);
+
+ INFO("Found %d thermal zone(s) regular expression\n", length);
+
+ for (i = 0; i < length; i++) {
+
+ config_setting_t *node;
+ const char *name;
+ int polling;
+
+ node = config_setting_get_elem(tz, i);
+ if (!node) {
+ ERROR("Missing node name '%d'\n", i);
+ return -1;
+ };
+
+ if (!config_setting_lookup_string(node, "name", &name)) {
+ ERROR("Thermal zone name not found\n");
+ return -1;
+ }
+
+ if (!config_setting_lookup_int(node, "polling", &polling)) {
+ ERROR("Polling value not found");
+ return -1;
+ }
+
+ config->tz_regex = realloc(config->tz_regex, sizeof(*config->tz_regex) *
+ (config->nr_tz_regex + 1));
+
+ if (regcomp(&config->tz_regex[config->nr_tz_regex].regex, name,
+ REG_NOSUB | REG_EXTENDED)) {
+ ERROR("Invalid regular expression '%s'\n", name);
+ continue;
+ }
+
+ config->tz_regex[config->nr_tz_regex].polling = polling;
+ config->nr_tz_regex++;
+
+ INFO("Thermal zone regular expression '%s' with polling %d\n",
+ name, polling);
+ }
+
+ return 0;
+}
+
+static int options_init(int argc, char *argv[], struct options *options)
+{
+ int opt;
+ time_t now = time(NULL);
+
+ strftime(options->postfix, sizeof(options->postfix),
+ "-%Y-%m-%d_%H:%M:%S", gmtime(&now));
+
+ while ((opt = getopt(argc, argv, "o:c:l:p:eswg")) != -1) {
+ switch (opt) {
+ case 'c':
+ options->config = optarg;
+ break;
+ case 'l':
+ options->loglvl = log_str2level(optarg);
+ break;
+ case 'p':
+ strcpy(options->postfix, optarg);
+ break;
+ case 'o':
+ strcpy(options->output, optarg);
+ break;
+ case 'e':
+ options->logopt |= TO_STDERR;
+ break;
+ case 's':
+ options->logopt |= TO_STDOUT;
+ break;
+ case 'g':
+ options->logopt |= TO_SYSLOG;
+ break;
+ case 'w':
+ options->overwrite = 1;
+ break;
+ default: /* '?' */
+ ERROR("Usage: %s \n", argv[0]);
+ return -1;
+ }
+ }
+
+ printf("Options;\n");
+ printf(" * config: '%s'\n", options->config);
+ printf(" * log level: '%d'\n", options->loglvl);
+ printf(" * postfix: %s\n", options->postfix);
+ printf(" * output: %s\n", options->output);
+
+ return 0;
+}
+
+static int thermometer_add_tz(const char *path, const char *name, int polling,
+ struct thermometer *thermometer)
+{
+ int fd;
+ char tz_path[PATH_MAX];
+
+ sprintf(tz_path, CLASS_THERMAL"/%s/temp", path);
+
+ fd = open(tz_path, O_RDONLY);
+ if (fd < 0) {
+ ERROR("Failed to open '%s': %m\n", tz_path);
+ return -1;
+ }
+
+ thermometer->tz = realloc(thermometer->tz,
+ sizeof(*thermometer->tz) * (thermometer->nr_tz + 1));
+ if (!thermometer->tz) {
+ ERROR("Failed to allocate thermometer->tz\n");
+ return -1;
+ }
+
+ thermometer->tz[thermometer->nr_tz].fd_temp = fd;
+ thermometer->tz[thermometer->nr_tz].name = strdup(name);
+ thermometer->tz[thermometer->nr_tz].polling = polling;
+ thermometer->nr_tz++;
+
+ INFO("Added thermal zone '%s->%s (polling:%d)'\n", path, name, polling);
+
+ return 0;
+}
+
+static int thermometer_init(struct configuration *config,
+ struct thermometer *thermometer)
+{
+ DIR *dir;
+ struct dirent *dirent;
+ struct tz_regex *tz_regex;
+ const char *tz_dirname = "thermal_zone";
+
+ if (mainloop_init()) {
+ ERROR("Failed to start mainloop\n");
+ return -1;
+ }
+
+ dir = opendir(CLASS_THERMAL);
+ if (!dir) {
+ ERROR("failed to open '%s'\n", CLASS_THERMAL);
+ return -1;
+ }
+
+ while ((dirent = readdir(dir))) {
+ char tz_type[THERMAL_NAME_LENGTH];
+ char tz_path[PATH_MAX];
+ FILE *tz_file;
+
+ if (strncmp(dirent->d_name, tz_dirname, strlen(tz_dirname)))
+ continue;
+
+ sprintf(tz_path, CLASS_THERMAL"/%s/type", dirent->d_name);
+
+ tz_file = fopen(tz_path, "r");
+ if (!tz_file) {
+ ERROR("Failed to open '%s': %m", tz_path);
+ continue;
+ }
+
+ fscanf(tz_file, "%s", tz_type);
+
+ fclose(tz_file);
+
+ tz_regex = configuration_tz_match(tz_type, config);
+ if (!tz_regex)
+ continue;
+
+ if (thermometer_add_tz(dirent->d_name, tz_type,
+ tz_regex->polling, thermometer))
+ continue;
+ }
+
+ closedir(dir);
+
+ return 0;
+}
+
+static int timer_callback(int fd, void *arg)
+{
+ struct tz *tz = arg;
+ char buf[16] = { 0 };
+
+ pread(tz->fd_temp, buf, sizeof(buf), 0);
+
+ fprintf(tz->file_out, "%ld %s", getuptimeofday_ms(), buf);
+
+ read(fd, buf, sizeof(buf));
+
+ return 0;
+}
+
+static int thermometer_start(struct thermometer *thermometer,
+ struct options *options)
+{
+ struct itimerspec timer_it = { 0 };
+ char *path;
+ FILE *f;
+ int i;
+
+ for (i = 0; i < thermometer->nr_tz; i++) {
+
+ asprintf(&path, "%s/%s%s", options->output,
+ thermometer->tz[i].name, options->postfix);
+
+ if (!options->overwrite && !access(path, F_OK)) {
+ ERROR("'%s' already exists\n", path);
+ return -1;
+ }
+
+ f = fopen(path, "w");
+ if (!f) {
+ ERROR("Failed to create '%s':%m\n", path);
+ return -1;
+ }
+
+ fprintf(f, "timestamp(ms) %s(°mC)\n", thermometer->tz[i].name);
+
+ thermometer->tz[i].file_out = f;
+
+ /*
+ * Create polling timer
+ */
+ thermometer->tz[i].fd_timer = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (thermometer->tz[i].fd_timer < 0) {
+ ERROR("Failed to create timer for '%s': %m\n",
+ thermometer->tz[i].name);
+ return -1;
+ }
+
+ timer_it.it_interval = timer_it.it_value =
+ msec_to_timespec(thermometer->tz[i].polling);
+
+ if (timerfd_settime(thermometer->tz[i].fd_timer, 0,
+ &timer_it, NULL) < 0)
+ return -1;
+
+ if (mainloop_add(thermometer->tz[i].fd_timer, timer_callback,
+ &thermometer->tz[i]))
+ return -1;
+ }
+
+ return mainloop(-1);
+}
+
+static int thermometer_stop(struct thermometer *thermometer)
+{
+ int i;
+
+ INFO("Closing/flushing output files\n");
+
+ for (i = 0; i < thermometer->nr_tz; i++) {
+ fclose(thermometer->tz[i].file_out);
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ struct options options = {
+ .config = "thermometer.conf",
+ .loglvl = LOG_DEBUG,
+ .output = ".",
+ };
+
+ struct configuration config = { 0 };
+
+ struct thermometer thermometer = { 0 };
+
+ if (options_init(argc, argv, &options))
+ return THERMOMETER_OPTION_ERROR;
+
+ if (log_init(options.loglvl, argv[0], options.logopt))
+ return THERMOMETER_LOG_ERROR;
+
+ if (configuration_init(options.config, &config))
+ return THERMOMETER_CONFIG_ERROR;
+
+ if (uptimeofday_init())
+ return THERMOMETER_TIME_ERROR;
+
+ if (thermometer_init(&config, &thermometer))
+ return THERMOMETER_INIT_ERROR;
+
+ if (thermometer_start(&thermometer, &options))
+ return THERMOMETER_RUNTIME_ERROR;
+
+ if (thermometer_stop(&thermometer))
+ return THERMOMETER_RUNTIME_ERROR;
+
+ return THERMOMETER_SUCCESS;
+}
diff --git a/tools/thermal/thermometer/thermometer.conf b/tools/thermal/thermometer/thermometer.conf
new file mode 100644
index 000000000000..350907accb3e
--- /dev/null
+++ b/tools/thermal/thermometer/thermometer.conf
@@ -0,0 +1,5 @@
+
+thermal-zones = (
+ { name = "cpu[0-7]-thermal";
+ polling = 100; }
+ )
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v1 4/4] tools/thermal: Add thermal daemon skeleton
2022-02-18 12:53 [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
` (2 preceding siblings ...)
2022-02-18 12:53 ` [PATCH v1 3/4] tools/thermal: A temperature capture tool Daniel Lezcano
@ 2022-02-18 12:53 ` Daniel Lezcano
2022-02-24 21:41 ` [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
4 siblings, 0 replies; 10+ messages in thread
From: Daniel Lezcano @ 2022-02-18 12:53 UTC (permalink / raw)
To: daniel.lezcano, rafael
Cc: srinivas.pandruvada, linux-kernel, linux-pm, Amit Kucheria,
Zhang Rui, Jonathan Cameron, Sasha Levin, William Breathitt Gray
This change provides a simple daemon skeleton. It provides an example
of how to use the thermal library.
The goal of this skeleton is to give a base brick for anyone
interested in writing its own thermal engine.
In the future, it will evolve with more features.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
tools/Makefile | 16 +-
tools/thermal/thermal-engine/Build | 2 +
tools/thermal/thermal-engine/Makefile | 27 ++
tools/thermal/thermal-engine/thermal-engine.c | 287 ++++++++++++++++++
4 files changed, 329 insertions(+), 3 deletions(-)
create mode 100644 tools/thermal/thermal-engine/Build
create mode 100644 tools/thermal/thermal-engine/Makefile
create mode 100644 tools/thermal/thermal-engine/thermal-engine.c
diff --git a/tools/Makefile b/tools/Makefile
index 78615f8cb463..b71cf39d3c08 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -32,6 +32,7 @@ help:
@echo ' spi - spi tools'
@echo ' tmon - thermal monitoring and tuning tool'
@echo ' thermometer - temperature capture tool'
+ @echo ' thermal-engine - thermal monitoring tool'
@echo ' thermal - thermal library'
@echo ' tracing - misc tracing tools'
@echo ' turbostat - Intel CPU idle stats and freq reporting tool'
@@ -99,6 +100,9 @@ tmon: FORCE
thermometer: FORCE
$(call descend,thermal/$@)
+thermal-engine: FORCE thermal
+ $(call descend,thermal/$@)
+
freefall: FORCE
$(call descend,laptop/$@)
@@ -109,7 +113,7 @@ all: acpi cgroup counter cpupower gpio hv firewire \
perf selftests bootconfig spi turbostat usb \
virtio vm bpf x86_energy_perf_policy \
tmon freefall iio objtool kvm_stat wmi \
- pci debugging tracing thermal thermometer
+ pci debugging tracing thermal thermometer thermal-engine
acpi_install:
$(call descend,power/$(@:_install=),install)
@@ -135,6 +139,9 @@ tmon_install:
thermometer_install:
$(call descend,thermal/$(@:_install=),install)
+thermal-engine_install:
+ $(call descend,thermal/$(@:_install=),install)
+
freefall_install:
$(call descend,laptop/$(@:_install=),install)
@@ -147,7 +154,7 @@ install: acpi_install cgroup_install counter_install cpupower_install gpio_insta
virtio_install vm_install bpf_install x86_energy_perf_policy_install \
tmon_install freefall_install objtool_install kvm_stat_install \
wmi_install pci_install debugging_install intel-speed-select_install \
- tracing_install thermometer_install
+ tracing_install thermometer_install thermal-engine_install
acpi_clean:
$(call descend,power/acpi,clean)
@@ -183,6 +190,9 @@ turbostat_clean x86_energy_perf_policy_clean intel-speed-select_clean:
thermometer_clean:
$(call descend,thermal/thermometer,clean)
+thermal-engine_clean:
+ $(call descend,thermal/thermal-engine,clean)
+
tmon_clean:
$(call descend,thermal/tmon,clean)
@@ -197,6 +207,6 @@ clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_cl
vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
freefall_clean build_clean libbpf_clean libsubcmd_clean \
gpio_clean objtool_clean leds_clean wmi_clean pci_clean firmware_clean debugging_clean \
- intel-speed-select_clean tracing_clean thermal_clean thermometer_clean
+ intel-speed-select_clean tracing_clean thermal_clean thermometer_clean thermal-engine_clean
.PHONY: FORCE
diff --git a/tools/thermal/thermal-engine/Build b/tools/thermal/thermal-engine/Build
new file mode 100644
index 000000000000..0c8b65248c80
--- /dev/null
+++ b/tools/thermal/thermal-engine/Build
@@ -0,0 +1,2 @@
+thermal-engine-y += thermal-engine.o
+
diff --git a/tools/thermal/thermal-engine/Makefile b/tools/thermal/thermal-engine/Makefile
new file mode 100644
index 000000000000..d4296a331377
--- /dev/null
+++ b/tools/thermal/thermal-engine/Makefile
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for thermal tools
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+# $(info Determined 'srctree' to be $(srctree))
+endif
+
+CFLAGS = -Wall -Wextra
+CFLAGS += -I$(srctree)/tools/thermal/lib
+CFLAGS += -I$(srctree)/tools/lib/thermal/include
+
+LDFLAGS = -L$(srctree)/tools/thermal/lib
+LDFLAGS += -L$(srctree)/tools/lib/thermal
+LDFLAGS += -lthermal_tools
+LDFLAGS += -lthermal
+LDFLAGS += -lconfig
+LDFLAGS += -lnl-genl-3 -lnl-3
+
+all: thermal-engine
+%: %.c
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+clean:
+ $(RM) thermal-engine
diff --git a/tools/thermal/thermal-engine/thermal-engine.c b/tools/thermal/thermal-engine/thermal-engine.c
new file mode 100644
index 000000000000..dc468278bb49
--- /dev/null
+++ b/tools/thermal/thermal-engine/thermal-engine.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Thermal monitoring tool based on the thermal netlink events.
+ *
+ * Copyright (C) 2022 Linaro Ltd.
+ *
+ * Author: Daniel Lezcano <daniel.lezcano@kernel.org>
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <syslog.h>
+
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <thermal.h>
+#include "thermal-tools.h"
+
+struct options {
+ int loglevel;
+ int logopt;
+ int interactive;
+};
+
+struct thermal_data {
+ struct thermal_zone *tz;
+ struct thermal_handler *th;
+};
+
+static int show_trip(struct thermal_trip *tt, __maybe_unused void *arg)
+{
+ INFO("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, __maybe_unused void *arg)
+{
+ thermal_cmd_get_temp(arg, tz);
+
+ INFO("temperature: %d\n", tz->temp);
+
+ return 0;
+}
+
+static int show_governor(struct thermal_zone *tz, __maybe_unused void *arg)
+{
+ thermal_cmd_get_governor(arg, tz);
+
+ INFO("governor: '%s'\n", tz->governor);
+
+ return 0;
+}
+
+static int show_tz(struct thermal_zone *tz, __maybe_unused void *arg)
+{
+ INFO("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, __maybe_unused void *arg)
+{
+ INFO("Thermal zone '%s'/%d created\n", name, tz_id);
+
+ return 0;
+}
+
+static int tz_delete(int tz_id, __maybe_unused void *arg)
+{
+ INFO("Thermal zone %d deleted\n", tz_id);
+
+ return 0;
+}
+
+static int tz_disable(int tz_id, void *arg)
+{
+ struct thermal_data *td = arg;
+ struct thermal_zone *tz = thermal_zone_find_by_id(td->tz, tz_id);
+
+ INFO("Thermal zone %d ('%s') disabled\n", tz_id, tz->name);
+
+ return 0;
+}
+
+static int tz_enable(int tz_id, void *arg)
+{
+ struct thermal_data *td = arg;
+ struct thermal_zone *tz = thermal_zone_find_by_id(td->tz, tz_id);
+
+ INFO("Thermal zone %d ('%s') enabled\n", tz_id, tz->name);
+
+ return 0;
+}
+
+static int trip_high(int tz_id, int trip_id, int temp, void *arg)
+{
+ struct thermal_data *td = arg;
+ struct thermal_zone *tz = thermal_zone_find_by_id(td->tz, tz_id);
+
+ INFO("Thermal zone %d ('%s'): trip point %d crossed way up with %d °C\n",
+ tz_id, tz->name, trip_id, temp);
+
+ return 0;
+}
+
+static int trip_low(int tz_id, int trip_id, int temp, void *arg)
+{
+ struct thermal_data *td = arg;
+ struct thermal_zone *tz = thermal_zone_find_by_id(td->tz, tz_id);
+
+ INFO("Thermal zone %d ('%s'): trip point %d crossed way down with %d °C\n",
+ tz_id, tz->name, trip_id, temp);
+
+ return 0;
+}
+
+static int trip_add(int tz_id, int trip_id, int type, int temp, int hyst, __maybe_unused void *arg)
+{
+ INFO("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, __maybe_unused void *arg)
+{
+ INFO("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, __maybe_unused void *arg)
+{
+ struct thermal_data *td = arg;
+ struct thermal_zone *tz = thermal_zone_find_by_id(td->tz, tz_id);
+
+ INFO("Trip point changed %d: id=%d, type=%d, temp=%d, hyst=%d\n",
+ tz_id, trip_id, type, temp, hyst);
+
+ tz->trip[trip_id].type = type;
+ tz->trip[trip_id].temp = temp;
+ tz->trip[trip_id].hyst = hyst;
+
+ return 0;
+}
+
+static int cdev_add(const char *name, int cdev_id, int max_state, __maybe_unused void *arg)
+{
+ INFO("Cooling device '%s'/%d (max state=%d) added\n", name, cdev_id, max_state);
+
+ return 0;
+}
+
+static int cdev_delete(int cdev_id, __maybe_unused void *arg)
+{
+ INFO("Cooling device %d deleted", cdev_id);
+
+ return 0;
+}
+
+static int cdev_update(int cdev_id, int cur_state, __maybe_unused void *arg)
+{
+ INFO("cdev:%d state:%d\n", cdev_id, cur_state);
+
+ return 0;
+}
+
+static int gov_change(int tz_id, const char *name, __maybe_unused void *arg)
+{
+ struct thermal_data *td = arg;
+ struct thermal_zone *tz = thermal_zone_find_by_id(td->tz, tz_id);
+
+ INFO("%s: governor changed %s -> %s\n", tz->name, tz->governor, name);
+
+ strcpy(tz->governor, name);
+
+ return 0;
+}
+
+static struct thermal_ops ops = {
+ .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 thermal_event(__maybe_unused int fd, __maybe_unused void *arg)
+{
+ struct thermal_data *td = arg;
+
+ return thermal_events_handle(td->th, td);
+}
+
+static int options_init(int argc, char *argv[], struct options *options)
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "sl:")) != -1) {
+ switch (opt) {
+ case 'l':
+ options->loglevel = log_str2level(optarg);
+ break;
+ case 's':
+ options->logopt |= TO_STDOUT;
+ break;
+ default: /* '?' */
+ ERROR("Usage: %s \n", argv[0]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+enum {
+ THERMAL_ENGINE_SUCCESS = 0,
+ THERMAL_ENGINE_OPTION_ERROR,
+ THERMAL_ENGINE_DAEMON_ERROR,
+ THERMAL_ENGINE_LOG_ERROR,
+ THERMAL_ENGINE_THERMAL_ERROR,
+ THERMAL_ENGINE_MAINLOOP_ERROR,
+};
+
+int main(int argc, char *argv[])
+{
+ struct thermal_data td;
+ struct options options = {
+ .loglevel = LOG_DEBUG,
+ .logopt = LOG_SYSLOG
+ };
+
+ if (options_init(argc, argv, &options))
+ return THERMAL_ENGINE_OPTION_ERROR;
+
+ if (!(options.logopt & TO_STDOUT) && daemon(0, 0))
+ return THERMAL_ENGINE_DAEMON_ERROR;
+
+ if (log_init(options.loglevel, basename(argv[0]), options.logopt))
+ return THERMAL_ENGINE_LOG_ERROR;
+
+ td.th = thermal_init(&ops);
+ if (!td.th)
+ return THERMAL_ENGINE_THERMAL_ERROR;
+
+ td.tz = thermal_zone_discover(td.th);
+ if (!td.tz)
+ return THERMAL_ENGINE_THERMAL_ERROR;
+
+ for_each_thermal_zone(td.tz, show_tz, td.th);
+
+ if (mainloop_init())
+ return THERMAL_ENGINE_MAINLOOP_ERROR;
+
+ if (mainloop_add(thermal_events_fd(td.th), thermal_event, &td))
+ return THERMAL_ENGINE_MAINLOOP_ERROR;
+
+ if (mainloop(-1))
+ return THERMAL_ENGINE_MAINLOOP_ERROR;
+
+ return THERMAL_ENGINE_SUCCESS;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v1 0/4] Thermal library and tools
2022-02-18 12:53 [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
` (3 preceding siblings ...)
2022-02-18 12:53 ` [PATCH v1 4/4] tools/thermal: Add thermal daemon skeleton Daniel Lezcano
@ 2022-02-24 21:41 ` Daniel Lezcano
2022-02-25 1:25 ` srinivas pandruvada
2022-02-28 17:13 ` srinivas pandruvada
4 siblings, 2 replies; 10+ messages in thread
From: Daniel Lezcano @ 2022-02-24 21:41 UTC (permalink / raw)
To: rafael; +Cc: srinivas.pandruvada, linux-kernel, linux-pm
Hi,
What shall I do with this series? Is everyone ok with it?
On 18/02/2022 13:53, Daniel Lezcano wrote:
> This series provides a thermal library providing the basic callback oriented
> netlink communication and events with the thermal framework, a temperature
> capture tool and a thermal monitoring skeleton using the thermal library.
>
> Changelog:
> - V1:
> - Took into account RFC comments (unsubscribe, error enum, thermal daemon
> renamed to thermal-engine)
>
> Daniel Lezcano (4):
> tools/lib/thermal: Add a thermal library
> tools/thermal: Add util library
> tools/thermal: A temperature capture tool
> tools/thermal: Add thermal daemon skeleton
>
> tools/Makefile | 36 +-
> tools/lib/thermal/.gitignore | 2 +
> tools/lib/thermal/Build | 5 +
> tools/lib/thermal/Makefile | 165 ++++++++
> tools/lib/thermal/commands.c | 351 ++++++++++++++++
> tools/lib/thermal/events.c | 164 ++++++++
> tools/lib/thermal/include/thermal.h | 141 +++++++
> tools/lib/thermal/libthermal.map | 25 ++
> tools/lib/thermal/libthermal.pc.template | 12 +
> tools/lib/thermal/sampling.c | 75 ++++
> tools/lib/thermal/thermal.c | 126 ++++++
> tools/lib/thermal/thermal_nl.c | 215 ++++++++++
> tools/lib/thermal/thermal_nl.h | 46 ++
> tools/thermal/lib/Build | 3 +
> tools/thermal/lib/Makefile | 158 +++++++
> .../thermal/lib/libthermal_tools.pc.template | 12 +
> tools/thermal/lib/log.c | 77 ++++
> tools/thermal/lib/log.h | 31 ++
> tools/thermal/lib/mainloop.c | 135 ++++++
> tools/thermal/lib/mainloop.h | 14 +
> tools/thermal/lib/thermal-tools.h | 10 +
> tools/thermal/lib/uptimeofday.c | 40 ++
> tools/thermal/lib/uptimeofday.h | 12 +
> tools/thermal/thermal-engine/Build | 2 +
> tools/thermal/thermal-engine/Makefile | 27 ++
> tools/thermal/thermal-engine/thermal-engine.c | 287 +++++++++++++
> tools/thermal/thermometer/Build | 2 +
> tools/thermal/thermometer/Makefile | 23 +
> tools/thermal/thermometer/thermometer.c | 393 ++++++++++++++++++
> tools/thermal/thermometer/thermometer.conf | 5 +
> 30 files changed, 2591 insertions(+), 3 deletions(-)
> create mode 100644 tools/lib/thermal/.gitignore
> create mode 100644 tools/lib/thermal/Build
> create mode 100644 tools/lib/thermal/Makefile
> create mode 100644 tools/lib/thermal/commands.c
> create mode 100644 tools/lib/thermal/events.c
> create mode 100644 tools/lib/thermal/include/thermal.h
> create mode 100644 tools/lib/thermal/libthermal.map
> create mode 100644 tools/lib/thermal/libthermal.pc.template
> create mode 100644 tools/lib/thermal/sampling.c
> create mode 100644 tools/lib/thermal/thermal.c
> create mode 100644 tools/lib/thermal/thermal_nl.c
> create mode 100644 tools/lib/thermal/thermal_nl.h
> create mode 100644 tools/thermal/lib/Build
> create mode 100644 tools/thermal/lib/Makefile
> create mode 100644 tools/thermal/lib/libthermal_tools.pc.template
> create mode 100644 tools/thermal/lib/log.c
> create mode 100644 tools/thermal/lib/log.h
> create mode 100644 tools/thermal/lib/mainloop.c
> create mode 100644 tools/thermal/lib/mainloop.h
> create mode 100644 tools/thermal/lib/thermal-tools.h
> create mode 100644 tools/thermal/lib/uptimeofday.c
> create mode 100644 tools/thermal/lib/uptimeofday.h
> create mode 100644 tools/thermal/thermal-engine/Build
> create mode 100644 tools/thermal/thermal-engine/Makefile
> create mode 100644 tools/thermal/thermal-engine/thermal-engine.c
> create mode 100644 tools/thermal/thermometer/Build
> create mode 100644 tools/thermal/thermometer/Makefile
> create mode 100644 tools/thermal/thermometer/thermometer.c
> create mode 100644 tools/thermal/thermometer/thermometer.conf
>
--
<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
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v1 0/4] Thermal library and tools
2022-02-24 21:41 ` [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
@ 2022-02-25 1:25 ` srinivas pandruvada
2022-02-25 8:39 ` Daniel Lezcano
2022-02-28 17:13 ` srinivas pandruvada
1 sibling, 1 reply; 10+ messages in thread
From: srinivas pandruvada @ 2022-02-25 1:25 UTC (permalink / raw)
To: Daniel Lezcano, rafael; +Cc: linux-kernel, linux-pm
Hi Daniel,
On Thu, 2022-02-24 at 22:41 +0100, Daniel Lezcano wrote:
>
> Hi,
>
> What shall I do with this series? Is everyone ok with it?
>
Want to try out on a system and check. But unfortunately couldn't get
to it yet. Hope to get to it next week. Is that OK?
Thanks,
Srinivas
>
>
> On 18/02/2022 13:53, Daniel Lezcano wrote:
> > This series provides a thermal library providing the basic callback
> > oriented
> > netlink communication and events with the thermal framework, a
> > temperature
> > capture tool and a thermal monitoring skeleton using the thermal
> > library.
> >
> > Changelog:
> > - V1:
> > - Took into account RFC comments (unsubscribe, error enum,
> > thermal daemon
> > renamed to thermal-engine)
> >
> > Daniel Lezcano (4):
> > tools/lib/thermal: Add a thermal library
> > tools/thermal: Add util library
> > tools/thermal: A temperature capture tool
> > tools/thermal: Add thermal daemon skeleton
> >
> > tools/Makefile | 36 +-
> > tools/lib/thermal/.gitignore | 2 +
> > tools/lib/thermal/Build | 5 +
> > tools/lib/thermal/Makefile | 165 ++++++++
> > tools/lib/thermal/commands.c | 351
> > ++++++++++++++++
> > tools/lib/thermal/events.c | 164 ++++++++
> > tools/lib/thermal/include/thermal.h | 141 +++++++
> > tools/lib/thermal/libthermal.map | 25 ++
> > tools/lib/thermal/libthermal.pc.template | 12 +
> > tools/lib/thermal/sampling.c | 75 ++++
> > tools/lib/thermal/thermal.c | 126 ++++++
> > tools/lib/thermal/thermal_nl.c | 215 ++++++++++
> > tools/lib/thermal/thermal_nl.h | 46 ++
> > tools/thermal/lib/Build | 3 +
> > tools/thermal/lib/Makefile | 158 +++++++
> > .../thermal/lib/libthermal_tools.pc.template | 12 +
> > tools/thermal/lib/log.c | 77 ++++
> > tools/thermal/lib/log.h | 31 ++
> > tools/thermal/lib/mainloop.c | 135 ++++++
> > tools/thermal/lib/mainloop.h | 14 +
> > tools/thermal/lib/thermal-tools.h | 10 +
> > tools/thermal/lib/uptimeofday.c | 40 ++
> > tools/thermal/lib/uptimeofday.h | 12 +
> > tools/thermal/thermal-engine/Build | 2 +
> > tools/thermal/thermal-engine/Makefile | 27 ++
> > tools/thermal/thermal-engine/thermal-engine.c | 287 +++++++++++++
> > tools/thermal/thermometer/Build | 2 +
> > tools/thermal/thermometer/Makefile | 23 +
> > tools/thermal/thermometer/thermometer.c | 393
> > ++++++++++++++++++
> > tools/thermal/thermometer/thermometer.conf | 5 +
> > 30 files changed, 2591 insertions(+), 3 deletions(-)
> > create mode 100644 tools/lib/thermal/.gitignore
> > create mode 100644 tools/lib/thermal/Build
> > create mode 100644 tools/lib/thermal/Makefile
> > create mode 100644 tools/lib/thermal/commands.c
> > create mode 100644 tools/lib/thermal/events.c
> > create mode 100644 tools/lib/thermal/include/thermal.h
> > create mode 100644 tools/lib/thermal/libthermal.map
> > create mode 100644 tools/lib/thermal/libthermal.pc.template
> > create mode 100644 tools/lib/thermal/sampling.c
> > create mode 100644 tools/lib/thermal/thermal.c
> > create mode 100644 tools/lib/thermal/thermal_nl.c
> > create mode 100644 tools/lib/thermal/thermal_nl.h
> > create mode 100644 tools/thermal/lib/Build
> > create mode 100644 tools/thermal/lib/Makefile
> > create mode 100644 tools/thermal/lib/libthermal_tools.pc.template
> > create mode 100644 tools/thermal/lib/log.c
> > create mode 100644 tools/thermal/lib/log.h
> > create mode 100644 tools/thermal/lib/mainloop.c
> > create mode 100644 tools/thermal/lib/mainloop.h
> > create mode 100644 tools/thermal/lib/thermal-tools.h
> > create mode 100644 tools/thermal/lib/uptimeofday.c
> > create mode 100644 tools/thermal/lib/uptimeofday.h
> > create mode 100644 tools/thermal/thermal-engine/Build
> > create mode 100644 tools/thermal/thermal-engine/Makefile
> > create mode 100644 tools/thermal/thermal-engine/thermal-engine.c
> > create mode 100644 tools/thermal/thermometer/Build
> > create mode 100644 tools/thermal/thermometer/Makefile
> > create mode 100644 tools/thermal/thermometer/thermometer.c
> > create mode 100644 tools/thermal/thermometer/thermometer.conf
> >
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v1 0/4] Thermal library and tools
2022-02-25 1:25 ` srinivas pandruvada
@ 2022-02-25 8:39 ` Daniel Lezcano
0 siblings, 0 replies; 10+ messages in thread
From: Daniel Lezcano @ 2022-02-25 8:39 UTC (permalink / raw)
To: srinivas pandruvada, rafael; +Cc: linux-kernel, linux-pm
Hi Srinivas,
On 25/02/2022 02:25, srinivas pandruvada wrote:
> Hi Daniel,
>
> On Thu, 2022-02-24 at 22:41 +0100, Daniel Lezcano wrote:
>>
>> Hi,
>>
>> What shall I do with this series? Is everyone ok with it?
>>
> Want to try out on a system and check. But unfortunately couldn't get
> to it yet. Hope to get to it next week. Is that OK?
Oh, great! Thanks for trying it out. Yes, I think next week is fine
--
<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
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v1 0/4] Thermal library and tools
2022-02-24 21:41 ` [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
2022-02-25 1:25 ` srinivas pandruvada
@ 2022-02-28 17:13 ` srinivas pandruvada
2022-03-09 15:42 ` Daniel Lezcano
1 sibling, 1 reply; 10+ messages in thread
From: srinivas pandruvada @ 2022-02-28 17:13 UTC (permalink / raw)
To: Daniel Lezcano, rafael; +Cc: linux-kernel, linux-pm
Hi Daniel,
On Thu, 2022-02-24 at 22:41 +0100, Daniel Lezcano wrote:
>
> Hi,
>
> What shall I do with this series? Is everyone ok with it?
>
Some comments
1. White space errors while applying
$git am ../daniel/\[PATCH\ v1\ 1_4\]\ tools_lib_thermal_\ Add\ a\
thermal\ library.mbox
Applying: tools/lib/thermal: Add a thermal library
.git/rebase-apply/patch:234: trailing whitespace.
clean:
.git/rebase-apply/patch:715: trailing whitespace.
nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
.git/rebase-apply/patch:878: trailing whitespace.
.git/rebase-apply/patch:879: trailing whitespace.
struct thermal_handler;
.git/rebase-apply/patch:1103: trailing whitespace.
}
warning: squelched 5 whitespace errors
warning: 10 lines add whitespace errors.
$git am ../daniel/\[PATCH\ v1\ 2_4\]\ tools_thermal_\ Add\ util\
library.mbox
Applying: tools/thermal: Add util library
.git/rebase-apply/patch:152: trailing whitespace.
clean:
.git/rebase-apply/patch:259: trailing whitespace.
.git/rebase-apply/patch:285: trailing whitespace.
.git/rebase-apply/patch:385: trailing whitespace.
.git/rebase-apply/patch:392: trailing whitespace.
/*
warning: squelched 1 whitespace error
warning: 6 lines add whitespace errors.
$git am ../daniel/\[PATCH\ v1\ 3_4\]\ tools_thermal_\ A\ temperature\
capture\ tool.mbox
Applying: tools/thermal: A temperature capture tool
.git/rebase-apply/patch:165: trailing whitespace.
regex_t regex;
.git/rebase-apply/patch:205: trailing whitespace.
.git/rebase-apply/patch:208: trailing whitespace.
.git/rebase-apply/patch:249: trailing whitespace.
.git/rebase-apply/patch:265: trailing whitespace.
warning: squelched 13 whitespace errors
warning: 18 lines add whitespace errors.
$ git am ../daniel/\[PATCH\ v1\ 4_4\]\ tools_thermal_\ Add\ thermal\
daemon\ skeleton.mbox
Applying: tools/thermal: Add thermal daemon skeleton
.git/rebase-apply/patch:170: trailing whitespace.
}
.git/rebase-apply/patch:186: trailing whitespace.
.git/rebase-apply/patch:197: trailing whitespace.
.git/rebase-apply/patch:199: trailing whitespace.
.git/rebase-apply/patch:348: trailing whitespace.
warning: squelched 3 whitespace errors
warning: 8 lines add whitespace errors.
2. No help or man page
thermal_engine has some options. There is no --help or man
3. Silent failure
For example:
$sudo ./thermal-engine
4.
sudo ./thermometer
Options;
* config: 'thermometer.conf'
* log level: '7'
* postfix: -2022-02-28_16:51:33
* output: .
What an user can do?
Thanks,
Srinivas
>
>
> On 18/02/2022 13:53, Daniel Lezcano wrote:
> > This series provides a thermal library providing the basic callback
> > oriented
> > netlink communication and events with the thermal framework, a
> > temperature
> > capture tool and a thermal monitoring skeleton using the thermal
> > library.
> >
> > Changelog:
> > - V1:
> > - Took into account RFC comments (unsubscribe, error enum,
> > thermal daemon
> > renamed to thermal-engine)
> >
> > Daniel Lezcano (4):
> > tools/lib/thermal: Add a thermal library
> > tools/thermal: Add util library
> > tools/thermal: A temperature capture tool
> > tools/thermal: Add thermal daemon skeleton
> >
> > tools/Makefile | 36 +-
> > tools/lib/thermal/.gitignore | 2 +
> > tools/lib/thermal/Build | 5 +
> > tools/lib/thermal/Makefile | 165 ++++++++
> > tools/lib/thermal/commands.c | 351
> > ++++++++++++++++
> > tools/lib/thermal/events.c | 164 ++++++++
> > tools/lib/thermal/include/thermal.h | 141 +++++++
> > tools/lib/thermal/libthermal.map | 25 ++
> > tools/lib/thermal/libthermal.pc.template | 12 +
> > tools/lib/thermal/sampling.c | 75 ++++
> > tools/lib/thermal/thermal.c | 126 ++++++
> > tools/lib/thermal/thermal_nl.c | 215 ++++++++++
> > tools/lib/thermal/thermal_nl.h | 46 ++
> > tools/thermal/lib/Build | 3 +
> > tools/thermal/lib/Makefile | 158 +++++++
> > .../thermal/lib/libthermal_tools.pc.template | 12 +
> > tools/thermal/lib/log.c | 77 ++++
> > tools/thermal/lib/log.h | 31 ++
> > tools/thermal/lib/mainloop.c | 135 ++++++
> > tools/thermal/lib/mainloop.h | 14 +
> > tools/thermal/lib/thermal-tools.h | 10 +
> > tools/thermal/lib/uptimeofday.c | 40 ++
> > tools/thermal/lib/uptimeofday.h | 12 +
> > tools/thermal/thermal-engine/Build | 2 +
> > tools/thermal/thermal-engine/Makefile | 27 ++
> > tools/thermal/thermal-engine/thermal-engine.c | 287 +++++++++++++
> > tools/thermal/thermometer/Build | 2 +
> > tools/thermal/thermometer/Makefile | 23 +
> > tools/thermal/thermometer/thermometer.c | 393
> > ++++++++++++++++++
> > tools/thermal/thermometer/thermometer.conf | 5 +
> > 30 files changed, 2591 insertions(+), 3 deletions(-)
> > create mode 100644 tools/lib/thermal/.gitignore
> > create mode 100644 tools/lib/thermal/Build
> > create mode 100644 tools/lib/thermal/Makefile
> > create mode 100644 tools/lib/thermal/commands.c
> > create mode 100644 tools/lib/thermal/events.c
> > create mode 100644 tools/lib/thermal/include/thermal.h
> > create mode 100644 tools/lib/thermal/libthermal.map
> > create mode 100644 tools/lib/thermal/libthermal.pc.template
> > create mode 100644 tools/lib/thermal/sampling.c
> > create mode 100644 tools/lib/thermal/thermal.c
> > create mode 100644 tools/lib/thermal/thermal_nl.c
> > create mode 100644 tools/lib/thermal/thermal_nl.h
> > create mode 100644 tools/thermal/lib/Build
> > create mode 100644 tools/thermal/lib/Makefile
> > create mode 100644 tools/thermal/lib/libthermal_tools.pc.template
> > create mode 100644 tools/thermal/lib/log.c
> > create mode 100644 tools/thermal/lib/log.h
> > create mode 100644 tools/thermal/lib/mainloop.c
> > create mode 100644 tools/thermal/lib/mainloop.h
> > create mode 100644 tools/thermal/lib/thermal-tools.h
> > create mode 100644 tools/thermal/lib/uptimeofday.c
> > create mode 100644 tools/thermal/lib/uptimeofday.h
> > create mode 100644 tools/thermal/thermal-engine/Build
> > create mode 100644 tools/thermal/thermal-engine/Makefile
> > create mode 100644 tools/thermal/thermal-engine/thermal-engine.c
> > create mode 100644 tools/thermal/thermometer/Build
> > create mode 100644 tools/thermal/thermometer/Makefile
> > create mode 100644 tools/thermal/thermometer/thermometer.c
> > create mode 100644 tools/thermal/thermometer/thermometer.conf
> >
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v1 0/4] Thermal library and tools
2022-02-28 17:13 ` srinivas pandruvada
@ 2022-03-09 15:42 ` Daniel Lezcano
0 siblings, 0 replies; 10+ messages in thread
From: Daniel Lezcano @ 2022-03-09 15:42 UTC (permalink / raw)
To: srinivas pandruvada, rafael; +Cc: linux-kernel, linux-pm
Hi Srinivas,
thanks for your feedbacks, I'll fix that.
-- Daniel
On 28/02/2022 18:13, srinivas pandruvada wrote:
> Hi Daniel,
> On Thu, 2022-02-24 at 22:41 +0100, Daniel Lezcano wrote:
>>
>> Hi,
>>
>> What shall I do with this series? Is everyone ok with it?
>>
> Some comments
> 1. White space errors while applying
> $git am ../daniel/\[PATCH\ v1\ 1_4\]\ tools_lib_thermal_\ Add\ a\
> thermal\ library.mbox
> Applying: tools/lib/thermal: Add a thermal library
> .git/rebase-apply/patch:234: trailing whitespace.
> clean:
> .git/rebase-apply/patch:715: trailing whitespace.
>
> nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
> .git/rebase-apply/patch:878: trailing whitespace.
>
> .git/rebase-apply/patch:879: trailing whitespace.
> struct thermal_handler;
> .git/rebase-apply/patch:1103: trailing whitespace.
> }
> warning: squelched 5 whitespace errors
> warning: 10 lines add whitespace errors.
>
> $git am ../daniel/\[PATCH\ v1\ 2_4\]\ tools_thermal_\ Add\ util\
> library.mbox
> Applying: tools/thermal: Add util library
> .git/rebase-apply/patch:152: trailing whitespace.
> clean:
> .git/rebase-apply/patch:259: trailing whitespace.
>
> .git/rebase-apply/patch:285: trailing whitespace.
>
> .git/rebase-apply/patch:385: trailing whitespace.
>
> .git/rebase-apply/patch:392: trailing whitespace.
> /*
> warning: squelched 1 whitespace error
> warning: 6 lines add whitespace errors.
> $git am ../daniel/\[PATCH\ v1\ 3_4\]\ tools_thermal_\ A\ temperature\
> capture\ tool.mbox
> Applying: tools/thermal: A temperature capture tool
> .git/rebase-apply/patch:165: trailing whitespace.
> regex_t regex;
> .git/rebase-apply/patch:205: trailing whitespace.
>
> .git/rebase-apply/patch:208: trailing whitespace.
>
> .git/rebase-apply/patch:249: trailing whitespace.
>
> .git/rebase-apply/patch:265: trailing whitespace.
>
> warning: squelched 13 whitespace errors
> warning: 18 lines add whitespace errors.
>
> $ git am ../daniel/\[PATCH\ v1\ 4_4\]\ tools_thermal_\ Add\ thermal\
> daemon\ skeleton.mbox
> Applying: tools/thermal: Add thermal daemon skeleton
> .git/rebase-apply/patch:170: trailing whitespace.
> }
> .git/rebase-apply/patch:186: trailing whitespace.
>
> .git/rebase-apply/patch:197: trailing whitespace.
>
> .git/rebase-apply/patch:199: trailing whitespace.
>
> .git/rebase-apply/patch:348: trailing whitespace.
>
> warning: squelched 3 whitespace errors
> warning: 8 lines add whitespace errors.
>
>
> 2. No help or man page
> thermal_engine has some options. There is no --help or man
>
> 3. Silent failure
>
> For example:
> $sudo ./thermal-engine
>
> 4.
> sudo ./thermometer
> Options;
> * config: 'thermometer.conf'
> * log level: '7'
> * postfix: -2022-02-28_16:51:33
> * output: .
>
> What an user can do?
>
> Thanks,
> Srinivas
>
>>
>>
>> On 18/02/2022 13:53, Daniel Lezcano wrote:
>>> This series provides a thermal library providing the basic callback
>>> oriented
>>> netlink communication and events with the thermal framework, a
>>> temperature
>>> capture tool and a thermal monitoring skeleton using the thermal
>>> library.
>>>
>>> Changelog:
>>> - V1:
>>> - Took into account RFC comments (unsubscribe, error enum,
>>> thermal daemon
>>> renamed to thermal-engine)
>>>
>>> Daniel Lezcano (4):
>>> tools/lib/thermal: Add a thermal library
>>> tools/thermal: Add util library
>>> tools/thermal: A temperature capture tool
>>> tools/thermal: Add thermal daemon skeleton
>>>
>>> tools/Makefile | 36 +-
>>> tools/lib/thermal/.gitignore | 2 +
>>> tools/lib/thermal/Build | 5 +
>>> tools/lib/thermal/Makefile | 165 ++++++++
>>> tools/lib/thermal/commands.c | 351
>>> ++++++++++++++++
>>> tools/lib/thermal/events.c | 164 ++++++++
>>> tools/lib/thermal/include/thermal.h | 141 +++++++
>>> tools/lib/thermal/libthermal.map | 25 ++
>>> tools/lib/thermal/libthermal.pc.template | 12 +
>>> tools/lib/thermal/sampling.c | 75 ++++
>>> tools/lib/thermal/thermal.c | 126 ++++++
>>> tools/lib/thermal/thermal_nl.c | 215 ++++++++++
>>> tools/lib/thermal/thermal_nl.h | 46 ++
>>> tools/thermal/lib/Build | 3 +
>>> tools/thermal/lib/Makefile | 158 +++++++
>>> .../thermal/lib/libthermal_tools.pc.template | 12 +
>>> tools/thermal/lib/log.c | 77 ++++
>>> tools/thermal/lib/log.h | 31 ++
>>> tools/thermal/lib/mainloop.c | 135 ++++++
>>> tools/thermal/lib/mainloop.h | 14 +
>>> tools/thermal/lib/thermal-tools.h | 10 +
>>> tools/thermal/lib/uptimeofday.c | 40 ++
>>> tools/thermal/lib/uptimeofday.h | 12 +
>>> tools/thermal/thermal-engine/Build | 2 +
>>> tools/thermal/thermal-engine/Makefile | 27 ++
>>> tools/thermal/thermal-engine/thermal-engine.c | 287 +++++++++++++
>>> tools/thermal/thermometer/Build | 2 +
>>> tools/thermal/thermometer/Makefile | 23 +
>>> tools/thermal/thermometer/thermometer.c | 393
>>> ++++++++++++++++++
>>> tools/thermal/thermometer/thermometer.conf | 5 +
>>> 30 files changed, 2591 insertions(+), 3 deletions(-)
>>> create mode 100644 tools/lib/thermal/.gitignore
>>> create mode 100644 tools/lib/thermal/Build
>>> create mode 100644 tools/lib/thermal/Makefile
>>> create mode 100644 tools/lib/thermal/commands.c
>>> create mode 100644 tools/lib/thermal/events.c
>>> create mode 100644 tools/lib/thermal/include/thermal.h
>>> create mode 100644 tools/lib/thermal/libthermal.map
>>> create mode 100644 tools/lib/thermal/libthermal.pc.template
>>> create mode 100644 tools/lib/thermal/sampling.c
>>> create mode 100644 tools/lib/thermal/thermal.c
>>> create mode 100644 tools/lib/thermal/thermal_nl.c
>>> create mode 100644 tools/lib/thermal/thermal_nl.h
>>> create mode 100644 tools/thermal/lib/Build
>>> create mode 100644 tools/thermal/lib/Makefile
>>> create mode 100644 tools/thermal/lib/libthermal_tools.pc.template
>>> create mode 100644 tools/thermal/lib/log.c
>>> create mode 100644 tools/thermal/lib/log.h
>>> create mode 100644 tools/thermal/lib/mainloop.c
>>> create mode 100644 tools/thermal/lib/mainloop.h
>>> create mode 100644 tools/thermal/lib/thermal-tools.h
>>> create mode 100644 tools/thermal/lib/uptimeofday.c
>>> create mode 100644 tools/thermal/lib/uptimeofday.h
>>> create mode 100644 tools/thermal/thermal-engine/Build
>>> create mode 100644 tools/thermal/thermal-engine/Makefile
>>> create mode 100644 tools/thermal/thermal-engine/thermal-engine.c
>>> create mode 100644 tools/thermal/thermometer/Build
>>> create mode 100644 tools/thermal/thermometer/Makefile
>>> create mode 100644 tools/thermal/thermometer/thermometer.c
>>> create mode 100644 tools/thermal/thermometer/thermometer.conf
>>>
>>
>>
>
--
<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
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2022-03-09 15:42 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-18 12:53 [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 1/4] tools/lib/thermal: Add a thermal library Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 2/4] tools/thermal: Add util library Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 3/4] tools/thermal: A temperature capture tool Daniel Lezcano
2022-02-18 12:53 ` [PATCH v1 4/4] tools/thermal: Add thermal daemon skeleton Daniel Lezcano
2022-02-24 21:41 ` [PATCH v1 0/4] Thermal library and tools Daniel Lezcano
2022-02-25 1:25 ` srinivas pandruvada
2022-02-25 8:39 ` Daniel Lezcano
2022-02-28 17:13 ` srinivas pandruvada
2022-03-09 15:42 ` Daniel Lezcano
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.