xref: /openbmc/linux/tools/lib/thermal/commands.c (revision 47c4b0de)
1*47c4b0deSDaniel Lezcano // SPDX-License-Identifier: LGPL-2.1+
2*47c4b0deSDaniel Lezcano // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
3*47c4b0deSDaniel Lezcano #define _GNU_SOURCE
4*47c4b0deSDaniel Lezcano #include <errno.h>
5*47c4b0deSDaniel Lezcano #include <stdio.h>
6*47c4b0deSDaniel Lezcano #include <stdlib.h>
7*47c4b0deSDaniel Lezcano #include <unistd.h>
8*47c4b0deSDaniel Lezcano 
9*47c4b0deSDaniel Lezcano #include <thermal.h>
10*47c4b0deSDaniel Lezcano #include "thermal_nl.h"
11*47c4b0deSDaniel Lezcano 
12*47c4b0deSDaniel Lezcano static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = {
13*47c4b0deSDaniel Lezcano 	/* Thermal zone */
14*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ]                  = { .type = NLA_NESTED },
15*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_ID]               = { .type = NLA_U32 },
16*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_TEMP]             = { .type = NLA_U32 },
17*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_TRIP]             = { .type = NLA_NESTED },
18*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_TRIP_ID]          = { .type = NLA_U32 },
19*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]        = { .type = NLA_U32 },
20*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]        = { .type = NLA_U32 },
21*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_TRIP_HYST]        = { .type = NLA_U32 },
22*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_MODE]             = { .type = NLA_U32 },
23*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT]      = { .type = NLA_U32 },
24*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_NAME]             = { .type = NLA_STRING },
25*47c4b0deSDaniel Lezcano 
26*47c4b0deSDaniel Lezcano 	/* Governor(s) */
27*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_GOV]              = { .type = NLA_NESTED },
28*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_TZ_GOV_NAME]         = { .type = NLA_STRING },
29*47c4b0deSDaniel Lezcano 
30*47c4b0deSDaniel Lezcano 	/* Cooling devices */
31*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_CDEV]                = { .type = NLA_NESTED },
32*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_CDEV_ID]             = { .type = NLA_U32 },
33*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_CDEV_CUR_STATE]      = { .type = NLA_U32 },
34*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_CDEV_MAX_STATE]      = { .type = NLA_U32 },
35*47c4b0deSDaniel Lezcano 	[THERMAL_GENL_ATTR_CDEV_NAME]           = { .type = NLA_STRING },
36*47c4b0deSDaniel Lezcano };
37*47c4b0deSDaniel Lezcano 
38*47c4b0deSDaniel Lezcano static int parse_tz_get(struct genl_info *info, struct thermal_zone **tz)
39*47c4b0deSDaniel Lezcano {
40*47c4b0deSDaniel Lezcano 	struct nlattr *attr;
41*47c4b0deSDaniel Lezcano 	struct thermal_zone *__tz = NULL;
42*47c4b0deSDaniel Lezcano 	size_t size = 0;
43*47c4b0deSDaniel Lezcano 	int rem;
44*47c4b0deSDaniel Lezcano 
45*47c4b0deSDaniel Lezcano 	nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_TZ], rem) {
46*47c4b0deSDaniel Lezcano 
47*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_ID) {
48*47c4b0deSDaniel Lezcano 
49*47c4b0deSDaniel Lezcano 			size++;
50*47c4b0deSDaniel Lezcano 
51*47c4b0deSDaniel Lezcano 			__tz = realloc(__tz, sizeof(*__tz) * (size + 2));
52*47c4b0deSDaniel Lezcano 			if (!__tz)
53*47c4b0deSDaniel Lezcano 				return THERMAL_ERROR;
54*47c4b0deSDaniel Lezcano 
55*47c4b0deSDaniel Lezcano 			__tz[size - 1].id = nla_get_u32(attr);
56*47c4b0deSDaniel Lezcano 		}
57*47c4b0deSDaniel Lezcano 
58*47c4b0deSDaniel Lezcano 
59*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_NAME)
60*47c4b0deSDaniel Lezcano 			nla_strlcpy(__tz[size - 1].name, attr,
61*47c4b0deSDaniel Lezcano 				    THERMAL_NAME_LENGTH);
62*47c4b0deSDaniel Lezcano 	}
63*47c4b0deSDaniel Lezcano 
64*47c4b0deSDaniel Lezcano 	if (__tz)
65*47c4b0deSDaniel Lezcano 		__tz[size].id = -1;
66*47c4b0deSDaniel Lezcano 
67*47c4b0deSDaniel Lezcano 	*tz = __tz;
68*47c4b0deSDaniel Lezcano 
69*47c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
70*47c4b0deSDaniel Lezcano }
71*47c4b0deSDaniel Lezcano 
72*47c4b0deSDaniel Lezcano static int parse_cdev_get(struct genl_info *info, struct thermal_cdev **cdev)
73*47c4b0deSDaniel Lezcano {
74*47c4b0deSDaniel Lezcano 	struct nlattr *attr;
75*47c4b0deSDaniel Lezcano 	struct thermal_cdev *__cdev = NULL;
76*47c4b0deSDaniel Lezcano 	size_t size = 0;
77*47c4b0deSDaniel Lezcano 	int rem;
78*47c4b0deSDaniel Lezcano 
79*47c4b0deSDaniel Lezcano 	nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_CDEV], rem) {
80*47c4b0deSDaniel Lezcano 
81*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_ID) {
82*47c4b0deSDaniel Lezcano 
83*47c4b0deSDaniel Lezcano 			size++;
84*47c4b0deSDaniel Lezcano 
85*47c4b0deSDaniel Lezcano 			__cdev = realloc(__cdev, sizeof(*__cdev) * (size + 2));
86*47c4b0deSDaniel Lezcano 			if (!__cdev)
87*47c4b0deSDaniel Lezcano 				return THERMAL_ERROR;
88*47c4b0deSDaniel Lezcano 
89*47c4b0deSDaniel Lezcano 			__cdev[size - 1].id = nla_get_u32(attr);
90*47c4b0deSDaniel Lezcano 		}
91*47c4b0deSDaniel Lezcano 
92*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_NAME) {
93*47c4b0deSDaniel Lezcano 			nla_strlcpy(__cdev[size - 1].name, attr,
94*47c4b0deSDaniel Lezcano 				    THERMAL_NAME_LENGTH);
95*47c4b0deSDaniel Lezcano 		}
96*47c4b0deSDaniel Lezcano 
97*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_CUR_STATE)
98*47c4b0deSDaniel Lezcano 			__cdev[size - 1].cur_state = nla_get_u32(attr);
99*47c4b0deSDaniel Lezcano 
100*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_CDEV_MAX_STATE)
101*47c4b0deSDaniel Lezcano 			__cdev[size - 1].max_state = nla_get_u32(attr);
102*47c4b0deSDaniel Lezcano 	}
103*47c4b0deSDaniel Lezcano 
104*47c4b0deSDaniel Lezcano 	if (__cdev)
105*47c4b0deSDaniel Lezcano 		__cdev[size].id = -1;
106*47c4b0deSDaniel Lezcano 
107*47c4b0deSDaniel Lezcano 	*cdev = __cdev;
108*47c4b0deSDaniel Lezcano 
109*47c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
110*47c4b0deSDaniel Lezcano }
111*47c4b0deSDaniel Lezcano 
112*47c4b0deSDaniel Lezcano static int parse_tz_get_trip(struct genl_info *info, struct thermal_zone *tz)
113*47c4b0deSDaniel Lezcano {
114*47c4b0deSDaniel Lezcano 	struct nlattr *attr;
115*47c4b0deSDaniel Lezcano 	struct thermal_trip *__tt = NULL;
116*47c4b0deSDaniel Lezcano 	size_t size = 0;
117*47c4b0deSDaniel Lezcano 	int rem;
118*47c4b0deSDaniel Lezcano 
119*47c4b0deSDaniel Lezcano 	nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_TZ_TRIP], rem) {
120*47c4b0deSDaniel Lezcano 
121*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_ID) {
122*47c4b0deSDaniel Lezcano 
123*47c4b0deSDaniel Lezcano 			size++;
124*47c4b0deSDaniel Lezcano 
125*47c4b0deSDaniel Lezcano 			__tt = realloc(__tt, sizeof(*__tt) * (size + 2));
126*47c4b0deSDaniel Lezcano 			if (!__tt)
127*47c4b0deSDaniel Lezcano 				return THERMAL_ERROR;
128*47c4b0deSDaniel Lezcano 
129*47c4b0deSDaniel Lezcano 			__tt[size - 1].id = nla_get_u32(attr);
130*47c4b0deSDaniel Lezcano 		}
131*47c4b0deSDaniel Lezcano 
132*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_TYPE)
133*47c4b0deSDaniel Lezcano 			__tt[size - 1].type = nla_get_u32(attr);
134*47c4b0deSDaniel Lezcano 
135*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_TEMP)
136*47c4b0deSDaniel Lezcano 			__tt[size - 1].temp = nla_get_u32(attr);
137*47c4b0deSDaniel Lezcano 
138*47c4b0deSDaniel Lezcano 		if (nla_type(attr) == THERMAL_GENL_ATTR_TZ_TRIP_HYST)
139*47c4b0deSDaniel Lezcano 			__tt[size - 1].hyst = nla_get_u32(attr);
140*47c4b0deSDaniel Lezcano 	}
141*47c4b0deSDaniel Lezcano 
142*47c4b0deSDaniel Lezcano 	if (__tt)
143*47c4b0deSDaniel Lezcano 		__tt[size].id = -1;
144*47c4b0deSDaniel Lezcano 
145*47c4b0deSDaniel Lezcano 	tz->trip = __tt;
146*47c4b0deSDaniel Lezcano 
147*47c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
148*47c4b0deSDaniel Lezcano }
149*47c4b0deSDaniel Lezcano 
150*47c4b0deSDaniel Lezcano static int parse_tz_get_temp(struct genl_info *info, struct thermal_zone *tz)
151*47c4b0deSDaniel Lezcano {
152*47c4b0deSDaniel Lezcano 	int id = -1;
153*47c4b0deSDaniel Lezcano 
154*47c4b0deSDaniel Lezcano 	if (info->attrs[THERMAL_GENL_ATTR_TZ_ID])
155*47c4b0deSDaniel Lezcano 		id = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_ID]);
156*47c4b0deSDaniel Lezcano 
157*47c4b0deSDaniel Lezcano 	if (tz->id != id)
158*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
159*47c4b0deSDaniel Lezcano 
160*47c4b0deSDaniel Lezcano 	if (info->attrs[THERMAL_GENL_ATTR_TZ_TEMP])
161*47c4b0deSDaniel Lezcano 		tz->temp = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_TEMP]);
162*47c4b0deSDaniel Lezcano 
163*47c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
164*47c4b0deSDaniel Lezcano }
165*47c4b0deSDaniel Lezcano 
166*47c4b0deSDaniel Lezcano static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz)
167*47c4b0deSDaniel Lezcano {
168*47c4b0deSDaniel Lezcano 	int id = -1;
169*47c4b0deSDaniel Lezcano 
170*47c4b0deSDaniel Lezcano 	if (info->attrs[THERMAL_GENL_ATTR_TZ_ID])
171*47c4b0deSDaniel Lezcano 		id = nla_get_u32(info->attrs[THERMAL_GENL_ATTR_TZ_ID]);
172*47c4b0deSDaniel Lezcano 
173*47c4b0deSDaniel Lezcano 	if (tz->id != id)
174*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
175*47c4b0deSDaniel Lezcano 
176*47c4b0deSDaniel Lezcano 	if (info->attrs[THERMAL_GENL_ATTR_TZ_GOV_NAME]) {
177*47c4b0deSDaniel Lezcano 		nla_strlcpy(tz->governor,
178*47c4b0deSDaniel Lezcano 			    info->attrs[THERMAL_GENL_ATTR_TZ_GOV_NAME],
179*47c4b0deSDaniel Lezcano 			    THERMAL_NAME_LENGTH);
180*47c4b0deSDaniel Lezcano 	}
181*47c4b0deSDaniel Lezcano 
182*47c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
183*47c4b0deSDaniel Lezcano }
184*47c4b0deSDaniel Lezcano 
185*47c4b0deSDaniel Lezcano static int handle_netlink(struct nl_cache_ops *unused,
186*47c4b0deSDaniel Lezcano 			  struct genl_cmd *cmd,
187*47c4b0deSDaniel Lezcano 			  struct genl_info *info, void *arg)
188*47c4b0deSDaniel Lezcano {
189*47c4b0deSDaniel Lezcano 	int ret;
190*47c4b0deSDaniel Lezcano 
191*47c4b0deSDaniel Lezcano 	switch (cmd->c_id) {
192*47c4b0deSDaniel Lezcano 
193*47c4b0deSDaniel Lezcano 	case THERMAL_GENL_CMD_TZ_GET_ID:
194*47c4b0deSDaniel Lezcano 		ret = parse_tz_get(info, arg);
195*47c4b0deSDaniel Lezcano 		break;
196*47c4b0deSDaniel Lezcano 
197*47c4b0deSDaniel Lezcano 	case THERMAL_GENL_CMD_CDEV_GET:
198*47c4b0deSDaniel Lezcano 		ret = parse_cdev_get(info, arg);
199*47c4b0deSDaniel Lezcano 		break;
200*47c4b0deSDaniel Lezcano 
201*47c4b0deSDaniel Lezcano 	case THERMAL_GENL_CMD_TZ_GET_TEMP:
202*47c4b0deSDaniel Lezcano 		ret = parse_tz_get_temp(info, arg);
203*47c4b0deSDaniel Lezcano 		break;
204*47c4b0deSDaniel Lezcano 
205*47c4b0deSDaniel Lezcano 	case THERMAL_GENL_CMD_TZ_GET_TRIP:
206*47c4b0deSDaniel Lezcano 		ret = parse_tz_get_trip(info, arg);
207*47c4b0deSDaniel Lezcano 		break;
208*47c4b0deSDaniel Lezcano 
209*47c4b0deSDaniel Lezcano 	case THERMAL_GENL_CMD_TZ_GET_GOV:
210*47c4b0deSDaniel Lezcano 		ret = parse_tz_get_gov(info, arg);
211*47c4b0deSDaniel Lezcano 		break;
212*47c4b0deSDaniel Lezcano 
213*47c4b0deSDaniel Lezcano 	default:
214*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
215*47c4b0deSDaniel Lezcano 	};
216*47c4b0deSDaniel Lezcano 
217*47c4b0deSDaniel Lezcano 	return ret;
218*47c4b0deSDaniel Lezcano }
219*47c4b0deSDaniel Lezcano 
220*47c4b0deSDaniel Lezcano static struct genl_cmd thermal_cmds[] = {
221*47c4b0deSDaniel Lezcano 	{
222*47c4b0deSDaniel Lezcano 		.c_id		= THERMAL_GENL_CMD_TZ_GET_ID,
223*47c4b0deSDaniel Lezcano 		.c_name		= (char *)"List thermal zones",
224*47c4b0deSDaniel Lezcano 		.c_msg_parser	= handle_netlink,
225*47c4b0deSDaniel Lezcano 		.c_maxattr	= THERMAL_GENL_ATTR_MAX,
226*47c4b0deSDaniel Lezcano 		.c_attr_policy	= thermal_genl_policy,
227*47c4b0deSDaniel Lezcano 	},
228*47c4b0deSDaniel Lezcano 	{
229*47c4b0deSDaniel Lezcano 		.c_id		= THERMAL_GENL_CMD_TZ_GET_GOV,
230*47c4b0deSDaniel Lezcano 		.c_name		= (char *)"Get governor",
231*47c4b0deSDaniel Lezcano 		.c_msg_parser	= handle_netlink,
232*47c4b0deSDaniel Lezcano 		.c_maxattr	= THERMAL_GENL_ATTR_MAX,
233*47c4b0deSDaniel Lezcano 		.c_attr_policy	= thermal_genl_policy,
234*47c4b0deSDaniel Lezcano 	},
235*47c4b0deSDaniel Lezcano 	{
236*47c4b0deSDaniel Lezcano 		.c_id		= THERMAL_GENL_CMD_TZ_GET_TEMP,
237*47c4b0deSDaniel Lezcano 		.c_name		= (char *)"Get thermal zone temperature",
238*47c4b0deSDaniel Lezcano 		.c_msg_parser	= handle_netlink,
239*47c4b0deSDaniel Lezcano 		.c_maxattr	= THERMAL_GENL_ATTR_MAX,
240*47c4b0deSDaniel Lezcano 		.c_attr_policy	= thermal_genl_policy,
241*47c4b0deSDaniel Lezcano 	},
242*47c4b0deSDaniel Lezcano 	{
243*47c4b0deSDaniel Lezcano 		.c_id		= THERMAL_GENL_CMD_TZ_GET_TRIP,
244*47c4b0deSDaniel Lezcano 		.c_name		= (char *)"Get thermal zone trip points",
245*47c4b0deSDaniel Lezcano 		.c_msg_parser	= handle_netlink,
246*47c4b0deSDaniel Lezcano 		.c_maxattr	= THERMAL_GENL_ATTR_MAX,
247*47c4b0deSDaniel Lezcano 		.c_attr_policy	= thermal_genl_policy,
248*47c4b0deSDaniel Lezcano 	},
249*47c4b0deSDaniel Lezcano 	{
250*47c4b0deSDaniel Lezcano 		.c_id		= THERMAL_GENL_CMD_CDEV_GET,
251*47c4b0deSDaniel Lezcano 		.c_name		= (char *)"Get cooling devices",
252*47c4b0deSDaniel Lezcano 		.c_msg_parser	= handle_netlink,
253*47c4b0deSDaniel Lezcano 		.c_maxattr	= THERMAL_GENL_ATTR_MAX,
254*47c4b0deSDaniel Lezcano 		.c_attr_policy	= thermal_genl_policy,
255*47c4b0deSDaniel Lezcano 	},
256*47c4b0deSDaniel Lezcano };
257*47c4b0deSDaniel Lezcano 
258*47c4b0deSDaniel Lezcano static struct genl_ops thermal_cmd_ops = {
259*47c4b0deSDaniel Lezcano 	.o_name		= (char *)"thermal",
260*47c4b0deSDaniel Lezcano 	.o_cmds		= thermal_cmds,
261*47c4b0deSDaniel Lezcano 	.o_ncmds	= ARRAY_SIZE(thermal_cmds),
262*47c4b0deSDaniel Lezcano };
263*47c4b0deSDaniel Lezcano 
264*47c4b0deSDaniel Lezcano static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int cmd,
265*47c4b0deSDaniel Lezcano 					 int flags, void *arg)
266*47c4b0deSDaniel Lezcano {
267*47c4b0deSDaniel Lezcano 	struct nl_msg *msg;
268*47c4b0deSDaniel Lezcano 	void *hdr;
269*47c4b0deSDaniel Lezcano 
270*47c4b0deSDaniel Lezcano 	msg = nlmsg_alloc();
271*47c4b0deSDaniel Lezcano 	if (!msg)
272*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
273*47c4b0deSDaniel Lezcano 
274*47c4b0deSDaniel Lezcano 	hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, thermal_cmd_ops.o_id,
275*47c4b0deSDaniel Lezcano 			  0, flags, cmd, THERMAL_GENL_VERSION);
276*47c4b0deSDaniel Lezcano 	if (!hdr)
277*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
278*47c4b0deSDaniel Lezcano 
279*47c4b0deSDaniel Lezcano 	if (id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id))
280*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
281*47c4b0deSDaniel Lezcano 
282*47c4b0deSDaniel Lezcano 	if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg))
283*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
284*47c4b0deSDaniel Lezcano 
285*47c4b0deSDaniel Lezcano 	nlmsg_free(msg);
286*47c4b0deSDaniel Lezcano 
287*47c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
288*47c4b0deSDaniel Lezcano }
289*47c4b0deSDaniel Lezcano 
290*47c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz)
291*47c4b0deSDaniel Lezcano {
292*47c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_TZ_GET_ID,
293*47c4b0deSDaniel Lezcano 				 NLM_F_DUMP | NLM_F_ACK, tz);
294*47c4b0deSDaniel Lezcano }
295*47c4b0deSDaniel Lezcano 
296*47c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_cdev(struct thermal_handler *th, struct thermal_cdev **tc)
297*47c4b0deSDaniel Lezcano {
298*47c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_CDEV_GET,
299*47c4b0deSDaniel Lezcano 				 NLM_F_DUMP | NLM_F_ACK, tc);
300*47c4b0deSDaniel Lezcano }
301*47c4b0deSDaniel Lezcano 
302*47c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_trip(struct thermal_handler *th, struct thermal_zone *tz)
303*47c4b0deSDaniel Lezcano {
304*47c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TRIP,
305*47c4b0deSDaniel Lezcano 				 0, tz);
306*47c4b0deSDaniel Lezcano }
307*47c4b0deSDaniel Lezcano 
308*47c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_governor(struct thermal_handler *th, struct thermal_zone *tz)
309*47c4b0deSDaniel Lezcano {
310*47c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz);
311*47c4b0deSDaniel Lezcano }
312*47c4b0deSDaniel Lezcano 
313*47c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz)
314*47c4b0deSDaniel Lezcano {
315*47c4b0deSDaniel Lezcano 	return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz);
316*47c4b0deSDaniel Lezcano }
317*47c4b0deSDaniel Lezcano 
318*47c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_exit(struct thermal_handler *th)
319*47c4b0deSDaniel Lezcano {
320*47c4b0deSDaniel Lezcano 	if (genl_unregister_family(&thermal_cmd_ops))
321*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
322*47c4b0deSDaniel Lezcano 
323*47c4b0deSDaniel Lezcano 	nl_thermal_disconnect(th->sk_cmd, th->cb_cmd);
324*47c4b0deSDaniel Lezcano 
325*47c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
326*47c4b0deSDaniel Lezcano }
327*47c4b0deSDaniel Lezcano 
328*47c4b0deSDaniel Lezcano thermal_error_t thermal_cmd_init(struct thermal_handler *th)
329*47c4b0deSDaniel Lezcano {
330*47c4b0deSDaniel Lezcano 	int ret;
331*47c4b0deSDaniel Lezcano 	int family;
332*47c4b0deSDaniel Lezcano 
333*47c4b0deSDaniel Lezcano 	if (nl_thermal_connect(&th->sk_cmd, &th->cb_cmd))
334*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
335*47c4b0deSDaniel Lezcano 
336*47c4b0deSDaniel Lezcano 	ret = genl_register_family(&thermal_cmd_ops);
337*47c4b0deSDaniel Lezcano 	if (ret)
338*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
339*47c4b0deSDaniel Lezcano 
340*47c4b0deSDaniel Lezcano 	ret = genl_ops_resolve(th->sk_cmd, &thermal_cmd_ops);
341*47c4b0deSDaniel Lezcano 	if (ret)
342*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
343*47c4b0deSDaniel Lezcano 
344*47c4b0deSDaniel Lezcano 	family = genl_ctrl_resolve(th->sk_cmd, "nlctrl");
345*47c4b0deSDaniel Lezcano 	if (family != GENL_ID_CTRL)
346*47c4b0deSDaniel Lezcano 		return THERMAL_ERROR;
347*47c4b0deSDaniel Lezcano 
348*47c4b0deSDaniel Lezcano 	return THERMAL_SUCCESS;
349*47c4b0deSDaniel Lezcano }
350