xref: /openbmc/linux/tools/lib/thermal/commands.c (revision f21b57eb)
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;
215*f21b57ebSJiapeng 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 
thermal_genl_auto(struct thermal_handler * th,int id,int cmd,int flags,void * arg)26447c4b0deSDaniel Lezcano static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int cmd,
26547c4b0deSDaniel Lezcano 					 int flags, void *arg)
26647c4b0deSDaniel Lezcano {
26747c4b0deSDaniel Lezcano 	struct nl_msg *msg;
26847c4b0deSDaniel Lezcano 	void *hdr;
26947c4b0deSDaniel Lezcano 
27047c4b0deSDaniel Lezcano 	msg = nlmsg_alloc();
27147c4b0deSDaniel Lezcano 	if (!msg)
27247c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
27347c4b0deSDaniel Lezcano 
27447c4b0deSDaniel Lezcano 	hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, thermal_cmd_ops.o_id,
27547c4b0deSDaniel Lezcano 			  0, flags, cmd, THERMAL_GENL_VERSION);
27647c4b0deSDaniel Lezcano 	if (!hdr)
27747c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
27847c4b0deSDaniel Lezcano 
27947c4b0deSDaniel Lezcano 	if (id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id))
28047c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
28147c4b0deSDaniel Lezcano 
28247c4b0deSDaniel Lezcano 	if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg))
28347c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
28447c4b0deSDaniel Lezcano 
28547c4b0deSDaniel Lezcano 	nlmsg_free(msg);
28647c4b0deSDaniel Lezcano 
28747c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
28847c4b0deSDaniel Lezcano }
28947c4b0deSDaniel Lezcano 
thermal_cmd_get_tz(struct thermal_handler * th,struct thermal_zone ** tz)29047c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz)
29147c4b0deSDaniel Lezcano {
29247c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_TZ_GET_ID,
29347c4b0deSDaniel Lezcano 				 NLM_F_DUMP | NLM_F_ACK, tz);
29447c4b0deSDaniel Lezcano }
29547c4b0deSDaniel Lezcano 
thermal_cmd_get_cdev(struct thermal_handler * th,struct thermal_cdev ** tc)29647c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_cdev(struct thermal_handler *th, struct thermal_cdev **tc)
29747c4b0deSDaniel Lezcano {
29847c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_CDEV_GET,
29947c4b0deSDaniel Lezcano 				 NLM_F_DUMP | NLM_F_ACK, tc);
30047c4b0deSDaniel Lezcano }
30147c4b0deSDaniel Lezcano 
thermal_cmd_get_trip(struct thermal_handler * th,struct thermal_zone * tz)30247c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_trip(struct thermal_handler *th, struct thermal_zone *tz)
30347c4b0deSDaniel Lezcano {
30447c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TRIP,
30547c4b0deSDaniel Lezcano 				 0, tz);
30647c4b0deSDaniel Lezcano }
30747c4b0deSDaniel Lezcano 
thermal_cmd_get_governor(struct thermal_handler * th,struct thermal_zone * tz)30847c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_governor(struct thermal_handler *th, struct thermal_zone *tz)
30947c4b0deSDaniel Lezcano {
31047c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz);
31147c4b0deSDaniel Lezcano }
31247c4b0deSDaniel Lezcano 
thermal_cmd_get_temp(struct thermal_handler * th,struct thermal_zone * tz)31347c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz)
31447c4b0deSDaniel Lezcano {
31547c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz);
31647c4b0deSDaniel Lezcano }
31747c4b0deSDaniel Lezcano 
thermal_cmd_exit(struct thermal_handler * th)31847c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_exit(struct thermal_handler *th)
31947c4b0deSDaniel Lezcano {
32047c4b0deSDaniel Lezcano 	if (genl_unregister_family(&thermal_cmd_ops))
32147c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
32247c4b0deSDaniel Lezcano 
32347c4b0deSDaniel Lezcano 	nl_thermal_disconnect(th->sk_cmd, th->cb_cmd);
32447c4b0deSDaniel Lezcano 
32547c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
32647c4b0deSDaniel Lezcano }
32747c4b0deSDaniel Lezcano 
thermal_cmd_init(struct thermal_handler * th)32847c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_init(struct thermal_handler *th)
32947c4b0deSDaniel Lezcano {
33047c4b0deSDaniel Lezcano 	int ret;
33147c4b0deSDaniel Lezcano 	int family;
33247c4b0deSDaniel Lezcano 
33347c4b0deSDaniel Lezcano 	if (nl_thermal_connect(&th->sk_cmd, &th->cb_cmd))
33447c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
33547c4b0deSDaniel Lezcano 
33647c4b0deSDaniel Lezcano 	ret = genl_register_family(&thermal_cmd_ops);
33747c4b0deSDaniel Lezcano 	if (ret)
33847c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
33947c4b0deSDaniel Lezcano 
34047c4b0deSDaniel Lezcano 	ret = genl_ops_resolve(th->sk_cmd, &thermal_cmd_ops);
34147c4b0deSDaniel Lezcano 	if (ret)
34247c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
34347c4b0deSDaniel Lezcano 
34447c4b0deSDaniel Lezcano 	family = genl_ctrl_resolve(th->sk_cmd, "nlctrl");
34547c4b0deSDaniel Lezcano 	if (family != GENL_ID_CTRL)
34647c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
34747c4b0deSDaniel Lezcano 
34847c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
34947c4b0deSDaniel Lezcano }
350