Skip to content

Commit a262672

Browse files
dlezcanorafaeljw
authored andcommitted
tools/lib/thermal: Add the threshold netlink ABI
The thermal framework supports the thresholds and allows the userspace to create, delete, flush, get the list of the thresholds as well as getting the list of the thresholds set for a specific thermal zone. Add the netlink abstraction in the thermal library to take full advantage of thresholds for the userspace program. Signed-off-by: Daniel Lezcano <[email protected]> Reviewed-by: Lukasz Luba <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 24b216b commit a262672

File tree

6 files changed

+242
-15
lines changed

6 files changed

+242
-15
lines changed

tools/lib/thermal/commands.c

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <stdio.h>
66
#include <stdlib.h>
77
#include <unistd.h>
8+
#include <limits.h>
89

910
#include <thermal.h>
1011
#include "thermal_nl.h"
@@ -33,6 +34,11 @@ static struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = {
3334
[THERMAL_GENL_ATTR_CDEV_CUR_STATE] = { .type = NLA_U32 },
3435
[THERMAL_GENL_ATTR_CDEV_MAX_STATE] = { .type = NLA_U32 },
3536
[THERMAL_GENL_ATTR_CDEV_NAME] = { .type = NLA_STRING },
37+
38+
/* Thresholds */
39+
[THERMAL_GENL_ATTR_THRESHOLD] = { .type = NLA_NESTED },
40+
[THERMAL_GENL_ATTR_THRESHOLD_TEMP] = { .type = NLA_U32 },
41+
[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION] = { .type = NLA_U32 },
3642
};
3743

3844
static int parse_tz_get(struct genl_info *info, struct thermal_zone **tz)
@@ -182,6 +188,48 @@ static int parse_tz_get_gov(struct genl_info *info, struct thermal_zone *tz)
182188
return THERMAL_SUCCESS;
183189
}
184190

191+
static int parse_threshold_get(struct genl_info *info, struct thermal_zone *tz)
192+
{
193+
struct nlattr *attr;
194+
struct thermal_threshold *__tt = NULL;
195+
size_t size = 0;
196+
int rem;
197+
198+
/*
199+
* The size contains the size of the array and we want to
200+
* access the last element, size - 1.
201+
*
202+
* The variable size is initialized to zero but it will be
203+
* then incremented by the first if() statement. The message
204+
* attributes are ordered, so the first if() statement will be
205+
* always called before the second one. If it happens that is
206+
* not the case, then it is a kernel bug.
207+
*/
208+
nla_for_each_nested(attr, info->attrs[THERMAL_GENL_ATTR_THRESHOLD], rem) {
209+
210+
if (nla_type(attr) == THERMAL_GENL_ATTR_THRESHOLD_TEMP) {
211+
212+
size++;
213+
214+
__tt = realloc(__tt, sizeof(*__tt) * (size + 2));
215+
if (!__tt)
216+
return THERMAL_ERROR;
217+
218+
__tt[size - 1].temperature = nla_get_u32(attr);
219+
}
220+
221+
if (nla_type(attr) == THERMAL_GENL_ATTR_THRESHOLD_DIRECTION)
222+
__tt[size - 1].direction = nla_get_u32(attr);
223+
}
224+
225+
if (__tt)
226+
__tt[size].temperature = INT_MAX;
227+
228+
tz->thresholds = __tt;
229+
230+
return THERMAL_SUCCESS;
231+
}
232+
185233
static int handle_netlink(struct nl_cache_ops *unused,
186234
struct genl_cmd *cmd,
187235
struct genl_info *info, void *arg)
@@ -210,6 +258,10 @@ static int handle_netlink(struct nl_cache_ops *unused,
210258
ret = parse_tz_get_gov(info, arg);
211259
break;
212260

261+
case THERMAL_GENL_CMD_THRESHOLD_GET:
262+
ret = parse_threshold_get(info, arg);
263+
break;
264+
213265
default:
214266
return THERMAL_ERROR;
215267
}
@@ -253,6 +305,34 @@ static struct genl_cmd thermal_cmds[] = {
253305
.c_maxattr = THERMAL_GENL_ATTR_MAX,
254306
.c_attr_policy = thermal_genl_policy,
255307
},
308+
{
309+
.c_id = THERMAL_GENL_CMD_THRESHOLD_GET,
310+
.c_name = (char *)"Get thresholds list",
311+
.c_msg_parser = handle_netlink,
312+
.c_maxattr = THERMAL_GENL_ATTR_MAX,
313+
.c_attr_policy = thermal_genl_policy,
314+
},
315+
{
316+
.c_id = THERMAL_GENL_CMD_THRESHOLD_ADD,
317+
.c_name = (char *)"Add a threshold",
318+
.c_msg_parser = handle_netlink,
319+
.c_maxattr = THERMAL_GENL_ATTR_MAX,
320+
.c_attr_policy = thermal_genl_policy,
321+
},
322+
{
323+
.c_id = THERMAL_GENL_CMD_THRESHOLD_DELETE,
324+
.c_name = (char *)"Delete a threshold",
325+
.c_msg_parser = handle_netlink,
326+
.c_maxattr = THERMAL_GENL_ATTR_MAX,
327+
.c_attr_policy = thermal_genl_policy,
328+
},
329+
{
330+
.c_id = THERMAL_GENL_CMD_THRESHOLD_FLUSH,
331+
.c_name = (char *)"Flush the thresholds",
332+
.c_msg_parser = handle_netlink,
333+
.c_maxattr = THERMAL_GENL_ATTR_MAX,
334+
.c_attr_policy = thermal_genl_policy,
335+
},
256336
};
257337

258338
static struct genl_ops thermal_cmd_ops = {
@@ -263,13 +343,29 @@ static struct genl_ops thermal_cmd_ops = {
263343

264344
struct cmd_param {
265345
int tz_id;
346+
int temp;
347+
int direction;
266348
};
267349

268350
typedef int (*cmd_cb_t)(struct nl_msg *, struct cmd_param *);
269351

270352
static int thermal_genl_tz_id_encode(struct nl_msg *msg, struct cmd_param *p)
271353
{
272-
if (p->tz_id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id))
354+
if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id))
355+
return -1;
356+
357+
return 0;
358+
}
359+
360+
static int thermal_genl_threshold_encode(struct nl_msg *msg, struct cmd_param *p)
361+
{
362+
if (thermal_genl_tz_id_encode(msg, p))
363+
return -1;
364+
365+
if (nla_put_u32(msg, THERMAL_GENL_ATTR_THRESHOLD_TEMP, p->temp))
366+
return -1;
367+
368+
if (nla_put_u32(msg, THERMAL_GENL_ATTR_THRESHOLD_DIRECTION, p->direction))
273369
return -1;
274370

275371
return 0;
@@ -338,6 +434,46 @@ thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_
338434
THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz);
339435
}
340436

437+
thermal_error_t thermal_cmd_threshold_get(struct thermal_handler *th,
438+
struct thermal_zone *tz)
439+
{
440+
struct cmd_param p = { .tz_id = tz->id };
441+
442+
return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p,
443+
THERMAL_GENL_CMD_THRESHOLD_GET, 0, tz);
444+
}
445+
446+
thermal_error_t thermal_cmd_threshold_add(struct thermal_handler *th,
447+
struct thermal_zone *tz,
448+
int temperature,
449+
int direction)
450+
{
451+
struct cmd_param p = { .tz_id = tz->id, .temp = temperature, .direction = direction };
452+
453+
return thermal_genl_auto(th, thermal_genl_threshold_encode, &p,
454+
THERMAL_GENL_CMD_THRESHOLD_ADD, 0, tz);
455+
}
456+
457+
thermal_error_t thermal_cmd_threshold_delete(struct thermal_handler *th,
458+
struct thermal_zone *tz,
459+
int temperature,
460+
int direction)
461+
{
462+
struct cmd_param p = { .tz_id = tz->id, .temp = temperature, .direction = direction };
463+
464+
return thermal_genl_auto(th, thermal_genl_threshold_encode, &p,
465+
THERMAL_GENL_CMD_THRESHOLD_DELETE, 0, tz);
466+
}
467+
468+
thermal_error_t thermal_cmd_threshold_flush(struct thermal_handler *th,
469+
struct thermal_zone *tz)
470+
{
471+
struct cmd_param p = { .tz_id = tz->id };
472+
473+
return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p,
474+
THERMAL_GENL_CMD_THRESHOLD_FLUSH, 0, tz);
475+
}
476+
341477
thermal_error_t thermal_cmd_exit(struct thermal_handler *th)
342478
{
343479
if (genl_unregister_family(&thermal_cmd_ops))

tools/lib/thermal/events.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,26 +94,55 @@ static int handle_thermal_event(struct nl_msg *n, void *arg)
9494
case THERMAL_GENL_EVENT_TZ_GOV_CHANGE:
9595
return ops->gov_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
9696
nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]), arg);
97+
98+
case THERMAL_GENL_EVENT_THRESHOLD_ADD:
99+
return ops->threshold_add(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
100+
nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]),
101+
nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION]), arg);
102+
103+
case THERMAL_GENL_EVENT_THRESHOLD_DELETE:
104+
return ops->threshold_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
105+
nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]),
106+
nla_get_u32(attrs[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION]), arg);
107+
108+
case THERMAL_GENL_EVENT_THRESHOLD_FLUSH:
109+
return ops->threshold_flush(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
110+
111+
case THERMAL_GENL_EVENT_THRESHOLD_UP:
112+
return ops->threshold_up(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
113+
nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]),
114+
nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_PREV_TEMP]), arg);
115+
116+
case THERMAL_GENL_EVENT_THRESHOLD_DOWN:
117+
return ops->threshold_down(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
118+
nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]),
119+
nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_PREV_TEMP]), arg);
120+
97121
default:
98122
return -1;
99123
}
100124
}
101125

102126
static void thermal_events_ops_init(struct thermal_events_ops *ops)
103127
{
104-
enabled_ops[THERMAL_GENL_EVENT_TZ_CREATE] = !!ops->tz_create;
105-
enabled_ops[THERMAL_GENL_EVENT_TZ_DELETE] = !!ops->tz_delete;
106-
enabled_ops[THERMAL_GENL_EVENT_TZ_DISABLE] = !!ops->tz_disable;
107-
enabled_ops[THERMAL_GENL_EVENT_TZ_ENABLE] = !!ops->tz_enable;
108-
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_UP] = !!ops->trip_high;
109-
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = !!ops->trip_low;
110-
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = !!ops->trip_change;
111-
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_ADD] = !!ops->trip_add;
112-
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = !!ops->trip_delete;
113-
enabled_ops[THERMAL_GENL_EVENT_CDEV_ADD] = !!ops->cdev_add;
114-
enabled_ops[THERMAL_GENL_EVENT_CDEV_DELETE] = !!ops->cdev_delete;
115-
enabled_ops[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = !!ops->cdev_update;
116-
enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = !!ops->gov_change;
128+
enabled_ops[THERMAL_GENL_EVENT_TZ_CREATE] = !!ops->tz_create;
129+
enabled_ops[THERMAL_GENL_EVENT_TZ_DELETE] = !!ops->tz_delete;
130+
enabled_ops[THERMAL_GENL_EVENT_TZ_DISABLE] = !!ops->tz_disable;
131+
enabled_ops[THERMAL_GENL_EVENT_TZ_ENABLE] = !!ops->tz_enable;
132+
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_UP] = !!ops->trip_high;
133+
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = !!ops->trip_low;
134+
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = !!ops->trip_change;
135+
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_ADD] = !!ops->trip_add;
136+
enabled_ops[THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = !!ops->trip_delete;
137+
enabled_ops[THERMAL_GENL_EVENT_CDEV_ADD] = !!ops->cdev_add;
138+
enabled_ops[THERMAL_GENL_EVENT_CDEV_DELETE] = !!ops->cdev_delete;
139+
enabled_ops[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = !!ops->cdev_update;
140+
enabled_ops[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = !!ops->gov_change;
141+
enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_ADD] = !!ops->threshold_add;
142+
enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_DELETE] = !!ops->threshold_delete;
143+
enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_FLUSH] = !!ops->threshold_flush;
144+
enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_UP] = !!ops->threshold_up;
145+
enabled_ops[THERMAL_GENL_EVENT_THRESHOLD_DOWN] = !!ops->threshold_down;
117146
}
118147

119148
thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg)

tools/lib/thermal/include/thermal.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,20 @@
44
#define __LIBTHERMAL_H
55

66
#include <linux/thermal.h>
7+
#include <sys/types.h>
78

89
#ifndef LIBTHERMAL_API
910
#define LIBTHERMAL_API __attribute__((visibility("default")))
1011
#endif
1112

13+
#ifndef THERMAL_THRESHOLD_WAY_UP
14+
#define THERMAL_THRESHOLD_WAY_UP 0x1
15+
#endif
16+
17+
#ifndef THERMAL_THRESHOLD_WAY_DOWN
18+
#define THERMAL_THRESHOLD_WAY_DOWN 0x2
19+
#endif
20+
1221
#ifdef __cplusplus
1322
extern "C" {
1423
#endif
@@ -31,6 +40,11 @@ struct thermal_events_ops {
3140
int (*cdev_delete)(int cdev_id, void *arg);
3241
int (*cdev_update)(int cdev_id, int cur_state, void *arg);
3342
int (*gov_change)(int tz_id, const char *gov_name, void *arg);
43+
int (*threshold_add)(int tz_id, int temperature, int direction, void *arg);
44+
int (*threshold_delete)(int tz_id, int temperature, int direction, void *arg);
45+
int (*threshold_flush)(int tz_id, void *arg);
46+
int (*threshold_up)(int tz_id, int temp, int prev_temp, void *arg);
47+
int (*threshold_down)(int tz_id, int temp, int prev_temp, void *arg);
3448
};
3549

3650
struct thermal_ops {
@@ -45,12 +59,18 @@ struct thermal_trip {
4559
int hyst;
4660
};
4761

62+
struct thermal_threshold {
63+
int temperature;
64+
int direction;
65+
};
66+
4867
struct thermal_zone {
4968
int id;
5069
int temp;
5170
char name[THERMAL_NAME_LENGTH];
5271
char governor[THERMAL_NAME_LENGTH];
5372
struct thermal_trip *trip;
73+
struct thermal_threshold *thresholds;
5474
};
5575

5676
struct thermal_cdev {
@@ -74,12 +94,16 @@ typedef int (*cb_tt_t)(struct thermal_trip *, void *);
7494

7595
typedef int (*cb_tc_t)(struct thermal_cdev *, void *);
7696

97+
typedef int (*cb_th_t)(struct thermal_threshold *, void *);
98+
7799
LIBTHERMAL_API int for_each_thermal_zone(struct thermal_zone *tz, cb_tz_t cb, void *arg);
78100

79101
LIBTHERMAL_API int for_each_thermal_trip(struct thermal_trip *tt, cb_tt_t cb, void *arg);
80102

81103
LIBTHERMAL_API int for_each_thermal_cdev(struct thermal_cdev *cdev, cb_tc_t cb, void *arg);
82104

105+
LIBTHERMAL_API int for_each_thermal_threshold(struct thermal_threshold *th, cb_th_t cb, void *arg);
106+
83107
LIBTHERMAL_API struct thermal_zone *thermal_zone_find_by_name(struct thermal_zone *tz,
84108
const char *name);
85109

@@ -124,6 +148,22 @@ LIBTHERMAL_API thermal_error_t thermal_cmd_get_governor(struct thermal_handler *
124148
LIBTHERMAL_API thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th,
125149
struct thermal_zone *tz);
126150

151+
LIBTHERMAL_API thermal_error_t thermal_cmd_threshold_get(struct thermal_handler *th,
152+
struct thermal_zone *tz);
153+
154+
LIBTHERMAL_API thermal_error_t thermal_cmd_threshold_add(struct thermal_handler *th,
155+
struct thermal_zone *tz,
156+
int temperature,
157+
int direction);
158+
159+
LIBTHERMAL_API thermal_error_t thermal_cmd_threshold_delete(struct thermal_handler *th,
160+
struct thermal_zone *tz,
161+
int temperature,
162+
int direction);
163+
164+
LIBTHERMAL_API thermal_error_t thermal_cmd_threshold_flush(struct thermal_handler *th,
165+
struct thermal_zone *tz);
166+
127167
/*
128168
* Netlink thermal samples
129169
*/

tools/lib/thermal/libthermal.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ LIBTHERMAL_0.0.1 {
44
for_each_thermal_zone;
55
for_each_thermal_trip;
66
for_each_thermal_cdev;
7+
for_each_thermal_threshold;
78
thermal_zone_find_by_name;
89
thermal_zone_find_by_id;
910
thermal_zone_discover;
@@ -17,6 +18,10 @@ LIBTHERMAL_0.0.1 {
1718
thermal_cmd_get_trip;
1819
thermal_cmd_get_governor;
1920
thermal_cmd_get_temp;
21+
thermal_cmd_threshold_get;
22+
thermal_cmd_threshold_add;
23+
thermal_cmd_threshold_delete;
24+
thermal_cmd_threshold_flush;
2025
thermal_sampling_init;
2126
thermal_sampling_handle;
2227
thermal_sampling_fd;

0 commit comments

Comments
 (0)