]> Git Repo - linux.git/blob - tools/lib/thermal/events.c
Linux 6.14-rc3
[linux.git] / tools / lib / thermal / events.c
1 // SPDX-License-Identifier: LGPL-2.1+
2 // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <[email protected]>
3 #include <linux/netlink.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7
8
9 #include <thermal.h>
10 #include "thermal_nl.h"
11
12 /*
13  * Optimization: fill this array to tell which event we do want to pay
14  * attention to. That happens at init time with the ops
15  * structure. Each ops will enable the event and the general handler
16  * will be able to discard the event if there is not ops associated
17  * with it.
18  */
19 static int enabled_ops[__THERMAL_GENL_EVENT_MAX];
20
21 static int handle_thermal_event(struct nl_msg *n, void *arg)
22 {
23         struct nlmsghdr *nlh = nlmsg_hdr(n);
24         struct genlmsghdr *genlhdr = genlmsg_hdr(nlh);
25         struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
26         struct thermal_handler_param *thp = arg;
27         struct thermal_events_ops *ops = &thp->th->ops->events;
28
29         genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
30
31         arg = thp->arg;
32
33         /*
34          * This is an event we don't care of, bail out.
35          */
36         if (!enabled_ops[genlhdr->cmd])
37                 return THERMAL_SUCCESS;
38
39         switch (genlhdr->cmd) {
40
41         case THERMAL_GENL_EVENT_TZ_CREATE:
42                 return ops->tz_create(nla_get_string(attrs[THERMAL_GENL_ATTR_TZ_NAME]),
43                                       nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
44
45         case THERMAL_GENL_EVENT_TZ_DELETE:
46                 return ops->tz_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
47
48         case THERMAL_GENL_EVENT_TZ_ENABLE:
49                 return ops->tz_enable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
50
51         case THERMAL_GENL_EVENT_TZ_DISABLE:
52                 return ops->tz_disable(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]), arg);
53
54         case THERMAL_GENL_EVENT_TZ_TRIP_CHANGE:
55                 return ops->trip_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
56                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
57                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
58                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
59                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
60
61         case THERMAL_GENL_EVENT_TZ_TRIP_ADD:
62                 return ops->trip_add(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
63                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
64                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]),
65                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]),
66                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]), arg);
67
68         case THERMAL_GENL_EVENT_TZ_TRIP_DELETE:
69                 return ops->trip_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
70                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]), arg);
71
72         case THERMAL_GENL_EVENT_TZ_TRIP_UP:
73                 return ops->trip_high(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
74                                       nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
75                                       nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
76
77         case THERMAL_GENL_EVENT_TZ_TRIP_DOWN:
78                 return ops->trip_low(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
79                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]),
80                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]), arg);
81
82         case THERMAL_GENL_EVENT_CDEV_ADD:
83                 return ops->cdev_add(nla_get_string(attrs[THERMAL_GENL_ATTR_CDEV_NAME]),
84                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
85                                      nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE]), arg);
86
87         case THERMAL_GENL_EVENT_CDEV_DELETE:
88                 return ops->cdev_delete(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]), arg);
89
90         case THERMAL_GENL_EVENT_CDEV_STATE_UPDATE:
91                 return ops->cdev_update(nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]),
92                                         nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE]), arg);
93
94         case THERMAL_GENL_EVENT_TZ_GOV_CHANGE:
95                 return ops->gov_change(nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]),
96                                        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
121         default:
122                 return -1;
123         }
124 }
125
126 static void thermal_events_ops_init(struct thermal_events_ops *ops)
127 {
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;
146 }
147
148 thermal_error_t thermal_events_handle(struct thermal_handler *th, void *arg)
149 {
150         struct thermal_handler_param thp = { .th = th, .arg = arg };
151
152         if (!th)
153                 return THERMAL_ERROR;
154
155         if (nl_cb_set(th->cb_event, NL_CB_VALID, NL_CB_CUSTOM,
156                       handle_thermal_event, &thp))
157                 return THERMAL_ERROR;
158
159         return nl_recvmsgs(th->sk_event, th->cb_event);
160 }
161
162 int thermal_events_fd(struct thermal_handler *th)
163 {
164         if (!th)
165                 return -1;
166
167         return nl_socket_get_fd(th->sk_event);
168 }
169
170 thermal_error_t thermal_events_exit(struct thermal_handler *th)
171 {
172         if (nl_unsubscribe_thermal(th->sk_event, th->cb_event,
173                                    THERMAL_GENL_EVENT_GROUP_NAME))
174                 return THERMAL_ERROR;
175
176         nl_thermal_disconnect(th->sk_event, th->cb_event);
177
178         return THERMAL_SUCCESS;
179 }
180
181 thermal_error_t thermal_events_init(struct thermal_handler *th)
182 {
183         thermal_events_ops_init(&th->ops->events);
184
185         if (nl_thermal_connect(&th->sk_event, &th->cb_event))
186                 return THERMAL_ERROR;
187
188         if (nl_subscribe_thermal(th->sk_event, th->cb_event,
189                                  THERMAL_GENL_EVENT_GROUP_NAME))
190                 return THERMAL_ERROR;
191
192         return THERMAL_SUCCESS;
193 }
This page took 0.041524 seconds and 4 git commands to generate.