Skip to content

Commit 1773572

Browse files
dlezcanorafaeljw
authored andcommitted
thermal: netlink: Add the commands and the events for the thresholds
The thresholds exist but there is no notification neither action code related to them yet. These changes implement the netlink for the notifications when the thresholds are crossed, added, deleted or flushed as well as the commands which allows to get the list of the thresholds, flush them, add and delete. Signed-off-by: Daniel Lezcano <[email protected]> Reviewed-by: Lukasz Luba <[email protected]> Link: https://patch.msgid.link/[email protected] [ rjw: Use the thermal_zone guard for locking, subject edit ] Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent dfa245f commit 1773572

File tree

5 files changed

+301
-28
lines changed

5 files changed

+301
-28
lines changed

drivers/thermal/thermal_netlink.c

Lines changed: 226 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/module.h>
1010
#include <linux/notifier.h>
1111
#include <linux/kernel.h>
12+
#include <net/sock.h>
1213
#include <net/genetlink.h>
1314
#include <uapi/linux/thermal.h>
1415

@@ -49,6 +50,11 @@ static const struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] =
4950
[THERMAL_GENL_ATTR_CPU_CAPABILITY_ID] = { .type = NLA_U32 },
5051
[THERMAL_GENL_ATTR_CPU_CAPABILITY_PERFORMANCE] = { .type = NLA_U32 },
5152
[THERMAL_GENL_ATTR_CPU_CAPABILITY_EFFICIENCY] = { .type = NLA_U32 },
53+
54+
/* Thresholds */
55+
[THERMAL_GENL_ATTR_THRESHOLD] = { .type = NLA_NESTED },
56+
[THERMAL_GENL_ATTR_THRESHOLD_TEMP] = { .type = NLA_U32 },
57+
[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION] = { .type = NLA_U32 },
5258
};
5359

5460
struct param {
@@ -62,6 +68,8 @@ struct param {
6268
int trip_type;
6369
int trip_hyst;
6470
int temp;
71+
int prev_temp;
72+
int direction;
6573
int cdev_state;
6674
int cdev_max_state;
6775
struct thermal_genl_cpu_caps *cpu_capabilities;
@@ -234,6 +242,34 @@ static int thermal_genl_event_cpu_capability_change(struct param *p)
234242
return -EMSGSIZE;
235243
}
236244

245+
static int thermal_genl_event_threshold_add(struct param *p)
246+
{
247+
if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
248+
nla_put_u32(p->msg, THERMAL_GENL_ATTR_THRESHOLD_TEMP, p->temp) ||
249+
nla_put_u32(p->msg, THERMAL_GENL_ATTR_THRESHOLD_DIRECTION, p->direction))
250+
return -EMSGSIZE;
251+
252+
return 0;
253+
}
254+
255+
static int thermal_genl_event_threshold_flush(struct param *p)
256+
{
257+
if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id))
258+
return -EMSGSIZE;
259+
260+
return 0;
261+
}
262+
263+
static int thermal_genl_event_threshold_up(struct param *p)
264+
{
265+
if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) ||
266+
nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_PREV_TEMP, p->prev_temp) ||
267+
nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TEMP, p->temp))
268+
return -EMSGSIZE;
269+
270+
return 0;
271+
}
272+
237273
int thermal_genl_event_tz_delete(struct param *p)
238274
__attribute__((alias("thermal_genl_event_tz")));
239275

@@ -246,6 +282,12 @@ int thermal_genl_event_tz_disable(struct param *p)
246282
int thermal_genl_event_tz_trip_down(struct param *p)
247283
__attribute__((alias("thermal_genl_event_tz_trip_up")));
248284

285+
int thermal_genl_event_threshold_delete(struct param *p)
286+
__attribute__((alias("thermal_genl_event_threshold_add")));
287+
288+
int thermal_genl_event_threshold_down(struct param *p)
289+
__attribute__((alias("thermal_genl_event_threshold_up")));
290+
249291
static cb_t event_cb[] = {
250292
[THERMAL_GENL_EVENT_TZ_CREATE] = thermal_genl_event_tz_create,
251293
[THERMAL_GENL_EVENT_TZ_DELETE] = thermal_genl_event_tz_delete,
@@ -259,6 +301,11 @@ static cb_t event_cb[] = {
259301
[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = thermal_genl_event_cdev_state_update,
260302
[THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = thermal_genl_event_gov_change,
261303
[THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE] = thermal_genl_event_cpu_capability_change,
304+
[THERMAL_GENL_EVENT_THRESHOLD_ADD] = thermal_genl_event_threshold_add,
305+
[THERMAL_GENL_EVENT_THRESHOLD_DELETE] = thermal_genl_event_threshold_delete,
306+
[THERMAL_GENL_EVENT_THRESHOLD_FLUSH] = thermal_genl_event_threshold_flush,
307+
[THERMAL_GENL_EVENT_THRESHOLD_DOWN] = thermal_genl_event_threshold_down,
308+
[THERMAL_GENL_EVENT_THRESHOLD_UP] = thermal_genl_event_threshold_up,
262309
};
263310

264311
/*
@@ -401,6 +448,43 @@ int thermal_genl_cpu_capability_event(int count,
401448
}
402449
EXPORT_SYMBOL_GPL(thermal_genl_cpu_capability_event);
403450

451+
int thermal_notify_threshold_add(const struct thermal_zone_device *tz,
452+
int temperature, int direction)
453+
{
454+
struct param p = { .tz_id = tz->id, .temp = temperature, .direction = direction };
455+
456+
return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_ADD, &p);
457+
}
458+
459+
int thermal_notify_threshold_delete(const struct thermal_zone_device *tz,
460+
int temperature, int direction)
461+
{
462+
struct param p = { .tz_id = tz->id, .temp = temperature, .direction = direction };
463+
464+
return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_DELETE, &p);
465+
}
466+
467+
int thermal_notify_threshold_flush(const struct thermal_zone_device *tz)
468+
{
469+
struct param p = { .tz_id = tz->id };
470+
471+
return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_FLUSH, &p);
472+
}
473+
474+
int thermal_notify_threshold_down(const struct thermal_zone_device *tz)
475+
{
476+
struct param p = { .tz_id = tz->id, .temp = tz->temperature, .prev_temp = tz->last_temperature };
477+
478+
return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_DOWN, &p);
479+
}
480+
481+
int thermal_notify_threshold_up(const struct thermal_zone_device *tz)
482+
{
483+
struct param p = { .tz_id = tz->id, .temp = tz->temperature, .prev_temp = tz->last_temperature };
484+
485+
return thermal_genl_send_event(THERMAL_GENL_EVENT_THRESHOLD_UP, &p);
486+
}
487+
404488
/*************************** Command encoding ********************************/
405489

406490
static int __thermal_genl_cmd_tz_get_id(struct thermal_zone_device *tz,
@@ -563,12 +647,128 @@ static int thermal_genl_cmd_cdev_get(struct param *p)
563647
return ret;
564648
}
565649

650+
static int __thermal_genl_cmd_threshold_get(struct user_threshold *threshold, void *arg)
651+
{
652+
struct sk_buff *msg = arg;
653+
654+
if (nla_put_u32(msg, THERMAL_GENL_ATTR_THRESHOLD_TEMP, threshold->temperature) ||
655+
nla_put_u32(msg, THERMAL_GENL_ATTR_THRESHOLD_DIRECTION, threshold->direction))
656+
return -1;
657+
658+
return 0;
659+
}
660+
661+
static int thermal_genl_cmd_threshold_get(struct param *p)
662+
{
663+
struct sk_buff *msg = p->msg;
664+
struct nlattr *start_trip;
665+
int id, ret;
666+
667+
if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID])
668+
return -EINVAL;
669+
670+
id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]);
671+
672+
CLASS(thermal_zone_get_by_id, tz)(id);
673+
if (!tz)
674+
return -EINVAL;
675+
676+
start_trip = nla_nest_start(msg, THERMAL_GENL_ATTR_THRESHOLD);
677+
if (!start_trip)
678+
return -EMSGSIZE;
679+
680+
ret = thermal_thresholds_for_each(tz, __thermal_genl_cmd_threshold_get, msg);
681+
if (ret)
682+
return -EMSGSIZE;
683+
684+
nla_nest_end(msg, start_trip);
685+
686+
return 0;
687+
}
688+
689+
static int thermal_genl_cmd_threshold_add(struct param *p)
690+
{
691+
int id, temp, direction;
692+
693+
if (!capable(CAP_SYS_ADMIN))
694+
return -EPERM;
695+
696+
if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID] ||
697+
!p->attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP] ||
698+
!p->attrs[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION])
699+
return -EINVAL;
700+
701+
id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]);
702+
temp = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]);
703+
direction = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION]);
704+
705+
CLASS(thermal_zone_get_by_id, tz)(id);
706+
if (!tz)
707+
return -EINVAL;
708+
709+
guard(thermal_zone)(tz);
710+
711+
return thermal_thresholds_add(tz, temp, direction);
712+
}
713+
714+
static int thermal_genl_cmd_threshold_delete(struct param *p)
715+
{
716+
int id, temp, direction;
717+
718+
if (!capable(CAP_SYS_ADMIN))
719+
return -EPERM;
720+
721+
if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID] ||
722+
!p->attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP] ||
723+
!p->attrs[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION])
724+
return -EINVAL;
725+
726+
id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]);
727+
temp = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_THRESHOLD_TEMP]);
728+
direction = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_THRESHOLD_DIRECTION]);
729+
730+
CLASS(thermal_zone_get_by_id, tz)(id);
731+
if (!tz)
732+
return -EINVAL;
733+
734+
guard(thermal_zone)(tz);
735+
736+
return thermal_thresholds_delete(tz, temp, direction);
737+
}
738+
739+
static int thermal_genl_cmd_threshold_flush(struct param *p)
740+
{
741+
int id;
742+
743+
if (!capable(CAP_SYS_ADMIN))
744+
return -EPERM;
745+
746+
if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID])
747+
return -EINVAL;
748+
749+
id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]);
750+
751+
CLASS(thermal_zone_get_by_id, tz)(id);
752+
if (!tz)
753+
return -EINVAL;
754+
755+
guard(thermal_zone)(tz);
756+
757+
thermal_thresholds_flush(tz);
758+
759+
return 0;
760+
}
761+
566762
static cb_t cmd_cb[] = {
567-
[THERMAL_GENL_CMD_TZ_GET_ID] = thermal_genl_cmd_tz_get_id,
568-
[THERMAL_GENL_CMD_TZ_GET_TRIP] = thermal_genl_cmd_tz_get_trip,
569-
[THERMAL_GENL_CMD_TZ_GET_TEMP] = thermal_genl_cmd_tz_get_temp,
570-
[THERMAL_GENL_CMD_TZ_GET_GOV] = thermal_genl_cmd_tz_get_gov,
571-
[THERMAL_GENL_CMD_CDEV_GET] = thermal_genl_cmd_cdev_get,
763+
[THERMAL_GENL_CMD_TZ_GET_ID] = thermal_genl_cmd_tz_get_id,
764+
[THERMAL_GENL_CMD_TZ_GET_TRIP] = thermal_genl_cmd_tz_get_trip,
765+
[THERMAL_GENL_CMD_TZ_GET_TEMP] = thermal_genl_cmd_tz_get_temp,
766+
[THERMAL_GENL_CMD_TZ_GET_GOV] = thermal_genl_cmd_tz_get_gov,
767+
[THERMAL_GENL_CMD_CDEV_GET] = thermal_genl_cmd_cdev_get,
768+
[THERMAL_GENL_CMD_THRESHOLD_GET] = thermal_genl_cmd_threshold_get,
769+
[THERMAL_GENL_CMD_THRESHOLD_ADD] = thermal_genl_cmd_threshold_add,
770+
[THERMAL_GENL_CMD_THRESHOLD_DELETE] = thermal_genl_cmd_threshold_delete,
771+
[THERMAL_GENL_CMD_THRESHOLD_FLUSH] = thermal_genl_cmd_threshold_flush,
572772
};
573773

574774
static int thermal_genl_cmd_dumpit(struct sk_buff *skb,
@@ -679,6 +879,26 @@ static const struct genl_small_ops thermal_genl_ops[] = {
679879
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
680880
.dumpit = thermal_genl_cmd_dumpit,
681881
},
882+
{
883+
.cmd = THERMAL_GENL_CMD_THRESHOLD_GET,
884+
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
885+
.doit = thermal_genl_cmd_doit,
886+
},
887+
{
888+
.cmd = THERMAL_GENL_CMD_THRESHOLD_ADD,
889+
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
890+
.doit = thermal_genl_cmd_doit,
891+
},
892+
{
893+
.cmd = THERMAL_GENL_CMD_THRESHOLD_DELETE,
894+
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
895+
.doit = thermal_genl_cmd_doit,
896+
},
897+
{
898+
.cmd = THERMAL_GENL_CMD_THRESHOLD_FLUSH,
899+
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
900+
.doit = thermal_genl_cmd_doit,
901+
},
682902
};
683903

684904
static struct genl_family thermal_genl_family __ro_after_init = {
@@ -691,7 +911,7 @@ static struct genl_family thermal_genl_family __ro_after_init = {
691911
.unbind = thermal_genl_unbind,
692912
.small_ops = thermal_genl_ops,
693913
.n_small_ops = ARRAY_SIZE(thermal_genl_ops),
694-
.resv_start_op = THERMAL_GENL_CMD_CDEV_GET + 1,
914+
.resv_start_op = __THERMAL_GENL_CMD_MAX,
695915
.mcgrps = thermal_genl_mcgrps,
696916
.n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps),
697917
};

drivers/thermal/thermal_netlink.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ int thermal_notify_tz_gov_change(const struct thermal_zone_device *tz,
5353
int thermal_genl_sampling_temp(int id, int temp);
5454
int thermal_genl_cpu_capability_event(int count,
5555
struct thermal_genl_cpu_caps *caps);
56+
int thermal_notify_threshold_add(const struct thermal_zone_device *tz,
57+
int temperature, int direction);
58+
int thermal_notify_threshold_delete(const struct thermal_zone_device *tz,
59+
int temperature, int direction);
60+
int thermal_notify_threshold_flush(const struct thermal_zone_device *tz);
61+
int thermal_notify_threshold_down(const struct thermal_zone_device *tz);
62+
int thermal_notify_threshold_up(const struct thermal_zone_device *tz);
5663
#else
5764
static inline int thermal_netlink_init(void)
5865
{
@@ -139,6 +146,33 @@ static inline int thermal_genl_cpu_capability_event(int count, struct thermal_ge
139146
return 0;
140147
}
141148

149+
static inline int thermal_notify_threshold_add(const struct thermal_zone_device *tz,
150+
int temperature, int direction)
151+
{
152+
return 0;
153+
}
154+
155+
static inline int thermal_notify_threshold_delete(const struct thermal_zone_device *tz,
156+
int temperature, int direction)
157+
{
158+
return 0;
159+
}
160+
161+
static inline int thermal_notify_threshold_flush(const struct thermal_zone_device *tz)
162+
{
163+
return 0;
164+
}
165+
166+
static inline int thermal_notify_threshold_down(const struct thermal_zone_device *tz)
167+
{
168+
return 0;
169+
}
170+
171+
static inline int thermal_notify_threshold_up(const struct thermal_zone_device *tz)
172+
{
173+
return 0;
174+
}
175+
142176
static inline void __init thermal_netlink_exit(void) {}
143177

144178
#endif /* CONFIG_THERMAL_NETLINK */

0 commit comments

Comments
 (0)