diff options
author | Daniel Lezcano <daniel.lezcano@linaro.org> | 2023-06-29 13:14:54 +0200 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2023-06-29 13:14:54 +0200 |
commit | 136a5443698e2c7a515d9440338a0ff8d3f0b7e8 (patch) | |
tree | 76e7bc966471f4e35146e5094468814ff882e08a | |
parent | 6cf776dd8ddf5b1ec536a0d05bd7def5f6d54f6e (diff) |
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | include/libthermal.h | 128 | ||||
-rw-r--r-- | include/thermal.h | 142 | ||||
-rw-r--r-- | patches/array_size_macro.patch | 15 | ||||
-rw-r--r-- | patches/patches.list | 1 | ||||
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/commands.c | 178 | ||||
-rw-r--r-- | src/events.c | 55 | ||||
-rw-r--r-- | src/sampling.c | 35 | ||||
-rw-r--r-- | src/thermal.c | 40 | ||||
-rw-r--r-- | src/thermal_nl.c (renamed from src/netlink.c) | 70 | ||||
-rw-r--r-- | src/thermal_nl.h (renamed from src/thermal.h) | 6 | ||||
-rwxr-xr-x | sync.sh | 51 | ||||
-rw-r--r-- | tst/tst_thermal.c | 2 |
14 files changed, 426 insertions, 301 deletions
@@ -56,7 +56,7 @@ cc_library_shared { "src/events.c", "src/sampling.c", "src/commands.c", - "src/netlink.c", + "src/thermal_nl.c", ], local_include_dirs: [ diff --git a/include/libthermal.h b/include/libthermal.h deleted file mode 100644 index 17a2111..0000000 --- a/include/libthermal.h +++ /dev/null @@ -1,128 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ -#ifndef __LIBTHERMAL_H -#define __LIBTHERMAL_H - -#include <linux/thermal.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef THERMAL_NAME_LENGTH -#define THERMAL_NAME_LENGTH 64 -#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; -}; - -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 *); - -int for_each_thermal_zone(struct thermal_zone *tz, cb_tz_t cb, void *arg); - -int for_each_thermal_trip(struct thermal_trip *tt, cb_tt_t cb, void *arg); - -int for_each_thermal_cdev(struct thermal_cdev *cdev, cb_tc_t cb, void *arg); - -struct thermal_zone *thermal_zone_find_by_name(struct thermal_zone *tz, - const char *name); - -struct thermal_zone *thermal_zone_find_by_id(struct thermal_zone *tz, int id); - -struct thermal_zone *thermal_zone_discover(struct thermal_handler *th); - -struct thermal_handler *thermal_init(struct thermal_ops *ops); - -/* - * Netlink thermal events - */ -extern int thermal_events_init(struct thermal_handler *th); - -extern int thermal_events_handle(struct thermal_handler *th, void *arg); - -extern int thermal_events_fd(struct thermal_handler *th); - -/* - * Netlink thermal commands - */ -extern int thermal_cmd_init(struct thermal_handler *th); - -extern int thermal_cmd_get_tz(struct thermal_handler *th, - struct thermal_zone **tz); - -extern int thermal_cmd_get_cdev(struct thermal_handler *th, - struct thermal_cdev **tc); - -extern int thermal_cmd_get_trip(struct thermal_handler *th, - struct thermal_zone *tz); - -extern int thermal_cmd_get_governor(struct thermal_handler *th, - struct thermal_zone *tz); - -extern int thermal_cmd_get_temp(struct thermal_handler *th, - struct thermal_zone *tz); - -/* - * Netlink thermal samples - */ -extern int thermal_sampling_init(struct thermal_handler *th); - -extern int thermal_sampling_handle(struct thermal_handler *th, void *arg); - -extern int thermal_sampling_fd(struct thermal_handler *th); - -#endif /* __LIBTHERMAL_H */ - -#ifdef __cplusplus -} -#endif diff --git a/include/thermal.h b/include/thermal.h new file mode 100644 index 0000000..1abc560 --- /dev/null +++ b/include/thermal.h @@ -0,0 +1,142 @@ +/* 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/patches/array_size_macro.patch b/patches/array_size_macro.patch new file mode 100644 index 0000000..f18b1f5 --- /dev/null +++ b/patches/array_size_macro.patch @@ -0,0 +1,15 @@ +diff --git a/src/commands.c b/src/commands.c +index 73d4d4e8d6ec..f57db6d07615 100644 +--- a/src/commands.c ++++ b/src/commands.c +@@ -9,6 +9,10 @@ + #include <thermal.h> + #include "thermal_nl.h" + ++#ifndef ARRAY_SIZE ++#define ARRAY_SIZE(__array) (sizeof(__array) / sizeof(__array[0])) ++#endif ++ + static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = { + /* Thermal zone */ + [THERMAL_GENL_ATTR_TZ] = { .type = NLA_NESTED }, diff --git a/patches/patches.list b/patches/patches.list new file mode 100644 index 0000000..6f28588 --- /dev/null +++ b/patches/patches.list @@ -0,0 +1 @@ +array_size_macro.patch diff --git a/src/Makefile b/src/Makefile index eb9db6a..7f8610a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,7 +3,7 @@ CC=gcc CFLAGS+=-g -Wall -Wno-unused -I/usr/include/libnl3 -I../include -fPIC -Wextra -O2 LDFLAGS=-lnl-genl-3 -lnl-3 -shared DEPS = include/libthermal.h -OBJS = thermal.o events.o sampling.o commands.o netlink.o +OBJS = thermal.o events.o sampling.o commands.o thermal_nl.o LIB=libthermal.so BINS=$(C_BINS:.c=) diff --git a/src/commands.c b/src/commands.c index 4a7bc22..f57db6d 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1,11 +1,17 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +// 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.h> +#include "thermal_nl.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(__array) (sizeof(__array) / sizeof(__array[0])) +#endif static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = { /* Thermal zone */ @@ -47,10 +53,8 @@ static int parse_tz_get(struct genl_info *info, struct thermal_zone **tz) size++; __tz = realloc(__tz, sizeof(*__tz) * (size + 2)); - if (!__tz) { - fprintf(stderr, "Failed to allocate memory\n"); - return -1; - } + if (!__tz) + return THERMAL_ERROR; __tz[size - 1].id = nla_get_u32(attr); } @@ -61,17 +65,15 @@ static int parse_tz_get(struct genl_info *info, struct thermal_zone **tz) THERMAL_NAME_LENGTH); } - /* - * We end the array of thermal zones - */ - __tz[size].id = -1; + if (__tz) + __tz[size].id = -1; *tz = __tz; - return 0; + return THERMAL_SUCCESS; } -int parse_cdev_get(struct genl_info *info, struct thermal_cdev **cdev) +static int parse_cdev_get(struct genl_info *info, struct thermal_cdev **cdev) { struct nlattr *attr; struct thermal_cdev *__cdev = NULL; @@ -85,10 +87,8 @@ int parse_cdev_get(struct genl_info *info, struct thermal_cdev **cdev) size++; __cdev = realloc(__cdev, sizeof(*__cdev) * (size + 2)); - if (!__cdev) { - fprintf(stderr, "Failed to allocate memory\n"); - return -1; - } + if (!__cdev) + return THERMAL_ERROR; __cdev[size - 1].id = nla_get_u32(attr); } @@ -98,20 +98,19 @@ int parse_cdev_get(struct genl_info *info, struct thermal_cdev **cdev) THERMAL_NAME_LENGTH); } - if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_CUR_STATE) { + 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) { + if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_MAX_STATE) __cdev[size - 1].max_state = nla_get_u32(attr); - } } - __cdev[size].id = -1; + if (__cdev) + __cdev[size].id = -1; *cdev = __cdev; - return 0; + return THERMAL_SUCCESS; } static int parse_tz_get_trip(struct genl_info *info, struct thermal_zone *tz) @@ -128,10 +127,8 @@ static int parse_tz_get_trip(struct genl_info *info, struct thermal_zone *tz) size++; __tt = realloc(__tt, sizeof(*__tt) * (size + 2)); - if (!__tt) { - fprintf(stderr, "Failed to allocate memory\n"); - return -1; - } + if (!__tt) + return THERMAL_ERROR; __tt[size - 1].id = nla_get_u32(attr); } @@ -146,11 +143,12 @@ static int parse_tz_get_trip(struct genl_info *info, struct thermal_zone *tz) __tt[size - 1].hyst = nla_get_u32(attr); } - __tt[size].id = -1; + if (__tt) + __tt[size].id = -1; tz->trip = __tt; - return 0; + return THERMAL_SUCCESS; } static int parse_tz_get_temp(struct genl_info *info, struct thermal_zone *tz) @@ -160,16 +158,13 @@ static int parse_tz_get_temp(struct genl_info *info, struct thermal_zone *tz) if (info->attrs[THERMAL_GENL_ATTR_TZ_ID]) id = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_ID]); - if (tz->id != id) { - fprintf(stderr, "thermal zone id mismatch '%d' <> '%d'\n", - tz->id, id); - return -1; - } + 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 0; + return THERMAL_SUCCESS; } static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz) @@ -179,11 +174,8 @@ static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz) if (info->attrs[THERMAL_GENL_ATTR_TZ_ID]) id = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_ID]); - if (tz->id != id) { - fprintf(stderr, "thermal zone id mismatch '%d' <> '%d'\n", - tz->id, id); - return -1; - } + if (tz->id != id) + return THERMAL_ERROR; if (info->attrs[THERMAL_GENL_ATTR_TZ_GOV_NAME]) { nla_strlcpy(tz->governor, @@ -191,175 +183,171 @@ static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz) THERMAL_NAME_LENGTH); } - return 0; + 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: - parse_tz_get(info, arg); + ret = parse_tz_get(info, arg); break; case THERMAL_GENL_CMD_CDEV_GET: - parse_cdev_get(info, arg); + ret = parse_cdev_get(info, arg); break; case THERMAL_GENL_CMD_TZ_GET_TEMP: - parse_tz_get_temp(info, arg); + ret = parse_tz_get_temp(info, arg); break; case THERMAL_GENL_CMD_TZ_GET_TRIP: - parse_tz_get_trip(info, arg); + ret = parse_tz_get_trip(info, arg); break; case THERMAL_GENL_CMD_TZ_GET_GOV: - parse_tz_get_gov(info, arg); + ret = parse_tz_get_gov(info, arg); break; default: - printf("Unknown command id:%d\n", cmd->c_id); - }; + return THERMAL_ERROR; + } - return 0; + return ret; } static struct genl_cmd thermal_cmds[] = { { .c_id = THERMAL_GENL_CMD_TZ_GET_ID, - .c_name = "List thermal zones", + .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 = "Get governor", + .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 = "Get thermal zone temperature", + .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 = "Get thermal zone trip points", + .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 = "Get cooling devices", + .c_name = (char *)"Get cooling devices", .c_msg_parser = handle_netlink, .c_maxattr = THERMAL_GENL_ATTR_MAX, .c_attr_policy = thermal_genl_policy, }, }; -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - static struct genl_ops thermal_cmd_ops = { - .o_name = "thermal", + .o_name = (char *)"thermal", .o_cmds = thermal_cmds, .o_ncmds = ARRAY_SIZE(thermal_cmds), }; -static int thermal_genl_auto(struct thermal_handler *th, int id, int cmd, - int flags, void *arg) +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) { - fprintf(stderr, "Failed to allocate message\n"); - return -1; - } + 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) { - fprintf(stderr, "Failed to set message\n"); - return -1; - } + if (!hdr) + return THERMAL_ERROR; - if (id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id)) { - fprintf(stderr, "Failed to set tz id\n"); - return -1; - } + 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)) { - fprintf(stderr, "Failed to send command\n"); - return -1; - } + if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg)) + return THERMAL_ERROR; nlmsg_free(msg); - return 0; + return THERMAL_SUCCESS; } -int thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz) +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); } -int thermal_cmd_get_cdev(struct thermal_handler *th, struct thermal_cdev **tc) +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); } -int thermal_cmd_get_trip(struct thermal_handler *th, struct thermal_zone *tz) +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); } -int thermal_cmd_get_governor(struct thermal_handler *th, struct thermal_zone *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); } -int thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *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); } -int thermal_cmd_init(struct thermal_handler *th) +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 -1; + return THERMAL_ERROR; ret = genl_register_family(&thermal_cmd_ops); - if (ret) { - fprintf(stderr, "genl_register_family: %d\n", ret); - return -1; - } + if (ret) + return THERMAL_ERROR; ret = genl_ops_resolve(th->sk_cmd, &thermal_cmd_ops); - if (ret) { - fprintf(stderr, "genl_ops_resolve: %d\n", ret); - return -1; - } + if (ret) + return THERMAL_ERROR; family = genl_ctrl_resolve(th->sk_cmd, "nlctrl"); - if (family != GENL_ID_CTRL) { - fprintf(stderr, "genl_ctrl_resolve: %d\n", family); - return -1; - } + if (family != GENL_ID_CTRL) + return THERMAL_ERROR; - return 0; + return THERMAL_SUCCESS; } diff --git a/src/events.c b/src/events.c index eb49a3c..a7a55d1 100644 --- a/src/events.c +++ b/src/events.c @@ -1,10 +1,13 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ -#include <errno.h> +// 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.h> +#include "thermal_nl.h" /* * Optimization: fill this array to tell which event we do want to pay @@ -13,7 +16,7 @@ * 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 enabled_ops[__THERMAL_GENL_EVENT_MAX]; static int handle_thermal_event(struct nl_msg *n, void *arg) { @@ -31,7 +34,7 @@ static int handle_thermal_event(struct nl_msg *n, void *arg) * This is an event we don't care of, bail out. */ if (!enabled_ops[genlhdr->cmd]) - return 0; + return THERMAL_SUCCESS; switch (genlhdr->cmd) { @@ -67,19 +70,14 @@ static int handle_thermal_event(struct nl_msg *n, void *arg) nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]), arg); case THERMAL_GENL_EVENT_TZ_TRIP_UP: -/* return th->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])); */ return ops->trip_high(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), - nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]), -1, arg); - + 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 th->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])); */ return ops->trip_low(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), - nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]), -1, arg); + 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]), @@ -96,9 +94,9 @@ static int handle_thermal_event(struct nl_msg *n, void *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; } - - return -1; } static void thermal_events_ops_init(struct thermal_events_ops *ops) @@ -118,16 +116,16 @@ static void thermal_events_ops_init(struct thermal_events_ops *ops) enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = !!ops->gov_change; } -int thermal_events_handle(struct thermal_handler *th, void *arg) +thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg) { struct thermal_handler_param thp = { .th = th, .arg = arg }; if (!th) - return -1; + return THERMAL_ERROR; if (nl_cb_set(th->cb_event, NL_CB_VALID, NL_CB_CUSTOM, handle_thermal_event, &thp)) - return -1; + return THERMAL_ERROR; return nl_recvmsgs(th->sk_event, th->cb_event); } @@ -140,16 +138,27 @@ int thermal_events_fd(struct thermal_handler *th) return nl_socket_get_fd(th->sk_event); } -int thermal_events_init(struct thermal_handler *th) +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 -1; + return THERMAL_ERROR; if (nl_subscribe_thermal(th->sk_event, th->cb_event, THERMAL_GENL_EVENT_GROUP_NAME)) - return -1; + return THERMAL_ERROR; - return 0; + return THERMAL_SUCCESS; } diff --git a/src/sampling.c b/src/sampling.c index 3609555..7057742 100644 --- a/src/sampling.c +++ b/src/sampling.c @@ -1,10 +1,12 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +// 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.h> +#include "thermal_nl.h" static int handle_thermal_sample(struct nl_msg *n, void *arg) { @@ -22,21 +24,21 @@ static int handle_thermal_sample(struct nl_msg *n, void *arg) 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; } - - return -1; } -int thermal_sampling_handle(struct thermal_handler *th, void *arg) +thermal_error_t thermal_sampling_handle(struct thermal_handler *th, void *arg) { struct thermal_handler_param thp = { .th = th, .arg = arg }; if (!th) - return -1; + return THERMAL_ERROR; if (nl_cb_set(th->cb_sampling, NL_CB_VALID, NL_CB_CUSTOM, handle_thermal_sample, &thp)) - return -1; + return THERMAL_ERROR; return nl_recvmsgs(th->sk_sampling, th->cb_sampling); } @@ -49,14 +51,25 @@ int thermal_sampling_fd(struct thermal_handler *th) return nl_socket_get_fd(th->sk_sampling); } -int thermal_sampling_init(struct thermal_handler *th) +thermal_error_t thermal_sampling_exit(struct thermal_handler *th) +{ + if (nl_unsubscribe_thermal(th->sk_sampling, th->cb_sampling, + THERMAL_GENL_SAMPLING_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 -1; + return THERMAL_ERROR; if (nl_subscribe_thermal(th->sk_sampling, th->cb_sampling, THERMAL_GENL_SAMPLING_GROUP_NAME)) - return -1; + return THERMAL_ERROR; - return 0; + return THERMAL_SUCCESS; } diff --git a/src/thermal.c b/src/thermal.c index bf121b9..72a76dc 100644 --- a/src/thermal.c +++ b/src/thermal.c @@ -1,20 +1,30 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ -#include "thermal.h" +// 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; + if (!cdev) + return 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; + if (!tt) + return 0; + for (i = 0; tt[i].id != -1; i++) ret |= cb(&tt[i], arg); @@ -25,6 +35,9 @@ int for_each_thermal_zone(struct thermal_zone *tz, cb_tz_t cb, void *arg) { int i, ret = 0; + if (!tz) + return 0; + for (i = 0; tz[i].id != -1; i++) ret |= cb(&tz[i], arg); @@ -36,9 +49,9 @@ struct thermal_zone *thermal_zone_find_by_name(struct thermal_zone *tz, { int i; - if (!name) + if (!tz || !name) return NULL; - + for (i = 0; tz[i].id != -1; i++) { if (!strcmp(tz[i].name, name)) return &tz[i]; @@ -51,9 +64,9 @@ struct thermal_zone *thermal_zone_find_by_id(struct thermal_zone *tz, int id) { int i; - if (id < 0) + if (!tz || id < 0) return NULL; - + for (i = 0; tz[i].id != -1; i++) { if (tz[i].id == id) return &tz[i]; @@ -86,6 +99,15 @@ struct thermal_zone *thermal_zone_discover(struct thermal_handler *th) 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; @@ -103,11 +125,11 @@ struct thermal_handler *thermal_init(struct thermal_ops *ops) if (thermal_cmd_init(th)) goto out_free; - + return th; out_free: free(th); - + return NULL; } diff --git a/src/netlink.c b/src/thermal_nl.c index 9ebb7e2..b05cf95 100644 --- a/src/netlink.c +++ b/src/thermal_nl.c @@ -1,12 +1,12 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +// 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 <sys/epoll.h> - -#include "thermal.h" +#include <thermal.h> +#include "thermal_nl.h" struct handler_args { const char *group; @@ -56,13 +56,11 @@ 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 -1; + return THERMAL_ERROR; err = nl_send_auto_complete(sock, msg); - if (err < 0) { - fprintf(stderr, "auto complete failed\n"); + if (err < 0) return err; - } nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, rx_handler, data); @@ -85,10 +83,8 @@ static int nl_family_handler(struct nl_msg *msg, void *arg) nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); - if (!tb[CTRL_ATTR_MCAST_GROUPS]) { - fprintf(stderr, "Multicast group not found\n"); - return -1; - } + if (!tb[CTRL_ATTR_MCAST_GROUPS]) + return THERMAL_ERROR; nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) { @@ -111,11 +107,11 @@ static int nl_family_handler(struct nl_msg *msg, void *arg) break; } - return 0; + return THERMAL_SUCCESS; } -int nl_get_multicast_id(struct nl_sock *sock, struct nl_cb *cb, - const char *family, const char *group) +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; @@ -126,7 +122,7 @@ int nl_get_multicast_id(struct nl_sock *sock, struct nl_cb *cb, msg = nlmsg_alloc(); if (!msg) - return -ENOMEM; + return THERMAL_ERROR; ctrlid = genl_ctrl_resolve(sock, "nlctrl"); @@ -152,7 +148,7 @@ int nl_thermal_connect(struct nl_sock **nl_sock, struct nl_cb **nl_cb) cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) - return -1; + return THERMAL_ERROR; sock = nl_socket_alloc(); if (!sock) @@ -161,22 +157,22 @@ int nl_thermal_connect(struct nl_sock **nl_sock, struct nl_cb **nl_cb) 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 -1; + 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 0; + return THERMAL_SUCCESS; out_socket_free: nl_socket_free(sock); out_cb_free: nl_cb_put(cb); - return -1; + return THERMAL_ERROR; } void nl_thermal_disconnect(struct nl_sock *nl_sock, struct nl_cb *nl_cb) @@ -186,6 +182,22 @@ void nl_thermal_disconnect(struct nl_sock *nl_sock, struct nl_cb *nl_cb) 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) { @@ -193,13 +205,11 @@ int nl_subscribe_thermal(struct nl_sock *nl_sock, struct nl_cb *nl_cb, mcid = nl_get_multicast_id(nl_sock, nl_cb, THERMAL_GENL_FAMILY_NAME, group); - if (mcid < 0) { - fprintf(stderr, "Subscribing to multicast failed\n"); - return -1; - } + if (mcid < 0) + return THERMAL_ERROR; if (nl_socket_add_membership(nl_sock, mcid)) - return -1; + return THERMAL_ERROR; - return 0; + return THERMAL_SUCCESS; } diff --git a/src/thermal.h b/src/thermal_nl.h index 85814a1..ddf6356 100644 --- a/src/thermal.h +++ b/src/thermal_nl.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +/* Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org> */ #ifndef __THERMAL_H #define __THERMAL_H @@ -7,8 +8,6 @@ #include <netlink/genl/mngt.h> #include <netlink/genl/ctrl.h> -#include "libthermal.h" - struct thermal_handler { int done; int error; @@ -33,6 +32,9 @@ struct thermal_handler_param { 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); @@ -0,0 +1,51 @@ +#!/bin/bash +# set -ax +GIT_LINUX_PATH=".linux" +GIT_REPO=https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + +if [ ! -d $GIT_LINUX_PATH ]; then + echo " * Cloning $GIT_REPO" + git clone --depth 1 --sparse $GIT_REPO $GIT_LINUX_PATH +fi + +pushd $GIT_LINUX_PATH > /dev/null + +# Update the official Linus' tree +echo " * Updating $GIT_REPO" +git pull + +GIT_LIB_THERMAL="tools/lib/thermal" +GIT_THERMAL_LIB="tools/thermal/lib" +GIT_SPARSE_SET="$GIT_LIB_THERMAL $GIT_THERMAL_LIB" + +echo " * Sparse checkout $GIT_SPARSE_SET" +git sparse-checkout set $GIT_SPARSE_SET + +popd > /dev/null + +INCLUDE_PATH=src/include +LIB_PATH=src/lib +THERMAL_MANAGER_PATH=src/thermal-manager + +declare -A TARGETS + +TARGETS["include"]="$GIT_LINUX_PATH/$GIT_LIB_THERMAL/include/*.[ch]" +TARGETS["src"]="$GIT_LINUX_PATH/$GIT_LIB_THERMAL/*.[ch] $GIT_LINUX_PATH/$GIT_LIB_THERMAL/Makefile" + +echo " * Updating source files" +for TARGET in ${!TARGETS[@]}; do + for SRC in $(ls ${TARGETS[${TARGET}]}); do + diff -q $SRC $TARGET 2> /dev/null + if [ "$?" != "0" ]; then + echo " - Copying $SRC --> $TARGET" + cp $SRC $TARGET + fi + done +done + +echo " * Patching source files" +for PATCH in $(cat patches/patches.list); do + patch -p1 < patches/$PATCH +done + +echo "Done" diff --git a/tst/tst_thermal.c b/tst/tst_thermal.c index 20e894d..ff89c13 100644 --- a/tst/tst_thermal.c +++ b/tst/tst_thermal.c @@ -11,7 +11,7 @@ #include <sys/stat.h> #include <sys/types.h> -#include "libthermal.h" +#include "thermal.h" #define MAX_EVENTS 10 |