147c4b0deSDaniel Lezcano // SPDX-License-Identifier: LGPL-2.1+
247c4b0deSDaniel Lezcano // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
347c4b0deSDaniel Lezcano #define _GNU_SOURCE
447c4b0deSDaniel Lezcano #include <errno.h>
547c4b0deSDaniel Lezcano #include <stdio.h>
647c4b0deSDaniel Lezcano #include <stdlib.h>
747c4b0deSDaniel Lezcano #include <unistd.h>
847c4b0deSDaniel Lezcano
947c4b0deSDaniel Lezcano #include <thermal.h>
1047c4b0deSDaniel Lezcano #include "thermal_nl.h"
1147c4b0deSDaniel Lezcano
1247c4b0deSDaniel Lezcano static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = {
1347c4b0deSDaniel Lezcano /* Thermal zone */
1447c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ] = { .type = NLA_NESTED },
1547c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_ID] = { .type = NLA_U32 },
1647c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_TEMP] = { .type = NLA_U32 },
1747c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_TRIP] = { .type = NLA_NESTED },
1847c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_TRIP_ID] = { .type = NLA_U32 },
1947c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_TRIP_TEMP] = { .type = NLA_U32 },
2047c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_TRIP_TYPE] = { .type = NLA_U32 },
2147c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_TRIP_HYST] = { .type = NLA_U32 },
2247c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_MODE] = { .type = NLA_U32 },
2347c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT] = { .type = NLA_U32 },
2447c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_NAME] = { .type = NLA_STRING },
2547c4b0deSDaniel Lezcano
2647c4b0deSDaniel Lezcano /* Governor(s) */
2747c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_GOV] = { .type = NLA_NESTED },
2847c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_TZ_GOV_NAME] = { .type = NLA_STRING },
2947c4b0deSDaniel Lezcano
3047c4b0deSDaniel Lezcano /* Cooling devices */
3147c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_CDEV] = { .type = NLA_NESTED },
3247c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_CDEV_ID] = { .type = NLA_U32 },
3347c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_CDEV_CUR_STATE] = { .type = NLA_U32 },
3447c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_CDEV_MAX_STATE] = { .type = NLA_U32 },
3547c4b0deSDaniel Lezcano [THERMAL_GENL_ATTR_CDEV_NAME] = { .type = NLA_STRING },
3647c4b0deSDaniel Lezcano };
3747c4b0deSDaniel Lezcano
parse_tz_get(struct genl_info * info,struct thermal_zone ** tz)3847c4b0deSDaniel Lezcano static int parse_tz_get(struct genl_info *info, struct thermal_zone **tz)
3947c4b0deSDaniel Lezcano {
4047c4b0deSDaniel Lezcano struct nlattr *attr;
4147c4b0deSDaniel Lezcano struct thermal_zone *__tz = NULL;
4247c4b0deSDaniel Lezcano size_t size = 0;
4347c4b0deSDaniel Lezcano int rem;
4447c4b0deSDaniel Lezcano
4547c4b0deSDaniel Lezcano nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_TZ], rem) {
4647c4b0deSDaniel Lezcano
4747c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_ID) {
4847c4b0deSDaniel Lezcano
4947c4b0deSDaniel Lezcano size++;
5047c4b0deSDaniel Lezcano
5147c4b0deSDaniel Lezcano __tz = realloc(__tz, sizeof(*__tz) * (size + 2));
5247c4b0deSDaniel Lezcano if (!__tz)
5347c4b0deSDaniel Lezcano return THERMAL_ERROR;
5447c4b0deSDaniel Lezcano
5547c4b0deSDaniel Lezcano __tz[size - 1].id = nla_get_u32(attr);
5647c4b0deSDaniel Lezcano }
5747c4b0deSDaniel Lezcano
5847c4b0deSDaniel Lezcano
5947c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_NAME)
6047c4b0deSDaniel Lezcano nla_strlcpy(__tz[size - 1].name, attr,
6147c4b0deSDaniel Lezcano THERMAL_NAME_LENGTH);
6247c4b0deSDaniel Lezcano }
6347c4b0deSDaniel Lezcano
6447c4b0deSDaniel Lezcano if (__tz)
6547c4b0deSDaniel Lezcano __tz[size].id = -1;
6647c4b0deSDaniel Lezcano
6747c4b0deSDaniel Lezcano *tz = __tz;
6847c4b0deSDaniel Lezcano
6947c4b0deSDaniel Lezcano return THERMAL_SUCCESS;
7047c4b0deSDaniel Lezcano }
7147c4b0deSDaniel Lezcano
parse_cdev_get(struct genl_info * info,struct thermal_cdev ** cdev)7247c4b0deSDaniel Lezcano static int parse_cdev_get(struct genl_info *info, struct thermal_cdev **cdev)
7347c4b0deSDaniel Lezcano {
7447c4b0deSDaniel Lezcano struct nlattr *attr;
7547c4b0deSDaniel Lezcano struct thermal_cdev *__cdev = NULL;
7647c4b0deSDaniel Lezcano size_t size = 0;
7747c4b0deSDaniel Lezcano int rem;
7847c4b0deSDaniel Lezcano
7947c4b0deSDaniel Lezcano nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_CDEV], rem) {
8047c4b0deSDaniel Lezcano
8147c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_ID) {
8247c4b0deSDaniel Lezcano
8347c4b0deSDaniel Lezcano size++;
8447c4b0deSDaniel Lezcano
8547c4b0deSDaniel Lezcano __cdev = realloc(__cdev, sizeof(*__cdev) * (size + 2));
8647c4b0deSDaniel Lezcano if (!__cdev)
8747c4b0deSDaniel Lezcano return THERMAL_ERROR;
8847c4b0deSDaniel Lezcano
8947c4b0deSDaniel Lezcano __cdev[size - 1].id = nla_get_u32(attr);
9047c4b0deSDaniel Lezcano }
9147c4b0deSDaniel Lezcano
9247c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_NAME) {
9347c4b0deSDaniel Lezcano nla_strlcpy(__cdev[size - 1].name, attr,
9447c4b0deSDaniel Lezcano THERMAL_NAME_LENGTH);
9547c4b0deSDaniel Lezcano }
9647c4b0deSDaniel Lezcano
9747c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_CUR_STATE)
9847c4b0deSDaniel Lezcano __cdev[size - 1].cur_state = nla_get_u32(attr);
9947c4b0deSDaniel Lezcano
10047c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_MAX_STATE)
10147c4b0deSDaniel Lezcano __cdev[size - 1].max_state = nla_get_u32(attr);
10247c4b0deSDaniel Lezcano }
10347c4b0deSDaniel Lezcano
10447c4b0deSDaniel Lezcano if (__cdev)
10547c4b0deSDaniel Lezcano __cdev[size].id = -1;
10647c4b0deSDaniel Lezcano
10747c4b0deSDaniel Lezcano *cdev = __cdev;
10847c4b0deSDaniel Lezcano
10947c4b0deSDaniel Lezcano return THERMAL_SUCCESS;
11047c4b0deSDaniel Lezcano }
11147c4b0deSDaniel Lezcano
parse_tz_get_trip(struct genl_info * info,struct thermal_zone * tz)11247c4b0deSDaniel Lezcano static int parse_tz_get_trip(struct genl_info *info, struct thermal_zone *tz)
11347c4b0deSDaniel Lezcano {
11447c4b0deSDaniel Lezcano struct nlattr *attr;
11547c4b0deSDaniel Lezcano struct thermal_trip *__tt = NULL;
11647c4b0deSDaniel Lezcano size_t size = 0;
11747c4b0deSDaniel Lezcano int rem;
11847c4b0deSDaniel Lezcano
11947c4b0deSDaniel Lezcano nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_TZ_TRIP], rem) {
12047c4b0deSDaniel Lezcano
12147c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_ID) {
12247c4b0deSDaniel Lezcano
12347c4b0deSDaniel Lezcano size++;
12447c4b0deSDaniel Lezcano
12547c4b0deSDaniel Lezcano __tt = realloc(__tt, sizeof(*__tt) * (size + 2));
12647c4b0deSDaniel Lezcano if (!__tt)
12747c4b0deSDaniel Lezcano return THERMAL_ERROR;
12847c4b0deSDaniel Lezcano
12947c4b0deSDaniel Lezcano __tt[size - 1].id = nla_get_u32(attr);
13047c4b0deSDaniel Lezcano }
13147c4b0deSDaniel Lezcano
13247c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_TYPE)
13347c4b0deSDaniel Lezcano __tt[size - 1].type = nla_get_u32(attr);
13447c4b0deSDaniel Lezcano
13547c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_TEMP)
13647c4b0deSDaniel Lezcano __tt[size - 1].temp = nla_get_u32(attr);
13747c4b0deSDaniel Lezcano
13847c4b0deSDaniel Lezcano if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_HYST)
13947c4b0deSDaniel Lezcano __tt[size - 1].hyst = nla_get_u32(attr);
14047c4b0deSDaniel Lezcano }
14147c4b0deSDaniel Lezcano
14247c4b0deSDaniel Lezcano if (__tt)
14347c4b0deSDaniel Lezcano __tt[size].id = -1;
14447c4b0deSDaniel Lezcano
14547c4b0deSDaniel Lezcano tz->trip = __tt;
14647c4b0deSDaniel Lezcano
14747c4b0deSDaniel Lezcano return THERMAL_SUCCESS;
14847c4b0deSDaniel Lezcano }
14947c4b0deSDaniel Lezcano
parse_tz_get_temp(struct genl_info * info,struct thermal_zone * tz)15047c4b0deSDaniel Lezcano static int parse_tz_get_temp(struct genl_info *info, struct thermal_zone *tz)
15147c4b0deSDaniel Lezcano {
15247c4b0deSDaniel Lezcano int id = -1;
15347c4b0deSDaniel Lezcano
15447c4b0deSDaniel Lezcano if (info->attrs[THERMAL_GENL_ATTR_TZ_ID])
15547c4b0deSDaniel Lezcano id = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_ID]);
15647c4b0deSDaniel Lezcano
15747c4b0deSDaniel Lezcano if (tz->id != id)
15847c4b0deSDaniel Lezcano return THERMAL_ERROR;
15947c4b0deSDaniel Lezcano
16047c4b0deSDaniel Lezcano if (info->attrs[THERMAL_GENL_ATTR_TZ_TEMP])
16147c4b0deSDaniel Lezcano tz->temp = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_TEMP]);
16247c4b0deSDaniel Lezcano
16347c4b0deSDaniel Lezcano return THERMAL_SUCCESS;
16447c4b0deSDaniel Lezcano }
16547c4b0deSDaniel Lezcano
parse_tz_get_gov(struct genl_info * info,struct thermal_zone * tz)16647c4b0deSDaniel Lezcano static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz)
16747c4b0deSDaniel Lezcano {
16847c4b0deSDaniel Lezcano int id = -1;
16947c4b0deSDaniel Lezcano
17047c4b0deSDaniel Lezcano if (info->attrs[THERMAL_GENL_ATTR_TZ_ID])
17147c4b0deSDaniel Lezcano id = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_ID]);
17247c4b0deSDaniel Lezcano
17347c4b0deSDaniel Lezcano if (tz->id != id)
17447c4b0deSDaniel Lezcano return THERMAL_ERROR;
17547c4b0deSDaniel Lezcano
17647c4b0deSDaniel Lezcano if (info->attrs[THERMAL_GENL_ATTR_TZ_GOV_NAME]) {
17747c4b0deSDaniel Lezcano nla_strlcpy(tz->governor,
17847c4b0deSDaniel Lezcano info->attrs[THERMAL_GENL_ATTR_TZ_GOV_NAME],
17947c4b0deSDaniel Lezcano THERMAL_NAME_LENGTH);
18047c4b0deSDaniel Lezcano }
18147c4b0deSDaniel Lezcano
18247c4b0deSDaniel Lezcano return THERMAL_SUCCESS;
18347c4b0deSDaniel Lezcano }
18447c4b0deSDaniel Lezcano
handle_netlink(struct nl_cache_ops * unused,struct genl_cmd * cmd,struct genl_info * info,void * arg)18547c4b0deSDaniel Lezcano static int handle_netlink(struct nl_cache_ops *unused,
18647c4b0deSDaniel Lezcano struct genl_cmd *cmd,
18747c4b0deSDaniel Lezcano struct genl_info *info, void *arg)
18847c4b0deSDaniel Lezcano {
18947c4b0deSDaniel Lezcano int ret;
19047c4b0deSDaniel Lezcano
19147c4b0deSDaniel Lezcano switch (cmd->c_id) {
19247c4b0deSDaniel Lezcano
19347c4b0deSDaniel Lezcano case THERMAL_GENL_CMD_TZ_GET_ID:
19447c4b0deSDaniel Lezcano ret = parse_tz_get(info, arg);
19547c4b0deSDaniel Lezcano break;
19647c4b0deSDaniel Lezcano
19747c4b0deSDaniel Lezcano case THERMAL_GENL_CMD_CDEV_GET:
19847c4b0deSDaniel Lezcano ret = parse_cdev_get(info, arg);
19947c4b0deSDaniel Lezcano break;
20047c4b0deSDaniel Lezcano
20147c4b0deSDaniel Lezcano case THERMAL_GENL_CMD_TZ_GET_TEMP:
20247c4b0deSDaniel Lezcano ret = parse_tz_get_temp(info, arg);
20347c4b0deSDaniel Lezcano break;
20447c4b0deSDaniel Lezcano
20547c4b0deSDaniel Lezcano case THERMAL_GENL_CMD_TZ_GET_TRIP:
20647c4b0deSDaniel Lezcano ret = parse_tz_get_trip(info, arg);
20747c4b0deSDaniel Lezcano break;
20847c4b0deSDaniel Lezcano
20947c4b0deSDaniel Lezcano case THERMAL_GENL_CMD_TZ_GET_GOV:
21047c4b0deSDaniel Lezcano ret = parse_tz_get_gov(info, arg);
21147c4b0deSDaniel Lezcano break;
21247c4b0deSDaniel Lezcano
21347c4b0deSDaniel Lezcano default:
21447c4b0deSDaniel Lezcano return THERMAL_ERROR;
215f21b57ebSJiapeng Chong }
21647c4b0deSDaniel Lezcano
21747c4b0deSDaniel Lezcano return ret;
21847c4b0deSDaniel Lezcano }
21947c4b0deSDaniel Lezcano
22047c4b0deSDaniel Lezcano static struct genl_cmd thermal_cmds[] = {
22147c4b0deSDaniel Lezcano {
22247c4b0deSDaniel Lezcano .c_id = THERMAL_GENL_CMD_TZ_GET_ID,
22347c4b0deSDaniel Lezcano .c_name = (char *)"List thermal zones",
22447c4b0deSDaniel Lezcano .c_msg_parser = handle_netlink,
22547c4b0deSDaniel Lezcano .c_maxattr = THERMAL_GENL_ATTR_MAX,
22647c4b0deSDaniel Lezcano .c_attr_policy = thermal_genl_policy,
22747c4b0deSDaniel Lezcano },
22847c4b0deSDaniel Lezcano {
22947c4b0deSDaniel Lezcano .c_id = THERMAL_GENL_CMD_TZ_GET_GOV,
23047c4b0deSDaniel Lezcano .c_name = (char *)"Get governor",
23147c4b0deSDaniel Lezcano .c_msg_parser = handle_netlink,
23247c4b0deSDaniel Lezcano .c_maxattr = THERMAL_GENL_ATTR_MAX,
23347c4b0deSDaniel Lezcano .c_attr_policy = thermal_genl_policy,
23447c4b0deSDaniel Lezcano },
23547c4b0deSDaniel Lezcano {
23647c4b0deSDaniel Lezcano .c_id = THERMAL_GENL_CMD_TZ_GET_TEMP,
23747c4b0deSDaniel Lezcano .c_name = (char *)"Get thermal zone temperature",
23847c4b0deSDaniel Lezcano .c_msg_parser = handle_netlink,
23947c4b0deSDaniel Lezcano .c_maxattr = THERMAL_GENL_ATTR_MAX,
24047c4b0deSDaniel Lezcano .c_attr_policy = thermal_genl_policy,
24147c4b0deSDaniel Lezcano },
24247c4b0deSDaniel Lezcano {
24347c4b0deSDaniel Lezcano .c_id = THERMAL_GENL_CMD_TZ_GET_TRIP,
24447c4b0deSDaniel Lezcano .c_name = (char *)"Get thermal zone trip points",
24547c4b0deSDaniel Lezcano .c_msg_parser = handle_netlink,
24647c4b0deSDaniel Lezcano .c_maxattr = THERMAL_GENL_ATTR_MAX,
24747c4b0deSDaniel Lezcano .c_attr_policy = thermal_genl_policy,
24847c4b0deSDaniel Lezcano },
24947c4b0deSDaniel Lezcano {
25047c4b0deSDaniel Lezcano .c_id = THERMAL_GENL_CMD_CDEV_GET,
25147c4b0deSDaniel Lezcano .c_name = (char *)"Get cooling devices",
25247c4b0deSDaniel Lezcano .c_msg_parser = handle_netlink,
25347c4b0deSDaniel Lezcano .c_maxattr = THERMAL_GENL_ATTR_MAX,
25447c4b0deSDaniel Lezcano .c_attr_policy = thermal_genl_policy,
25547c4b0deSDaniel Lezcano },
25647c4b0deSDaniel Lezcano };
25747c4b0deSDaniel Lezcano
25847c4b0deSDaniel Lezcano static struct genl_ops thermal_cmd_ops = {
25947c4b0deSDaniel Lezcano .o_name = (char *)"thermal",
26047c4b0deSDaniel Lezcano .o_cmds = thermal_cmds,
26147c4b0deSDaniel Lezcano .o_ncmds = ARRAY_SIZE(thermal_cmds),
26247c4b0deSDaniel Lezcano };
26347c4b0deSDaniel Lezcano
2641b78ac7eSDaniel Lezcano struct cmd_param {
2651b78ac7eSDaniel Lezcano int tz_id;
2661b78ac7eSDaniel Lezcano };
2671b78ac7eSDaniel Lezcano
2681b78ac7eSDaniel Lezcano typedef int (*cmd_cb_t)(struct nl_msg *, struct cmd_param *);
2691b78ac7eSDaniel Lezcano
thermal_genl_tz_id_encode(struct nl_msg * msg,struct cmd_param * p)2701b78ac7eSDaniel Lezcano static int thermal_genl_tz_id_encode(struct nl_msg *msg, struct cmd_param *p)
2711b78ac7eSDaniel Lezcano {
2721b78ac7eSDaniel Lezcano if (p->tz_id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id))
2731b78ac7eSDaniel Lezcano return -1;
2741b78ac7eSDaniel Lezcano
2751b78ac7eSDaniel Lezcano return 0;
2761b78ac7eSDaniel Lezcano }
2771b78ac7eSDaniel Lezcano
thermal_genl_auto(struct thermal_handler * th,cmd_cb_t cmd_cb,struct cmd_param * param,int cmd,int flags,void * arg)2781b78ac7eSDaniel Lezcano static thermal_error_t thermal_genl_auto(struct thermal_handler *th, cmd_cb_t cmd_cb,
2791b78ac7eSDaniel Lezcano struct cmd_param *param,
2801b78ac7eSDaniel Lezcano int cmd, int flags, void *arg)
28147c4b0deSDaniel Lezcano {
282*cc08c2c8SDaniel Lezcano thermal_error_t ret = THERMAL_ERROR;
28347c4b0deSDaniel Lezcano struct nl_msg *msg;
28447c4b0deSDaniel Lezcano void *hdr;
28547c4b0deSDaniel Lezcano
28647c4b0deSDaniel Lezcano msg = nlmsg_alloc();
28747c4b0deSDaniel Lezcano if (!msg)
28847c4b0deSDaniel Lezcano return THERMAL_ERROR;
28947c4b0deSDaniel Lezcano
29047c4b0deSDaniel Lezcano hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, thermal_cmd_ops.o_id,
29147c4b0deSDaniel Lezcano 0, flags, cmd, THERMAL_GENL_VERSION);
29247c4b0deSDaniel Lezcano if (!hdr)
293*cc08c2c8SDaniel Lezcano goto out;
29447c4b0deSDaniel Lezcano
2951b78ac7eSDaniel Lezcano if (cmd_cb && cmd_cb(msg, param))
296*cc08c2c8SDaniel Lezcano goto out;
29747c4b0deSDaniel Lezcano
29847c4b0deSDaniel Lezcano if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg))
299*cc08c2c8SDaniel Lezcano goto out;
30047c4b0deSDaniel Lezcano
301*cc08c2c8SDaniel Lezcano ret = THERMAL_SUCCESS;
302*cc08c2c8SDaniel Lezcano out:
30347c4b0deSDaniel Lezcano nlmsg_free(msg);
30447c4b0deSDaniel Lezcano
305*cc08c2c8SDaniel Lezcano return ret;
30647c4b0deSDaniel Lezcano }
30747c4b0deSDaniel Lezcano
thermal_cmd_get_tz(struct thermal_handler * th,struct thermal_zone ** tz)30847c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz)
30947c4b0deSDaniel Lezcano {
3101b78ac7eSDaniel Lezcano return thermal_genl_auto(th, NULL, NULL, THERMAL_GENL_CMD_TZ_GET_ID,
31147c4b0deSDaniel Lezcano NLM_F_DUMP | NLM_F_ACK, tz);
31247c4b0deSDaniel Lezcano }
31347c4b0deSDaniel Lezcano
thermal_cmd_get_cdev(struct thermal_handler * th,struct thermal_cdev ** tc)31447c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_cdev(struct thermal_handler *th, struct thermal_cdev **tc)
31547c4b0deSDaniel Lezcano {
3161b78ac7eSDaniel Lezcano return thermal_genl_auto(th, NULL, NULL, THERMAL_GENL_CMD_CDEV_GET,
31747c4b0deSDaniel Lezcano NLM_F_DUMP | NLM_F_ACK, tc);
31847c4b0deSDaniel Lezcano }
31947c4b0deSDaniel Lezcano
thermal_cmd_get_trip(struct thermal_handler * th,struct thermal_zone * tz)32047c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_trip(struct thermal_handler *th, struct thermal_zone *tz)
32147c4b0deSDaniel Lezcano {
3221b78ac7eSDaniel Lezcano struct cmd_param p = { .tz_id = tz->id };
3231b78ac7eSDaniel Lezcano
3241b78ac7eSDaniel Lezcano return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p,
3251b78ac7eSDaniel Lezcano THERMAL_GENL_CMD_TZ_GET_TRIP, 0, tz);
32647c4b0deSDaniel Lezcano }
32747c4b0deSDaniel Lezcano
thermal_cmd_get_governor(struct thermal_handler * th,struct thermal_zone * tz)32847c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_governor(struct thermal_handler *th, struct thermal_zone *tz)
32947c4b0deSDaniel Lezcano {
3301b78ac7eSDaniel Lezcano struct cmd_param p = { .tz_id = tz->id };
3311b78ac7eSDaniel Lezcano
3321b78ac7eSDaniel Lezcano return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p,
3331b78ac7eSDaniel Lezcano THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz);
33447c4b0deSDaniel Lezcano }
33547c4b0deSDaniel Lezcano
thermal_cmd_get_temp(struct thermal_handler * th,struct thermal_zone * tz)33647c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz)
33747c4b0deSDaniel Lezcano {
3381b78ac7eSDaniel Lezcano struct cmd_param p = { .tz_id = tz->id };
3391b78ac7eSDaniel Lezcano
3401b78ac7eSDaniel Lezcano return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p,
3411b78ac7eSDaniel Lezcano THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz);
34247c4b0deSDaniel Lezcano }
34347c4b0deSDaniel Lezcano
thermal_cmd_exit(struct thermal_handler * th)34447c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_exit(struct thermal_handler *th)
34547c4b0deSDaniel Lezcano {
34647c4b0deSDaniel Lezcano if (genl_unregister_family(&thermal_cmd_ops))
34747c4b0deSDaniel Lezcano return THERMAL_ERROR;
34847c4b0deSDaniel Lezcano
34947c4b0deSDaniel Lezcano nl_thermal_disconnect(th->sk_cmd, th->cb_cmd);
35047c4b0deSDaniel Lezcano
35147c4b0deSDaniel Lezcano return THERMAL_SUCCESS;
35247c4b0deSDaniel Lezcano }
35347c4b0deSDaniel Lezcano
thermal_cmd_init(struct thermal_handler * th)35447c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_init(struct thermal_handler *th)
35547c4b0deSDaniel Lezcano {
35647c4b0deSDaniel Lezcano int ret;
35747c4b0deSDaniel Lezcano int family;
35847c4b0deSDaniel Lezcano
35947c4b0deSDaniel Lezcano if (nl_thermal_connect(&th->sk_cmd, &th->cb_cmd))
36047c4b0deSDaniel Lezcano return THERMAL_ERROR;
36147c4b0deSDaniel Lezcano
36247c4b0deSDaniel Lezcano ret = genl_register_family(&thermal_cmd_ops);
36347c4b0deSDaniel Lezcano if (ret)
36447c4b0deSDaniel Lezcano return THERMAL_ERROR;
36547c4b0deSDaniel Lezcano
36647c4b0deSDaniel Lezcano ret = genl_ops_resolve(th->sk_cmd, &thermal_cmd_ops);
36747c4b0deSDaniel Lezcano if (ret)
36847c4b0deSDaniel Lezcano return THERMAL_ERROR;
36947c4b0deSDaniel Lezcano
37047c4b0deSDaniel Lezcano family = genl_ctrl_resolve(th->sk_cmd, "nlctrl");
37147c4b0deSDaniel Lezcano if (family != GENL_ID_CTRL)
37247c4b0deSDaniel Lezcano return THERMAL_ERROR;
37347c4b0deSDaniel Lezcano
37447c4b0deSDaniel Lezcano return THERMAL_SUCCESS;
37547c4b0deSDaniel Lezcano }
376