sysmon_envsys_events.c revision 1.13.2.2 1 1.13.2.2 ad /* $NetBSD: sysmon_envsys_events.c,v 1.13.2.2 2007/07/15 13:21:45 ad Exp $ */
2 1.13.2.2 ad
3 1.13.2.2 ad /*-
4 1.13.2.2 ad * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 1.13.2.2 ad * All rights reserved.
6 1.13.2.2 ad *
7 1.13.2.2 ad * This code is derived from software contributed to The NetBSD Foundation
8 1.13.2.2 ad * by Juan Romero Pardines.
9 1.13.2.2 ad *
10 1.13.2.2 ad * Redistribution and use in source and binary forms, with or without
11 1.13.2.2 ad * modification, are permitted provided that the following conditions
12 1.13.2.2 ad * are met:
13 1.13.2.2 ad * 1. Redistributions of source code must retain the above copyright
14 1.13.2.2 ad * notice, this list of conditions and the following disclaimer.
15 1.13.2.2 ad * 2. Redistributions in binary form must reproduce the above copyright
16 1.13.2.2 ad * notice, this list of conditions and the following disclaimer in the
17 1.13.2.2 ad * documentation and/or other materials provided with the distribution.
18 1.13.2.2 ad * 3. All advertising materials mentioning features or use of this software
19 1.13.2.2 ad * must display the following acknowledgement:
20 1.13.2.2 ad * This product includes software developed by Juan Romero Pardines
21 1.13.2.2 ad * for the NetBSD Foundation, Inc. and its contributors.
22 1.13.2.2 ad * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.13.2.2 ad * contributors may be used to endorse or promote products derived
24 1.13.2.2 ad * from this software without specific prior written permission.
25 1.13.2.2 ad *
26 1.13.2.2 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.13.2.2 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.13.2.2 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.13.2.2 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.13.2.2 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.13.2.2 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.13.2.2 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.13.2.2 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.13.2.2 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.13.2.2 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.13.2.2 ad * POSSIBILITY OF SUCH DAMAGE.
37 1.13.2.2 ad */
38 1.13.2.2 ad
39 1.13.2.2 ad /*
40 1.13.2.2 ad * sysmon_envsys(9) events framework.
41 1.13.2.2 ad */
42 1.13.2.2 ad
43 1.13.2.2 ad #include <sys/cdefs.h>
44 1.13.2.2 ad __KERNEL_RCSID(0, "$NetBSD: sysmon_envsys_events.c,v 1.13.2.2 2007/07/15 13:21:45 ad Exp $");
45 1.13.2.2 ad
46 1.13.2.2 ad #include <sys/param.h>
47 1.13.2.2 ad #include <sys/types.h>
48 1.13.2.2 ad #include <sys/conf.h>
49 1.13.2.2 ad #include <sys/errno.h>
50 1.13.2.2 ad #include <sys/kernel.h>
51 1.13.2.2 ad #include <sys/sysctl.h>
52 1.13.2.2 ad #include <sys/systm.h>
53 1.13.2.2 ad #include <sys/proc.h>
54 1.13.2.2 ad #include <sys/mutex.h>
55 1.13.2.2 ad #include <sys/kmem.h>
56 1.13.2.2 ad #include <sys/callout.h>
57 1.13.2.2 ad
58 1.13.2.2 ad #include <dev/sysmon/sysmonvar.h>
59 1.13.2.2 ad #include <dev/sysmon/sysmon_envsysvar.h>
60 1.13.2.2 ad
61 1.13.2.2 ad struct sme_sensor_state {
62 1.13.2.2 ad int type;
63 1.13.2.2 ad const char *desc;
64 1.13.2.2 ad };
65 1.13.2.2 ad
66 1.13.2.2 ad struct sme_sensor_event {
67 1.13.2.2 ad int state;
68 1.13.2.2 ad int event;
69 1.13.2.2 ad };
70 1.13.2.2 ad
71 1.13.2.2 ad static const struct sme_sensor_state sme_sensor_drive_state[] = {
72 1.13.2.2 ad { ENVSYS_DRIVE_EMPTY, "drive state is unknown" },
73 1.13.2.2 ad { ENVSYS_DRIVE_READY, "drive is ready" },
74 1.13.2.2 ad { ENVSYS_DRIVE_POWERUP, "drive is powering up" },
75 1.13.2.2 ad { ENVSYS_DRIVE_ONLINE, "drive is online" },
76 1.13.2.2 ad { ENVSYS_DRIVE_IDLE, "drive is idle" },
77 1.13.2.2 ad { ENVSYS_DRIVE_ACTIVE, "drive is active" },
78 1.13.2.2 ad { ENVSYS_DRIVE_REBUILD, "drive is rebuilding" },
79 1.13.2.2 ad { ENVSYS_DRIVE_POWERDOWN, "drive is powering down" },
80 1.13.2.2 ad { ENVSYS_DRIVE_FAIL, "drive failed" },
81 1.13.2.2 ad { ENVSYS_DRIVE_PFAIL, "drive degraded" },
82 1.13.2.2 ad { -1, "unknown" }
83 1.13.2.2 ad };
84 1.13.2.2 ad
85 1.13.2.2 ad static const struct sme_sensor_event sme_sensor_event[] = {
86 1.13.2.2 ad { ENVSYS_SVALID, PENVSYS_EVENT_NORMAL },
87 1.13.2.2 ad { ENVSYS_SCRITICAL, PENVSYS_EVENT_CRITICAL },
88 1.13.2.2 ad { ENVSYS_SCRITOVER, PENVSYS_EVENT_CRITOVER },
89 1.13.2.2 ad { ENVSYS_SCRITUNDER, PENVSYS_EVENT_CRITUNDER },
90 1.13.2.2 ad { ENVSYS_SWARNOVER, PENVSYS_EVENT_WARNOVER },
91 1.13.2.2 ad { ENVSYS_SWARNUNDER, PENVSYS_EVENT_WARNUNDER },
92 1.13.2.2 ad { -1, -1 }
93 1.13.2.2 ad };
94 1.13.2.2 ad
95 1.13.2.2 ad static struct workqueue *seewq;
96 1.13.2.2 ad static struct callout seeco;
97 1.13.2.2 ad static bool sme_events_initialized = false;
98 1.13.2.2 ad kmutex_t sme_mtx, sme_event_mtx, sme_event_init_mtx;
99 1.13.2.2 ad
100 1.13.2.2 ad /* 10 seconds of timeout for the callout */
101 1.13.2.2 ad static int sme_events_timeout = 10;
102 1.13.2.2 ad static int sme_events_timeout_sysctl(SYSCTLFN_PROTO);
103 1.13.2.2 ad #define SME_EVTIMO (sme_events_timeout * hz)
104 1.13.2.2 ad
105 1.13.2.2 ad /*
106 1.13.2.2 ad * sysctl(9) stuff to handle the refresh value in the callout
107 1.13.2.2 ad * function.
108 1.13.2.2 ad */
109 1.13.2.2 ad static int
110 1.13.2.2 ad sme_events_timeout_sysctl(SYSCTLFN_ARGS)
111 1.13.2.2 ad {
112 1.13.2.2 ad struct sysctlnode node;
113 1.13.2.2 ad int timo, error;
114 1.13.2.2 ad
115 1.13.2.2 ad node = *rnode;
116 1.13.2.2 ad timo = sme_events_timeout;
117 1.13.2.2 ad node.sysctl_data = &timo;
118 1.13.2.2 ad
119 1.13.2.2 ad error = sysctl_lookup(SYSCTLFN_CALL(&node));
120 1.13.2.2 ad if (error || newp == NULL)
121 1.13.2.2 ad return error;
122 1.13.2.2 ad
123 1.13.2.2 ad /* min 1s */
124 1.13.2.2 ad if (timo < 1)
125 1.13.2.2 ad return EINVAL;
126 1.13.2.2 ad
127 1.13.2.2 ad sme_events_timeout = timo;
128 1.13.2.2 ad return 0;
129 1.13.2.2 ad }
130 1.13.2.2 ad
131 1.13.2.2 ad SYSCTL_SETUP(sysctl_kern_envsys_timeout_setup, "sysctl kern.envsys subtree")
132 1.13.2.2 ad {
133 1.13.2.2 ad const struct sysctlnode *node, *envsys_node;
134 1.13.2.2 ad
135 1.13.2.2 ad sysctl_createv(clog, 0, NULL, &node,
136 1.13.2.2 ad CTLFLAG_PERMANENT,
137 1.13.2.2 ad CTLTYPE_NODE, "kern", NULL,
138 1.13.2.2 ad NULL, 0, NULL, 0,
139 1.13.2.2 ad CTL_KERN, CTL_EOL);
140 1.13.2.2 ad
141 1.13.2.2 ad sysctl_createv(clog, 0, &node, &envsys_node,
142 1.13.2.2 ad 0,
143 1.13.2.2 ad CTLTYPE_NODE, "envsys", NULL,
144 1.13.2.2 ad NULL, 0, NULL, 0,
145 1.13.2.2 ad CTL_CREATE, CTL_EOL);
146 1.13.2.2 ad
147 1.13.2.2 ad sysctl_createv(clog, 0, &envsys_node, &node,
148 1.13.2.2 ad CTLFLAG_READWRITE,
149 1.13.2.2 ad CTLTYPE_INT, "refresh_value",
150 1.13.2.2 ad SYSCTL_DESCR("wait time in seconds to refresh "
151 1.13.2.2 ad "sensors being monitored"),
152 1.13.2.2 ad sme_events_timeout_sysctl, 0, &sme_events_timeout, 0,
153 1.13.2.2 ad CTL_CREATE, CTL_EOL);
154 1.13.2.2 ad }
155 1.13.2.2 ad
156 1.13.2.2 ad
157 1.13.2.2 ad /*
158 1.13.2.2 ad * sme_event_register:
159 1.13.2.2 ad *
160 1.13.2.2 ad * + Registers a sysmon envsys event.
161 1.13.2.2 ad * + Creates a new sysmon envsys event.
162 1.13.2.2 ad */
163 1.13.2.2 ad int
164 1.13.2.2 ad sme_event_register(sme_event_t *see)
165 1.13.2.2 ad {
166 1.13.2.2 ad sme_event_t *lsee;
167 1.13.2.2 ad struct penvsys_state *pes_old, *pes_new;
168 1.13.2.2 ad int error = 0;
169 1.13.2.2 ad
170 1.13.2.2 ad KASSERT(see != NULL);
171 1.13.2.2 ad
172 1.13.2.2 ad pes_new = &see->pes;
173 1.13.2.2 ad
174 1.13.2.2 ad mutex_enter(&sme_event_mtx);
175 1.13.2.2 ad /*
176 1.13.2.2 ad * Ensure that we don't add events for the same sensor
177 1.13.2.2 ad * and with the same type.
178 1.13.2.2 ad */
179 1.13.2.2 ad LIST_FOREACH(lsee, &sme_events_list, see_list) {
180 1.13.2.2 ad pes_old = &lsee->pes;
181 1.13.2.2 ad if (strcmp(pes_old->pes_sensname,
182 1.13.2.2 ad pes_new->pes_sensname) == 0) {
183 1.13.2.2 ad if (lsee->type == see->type) {
184 1.13.2.2 ad DPRINTF(("%s: dev=%s sensor=%s type=%d "
185 1.13.2.2 ad "(already exists)\n", __func__,
186 1.13.2.2 ad see->pes.pes_dvname,
187 1.13.2.2 ad see->pes.pes_sensname, see->type));
188 1.13.2.2 ad error = EEXIST;
189 1.13.2.2 ad goto out;
190 1.13.2.2 ad }
191 1.13.2.2 ad }
192 1.13.2.2 ad }
193 1.13.2.2 ad
194 1.13.2.2 ad DPRINTF(("%s: dev=%s sensor=%s snum=%d type=%d "
195 1.13.2.2 ad "critval=%" PRIu32 "\n", __func__,
196 1.13.2.2 ad see->pes.pes_dvname, see->pes.pes_sensname,
197 1.13.2.2 ad see->snum, see->type, see->critval));
198 1.13.2.2 ad
199 1.13.2.2 ad LIST_INSERT_HEAD(&sme_events_list, see, see_list);
200 1.13.2.2 ad /*
201 1.13.2.2 ad * Initialize the events framework if it wasn't initialized
202 1.13.2.2 ad * before.
203 1.13.2.2 ad */
204 1.13.2.2 ad mutex_enter(&sme_event_init_mtx);
205 1.13.2.2 ad if (sme_events_initialized == false)
206 1.13.2.2 ad error = sme_events_init();
207 1.13.2.2 ad mutex_exit(&sme_event_init_mtx);
208 1.13.2.2 ad
209 1.13.2.2 ad out:
210 1.13.2.2 ad mutex_exit(&sme_event_mtx);
211 1.13.2.2 ad return error;
212 1.13.2.2 ad }
213 1.13.2.2 ad
214 1.13.2.2 ad /*
215 1.13.2.2 ad * sme_event_unregister:
216 1.13.2.2 ad *
217 1.13.2.2 ad * + Unregisters a sysmon envsys event.
218 1.13.2.2 ad */
219 1.13.2.2 ad int
220 1.13.2.2 ad sme_event_unregister(const char *sensor, int type)
221 1.13.2.2 ad {
222 1.13.2.2 ad sme_event_t *see;
223 1.13.2.2 ad bool found = false;
224 1.13.2.2 ad
225 1.13.2.2 ad KASSERT(sensor != NULL);
226 1.13.2.2 ad
227 1.13.2.2 ad mutex_enter(&sme_event_mtx);
228 1.13.2.2 ad LIST_FOREACH(see, &sme_events_list, see_list) {
229 1.13.2.2 ad if (strcmp(see->pes.pes_sensname, sensor) == 0) {
230 1.13.2.2 ad if (see->type == type) {
231 1.13.2.2 ad found = true;
232 1.13.2.2 ad break;
233 1.13.2.2 ad }
234 1.13.2.2 ad }
235 1.13.2.2 ad }
236 1.13.2.2 ad
237 1.13.2.2 ad if (!found) {
238 1.13.2.2 ad mutex_exit(&sme_event_mtx);
239 1.13.2.2 ad return EINVAL;
240 1.13.2.2 ad }
241 1.13.2.2 ad
242 1.13.2.2 ad DPRINTF(("%s: removing dev=%s sensor=%s type=%d\n",
243 1.13.2.2 ad __func__, see->pes.pes_dvname, sensor, type));
244 1.13.2.2 ad LIST_REMOVE(see, see_list);
245 1.13.2.2 ad
246 1.13.2.2 ad /*
247 1.13.2.2 ad * So the events list is empty, we'll do the following:
248 1.13.2.2 ad *
249 1.13.2.2 ad * - stop and destroy the callout.
250 1.13.2.2 ad * - destroy the workqueue.
251 1.13.2.2 ad */
252 1.13.2.2 ad if (LIST_EMPTY(&sme_events_list)) {
253 1.13.2.2 ad mutex_exit(&sme_event_mtx);
254 1.13.2.2 ad
255 1.13.2.2 ad mutex_enter(&sme_event_init_mtx);
256 1.13.2.2 ad callout_stop(&seeco);
257 1.13.2.2 ad callout_destroy(&seeco);
258 1.13.2.2 ad workqueue_destroy(seewq);
259 1.13.2.2 ad sme_events_initialized = false;
260 1.13.2.2 ad DPRINTF(("%s: events framework destroyed\n", __func__));
261 1.13.2.2 ad mutex_exit(&sme_event_init_mtx);
262 1.13.2.2 ad goto out;
263 1.13.2.2 ad }
264 1.13.2.2 ad
265 1.13.2.2 ad mutex_exit(&sme_event_mtx);
266 1.13.2.2 ad kmem_free(see, sizeof(*see));
267 1.13.2.2 ad
268 1.13.2.2 ad out:
269 1.13.2.2 ad return 0;
270 1.13.2.2 ad }
271 1.13.2.2 ad
272 1.13.2.2 ad /*
273 1.13.2.2 ad * sme_event_drvadd:
274 1.13.2.2 ad *
275 1.13.2.2 ad * + Adds a new sysmon envsys event for a driver if a sensor
276 1.13.2.2 ad * has set any accepted monitoring flag.
277 1.13.2.2 ad */
278 1.13.2.2 ad void
279 1.13.2.2 ad sme_event_drvadd(void *arg)
280 1.13.2.2 ad {
281 1.13.2.2 ad sme_event_drv_t *sed_t = arg;
282 1.13.2.2 ad int error = 0;
283 1.13.2.2 ad
284 1.13.2.2 ad KASSERT(sed_t != NULL);
285 1.13.2.2 ad
286 1.13.2.2 ad #define SEE_REGEVENT(a, b, c) \
287 1.13.2.2 ad do { \
288 1.13.2.2 ad if (sed_t->edata->flags & (a)) { \
289 1.13.2.2 ad char str[32] = "monitoring-state-"; \
290 1.13.2.2 ad \
291 1.13.2.2 ad error = sme_event_add(sed_t->sdict, \
292 1.13.2.2 ad sed_t->edata, \
293 1.13.2.2 ad sed_t->sme->sme_name, \
294 1.13.2.2 ad NULL, \
295 1.13.2.2 ad 0, \
296 1.13.2.2 ad (b), \
297 1.13.2.2 ad sed_t->powertype); \
298 1.13.2.2 ad if (error && error != EEXIST) \
299 1.13.2.2 ad printf("%s: failed to add event! " \
300 1.13.2.2 ad "error=%d sensor=%s event=%s\n", \
301 1.13.2.2 ad __func__, error, sed_t->edata->desc, (c)); \
302 1.13.2.2 ad else { \
303 1.13.2.2 ad mutex_enter(&sme_mtx); \
304 1.13.2.2 ad (void)strlcat(str, (c), sizeof(str)); \
305 1.13.2.2 ad prop_dictionary_set_bool(sed_t->sdict, \
306 1.13.2.2 ad str, \
307 1.13.2.2 ad true); \
308 1.13.2.2 ad mutex_exit(&sme_mtx); \
309 1.13.2.2 ad } \
310 1.13.2.2 ad } \
311 1.13.2.2 ad } while (/* CONSTCOND */ 0)
312 1.13.2.2 ad
313 1.13.2.2 ad SEE_REGEVENT(ENVSYS_FMONCRITICAL,
314 1.13.2.2 ad PENVSYS_EVENT_CRITICAL,
315 1.13.2.2 ad "critical");
316 1.13.2.2 ad
317 1.13.2.2 ad SEE_REGEVENT(ENVSYS_FMONCRITUNDER,
318 1.13.2.2 ad PENVSYS_EVENT_CRITUNDER,
319 1.13.2.2 ad "critunder");
320 1.13.2.2 ad
321 1.13.2.2 ad SEE_REGEVENT(ENVSYS_FMONCRITOVER,
322 1.13.2.2 ad PENVSYS_EVENT_CRITOVER,
323 1.13.2.2 ad "critover");
324 1.13.2.2 ad
325 1.13.2.2 ad SEE_REGEVENT(ENVSYS_FMONWARNUNDER,
326 1.13.2.2 ad PENVSYS_EVENT_WARNUNDER,
327 1.13.2.2 ad "warnunder");
328 1.13.2.2 ad
329 1.13.2.2 ad SEE_REGEVENT(ENVSYS_FMONWARNOVER,
330 1.13.2.2 ad PENVSYS_EVENT_WARNOVER,
331 1.13.2.2 ad "warnover");
332 1.13.2.2 ad
333 1.13.2.2 ad SEE_REGEVENT(ENVSYS_FMONDRVSTATE,
334 1.13.2.2 ad PENVSYS_EVENT_DRIVE_STCHANGED,
335 1.13.2.2 ad "drvstchanged");
336 1.13.2.2 ad
337 1.13.2.2 ad /* we are done, free memory now */
338 1.13.2.2 ad kmem_free(sed_t, sizeof(*sed_t));
339 1.13.2.2 ad }
340 1.13.2.2 ad
341 1.13.2.2 ad /*
342 1.13.2.2 ad * sme_event_add:
343 1.13.2.2 ad *
344 1.13.2.2 ad * + Initializes or updates a sysmon envsys event.
345 1.13.2.2 ad */
346 1.13.2.2 ad int
347 1.13.2.2 ad sme_event_add(prop_dictionary_t sdict, envsys_data_t *edata,
348 1.13.2.2 ad const char *drvn, const char *objkey,
349 1.13.2.2 ad int32_t critval, int crittype, int powertype)
350 1.13.2.2 ad {
351 1.13.2.2 ad sme_event_t *see = NULL;
352 1.13.2.2 ad prop_object_t obj;
353 1.13.2.2 ad int error = 0;
354 1.13.2.2 ad
355 1.13.2.2 ad KASSERT(sdict != NULL || edata != NULL);
356 1.13.2.2 ad
357 1.13.2.2 ad /* critical condition set via userland */
358 1.13.2.2 ad if (objkey && critval) {
359 1.13.2.2 ad obj = prop_dictionary_get(sdict, objkey);
360 1.13.2.2 ad if (obj != NULL) {
361 1.13.2.2 ad /*
362 1.13.2.2 ad * object is already in dictionary, update
363 1.13.2.2 ad * the critical value.
364 1.13.2.2 ad */
365 1.13.2.2 ad mutex_enter(&sme_event_mtx);
366 1.13.2.2 ad LIST_FOREACH(see, &sme_events_list, see_list) {
367 1.13.2.2 ad if (strcmp(edata->desc,
368 1.13.2.2 ad see->pes.pes_sensname) == 0)
369 1.13.2.2 ad if (crittype == see->type)
370 1.13.2.2 ad break;
371 1.13.2.2 ad }
372 1.13.2.2 ad
373 1.13.2.2 ad if (see->critval != critval) {
374 1.13.2.2 ad see->critval = critval;
375 1.13.2.2 ad DPRINTF(("%s: sensor=%s type=%d "
376 1.13.2.2 ad "(critval updated)\n", __func__,
377 1.13.2.2 ad edata->desc, see->type));
378 1.13.2.2 ad }
379 1.13.2.2 ad
380 1.13.2.2 ad mutex_exit(&sme_event_mtx);
381 1.13.2.2 ad goto out;
382 1.13.2.2 ad }
383 1.13.2.2 ad }
384 1.13.2.2 ad
385 1.13.2.2 ad if (LIST_EMPTY(&sme_events_list))
386 1.13.2.2 ad goto register_event;
387 1.13.2.2 ad
388 1.13.2.2 ad /* check if the event is already on the list */
389 1.13.2.2 ad mutex_enter(&sme_event_mtx);
390 1.13.2.2 ad LIST_FOREACH(see, &sme_events_list, see_list) {
391 1.13.2.2 ad if (strcmp(edata->desc, see->pes.pes_sensname) == 0)
392 1.13.2.2 ad if (crittype == see->type) {
393 1.13.2.2 ad mutex_exit(&sme_event_mtx);
394 1.13.2.2 ad error = EEXIST;
395 1.13.2.2 ad goto out;
396 1.13.2.2 ad }
397 1.13.2.2 ad }
398 1.13.2.2 ad mutex_exit(&sme_event_mtx);
399 1.13.2.2 ad
400 1.13.2.2 ad /*
401 1.13.2.2 ad * object is not in dictionary, create a new
402 1.13.2.2 ad * sme event and assign required members.
403 1.13.2.2 ad */
404 1.13.2.2 ad register_event:
405 1.13.2.2 ad see = kmem_zalloc(sizeof(*see), KM_SLEEP);
406 1.13.2.2 ad
407 1.13.2.2 ad mutex_enter(&sme_event_mtx);
408 1.13.2.2 ad see->critval = critval;
409 1.13.2.2 ad see->type = crittype;
410 1.13.2.2 ad (void)strlcpy(see->pes.pes_dvname, drvn,
411 1.13.2.2 ad sizeof(see->pes.pes_dvname));
412 1.13.2.2 ad see->pes.pes_type = powertype;
413 1.13.2.2 ad (void)strlcpy(see->pes.pes_sensname, edata->desc,
414 1.13.2.2 ad sizeof(see->pes.pes_sensname));
415 1.13.2.2 ad see->snum = edata->sensor;
416 1.13.2.2 ad mutex_exit(&sme_event_mtx);
417 1.13.2.2 ad
418 1.13.2.2 ad error = sme_event_register(see);
419 1.13.2.2 ad if (error)
420 1.13.2.2 ad kmem_free(see, sizeof(*see));
421 1.13.2.2 ad
422 1.13.2.2 ad out:
423 1.13.2.2 ad /* update the object in the dictionary */
424 1.13.2.2 ad if (objkey && critval) {
425 1.13.2.2 ad mutex_enter(&sme_event_mtx);
426 1.13.2.2 ad SENSOR_UPINT32(sdict, objkey, critval);
427 1.13.2.2 ad mutex_exit(&sme_event_mtx);
428 1.13.2.2 ad }
429 1.13.2.2 ad
430 1.13.2.2 ad return error;
431 1.13.2.2 ad }
432 1.13.2.2 ad
433 1.13.2.2 ad /*
434 1.13.2.2 ad * sme_events_init:
435 1.13.2.2 ad *
436 1.13.2.2 ad * + Initializes the callout and the workqueue to handle
437 1.13.2.2 ad * the sysmon envsys events.
438 1.13.2.2 ad */
439 1.13.2.2 ad int
440 1.13.2.2 ad sme_events_init(void)
441 1.13.2.2 ad {
442 1.13.2.2 ad int error;
443 1.13.2.2 ad
444 1.13.2.2 ad error = workqueue_create(&seewq, "envsysev",
445 1.13.2.2 ad sme_events_worker, NULL, 0, IPL_SOFTCLOCK, 0);
446 1.13.2.2 ad if (error)
447 1.13.2.2 ad goto out;
448 1.13.2.2 ad
449 1.13.2.2 ad callout_init(&seeco, 0);
450 1.13.2.2 ad callout_setfunc(&seeco, sme_events_check, NULL);
451 1.13.2.2 ad callout_schedule(&seeco, SME_EVTIMO);
452 1.13.2.2 ad sme_events_initialized = true;
453 1.13.2.2 ad DPRINTF(("%s: events framework initialized\n", __func__));
454 1.13.2.2 ad
455 1.13.2.2 ad out:
456 1.13.2.2 ad return error;
457 1.13.2.2 ad }
458 1.13.2.2 ad
459 1.13.2.2 ad /*
460 1.13.2.2 ad * sme_events_check:
461 1.13.2.2 ad *
462 1.13.2.2 ad * + Runs the work on each sysmon envsys event in our
463 1.13.2.2 ad * workqueue periodically with callout.
464 1.13.2.2 ad */
465 1.13.2.2 ad void
466 1.13.2.2 ad sme_events_check(void *arg)
467 1.13.2.2 ad {
468 1.13.2.2 ad sme_event_t *see;
469 1.13.2.2 ad
470 1.13.2.2 ad LIST_FOREACH(see, &sme_events_list, see_list) {
471 1.13.2.2 ad DPRINTF(("%s: dev=%s sensor=%s type=%d\n",
472 1.13.2.2 ad __func__,
473 1.13.2.2 ad see->pes.pes_dvname,
474 1.13.2.2 ad see->pes.pes_sensname,
475 1.13.2.2 ad see->type));
476 1.13.2.2 ad workqueue_enqueue(seewq, &see->see_wk, NULL);
477 1.13.2.2 ad }
478 1.13.2.2 ad callout_schedule(&seeco, SME_EVTIMO);
479 1.13.2.2 ad }
480 1.13.2.2 ad
481 1.13.2.2 ad /*
482 1.13.2.2 ad * sme_events_worker:
483 1.13.2.2 ad *
484 1.13.2.2 ad * + workqueue thread that checks if there's a critical condition
485 1.13.2.2 ad * and sends an event if the condition was triggered.
486 1.13.2.2 ad */
487 1.13.2.2 ad void
488 1.13.2.2 ad sme_events_worker(struct work *wk, void *arg)
489 1.13.2.2 ad {
490 1.13.2.2 ad const struct sme_sensor_state *esds = sme_sensor_drive_state;
491 1.13.2.2 ad const struct sme_sensor_event *sse = sme_sensor_event;
492 1.13.2.2 ad sme_event_t *see = (void *)wk;
493 1.13.2.2 ad struct sysmon_envsys *sme;
494 1.13.2.2 ad envsys_data_t *edata;
495 1.13.2.2 ad int i, error = 0;
496 1.13.2.2 ad
497 1.13.2.2 ad KASSERT(wk == &see->see_wk);
498 1.13.2.2 ad
499 1.13.2.2 ad /* XXX: NOT YET mutex_enter(&sme_event_mtx); */
500 1.13.2.2 ad /*
501 1.13.2.2 ad * We have to find the sme device by looking
502 1.13.2.2 ad * at the power envsys device name.
503 1.13.2.2 ad */
504 1.13.2.2 ad LIST_FOREACH(sme, &sysmon_envsys_list, sme_list)
505 1.13.2.2 ad if (strcmp(sme->sme_name, see->pes.pes_dvname) == 0)
506 1.13.2.2 ad break;
507 1.13.2.2 ad
508 1.13.2.2 ad KASSERT(sme != NULL);
509 1.13.2.2 ad
510 1.13.2.2 ad /* get the sensor with the index specified in see->snum */
511 1.13.2.2 ad edata = &sme->sme_sensor_data[see->snum];
512 1.13.2.2 ad
513 1.13.2.2 ad /*
514 1.13.2.2 ad * refresh the sensor that was marked with a critical
515 1.13.2.2 ad * event.
516 1.13.2.2 ad */
517 1.13.2.2 ad if ((sme->sme_flags & SME_DISABLE_GTREDATA) == 0) {
518 1.13.2.2 ad error = (*sme->sme_gtredata)(sme, edata);
519 1.13.2.2 ad if (error) {
520 1.13.2.2 ad /* XXX: NOT YET mutex_exit(&sme_event_mtx); */
521 1.13.2.2 ad return;
522 1.13.2.2 ad }
523 1.13.2.2 ad }
524 1.13.2.2 ad
525 1.13.2.2 ad DPRINTF(("%s: desc=%s sensor=%d units=%d value_cur=%d\n",
526 1.13.2.2 ad __func__, edata->desc, edata->sensor,
527 1.13.2.2 ad edata->units, edata->value_cur));
528 1.13.2.2 ad
529 1.13.2.2 ad #define SME_SEND_NORMALEVENT() \
530 1.13.2.2 ad do { \
531 1.13.2.2 ad see->evsent = false; \
532 1.13.2.2 ad sysmon_penvsys_event(&see->pes, PENVSYS_EVENT_NORMAL); \
533 1.13.2.2 ad } while (/* CONSTCOND */ 0)
534 1.13.2.2 ad
535 1.13.2.2 ad #define SME_SEND_EVENT(type) \
536 1.13.2.2 ad do { \
537 1.13.2.2 ad see->evsent = true; \
538 1.13.2.2 ad sysmon_penvsys_event(&see->pes, (type)); \
539 1.13.2.2 ad } while (/* CONSTCOND */ 0)
540 1.13.2.2 ad
541 1.13.2.2 ad switch (see->type) {
542 1.13.2.2 ad /*
543 1.13.2.2 ad * if state is the same than the one that matches sse[i].state,
544 1.13.2.2 ad * send the event...
545 1.13.2.2 ad */
546 1.13.2.2 ad case PENVSYS_EVENT_CRITICAL:
547 1.13.2.2 ad case PENVSYS_EVENT_CRITUNDER:
548 1.13.2.2 ad case PENVSYS_EVENT_CRITOVER:
549 1.13.2.2 ad case PENVSYS_EVENT_WARNUNDER:
550 1.13.2.2 ad case PENVSYS_EVENT_WARNOVER:
551 1.13.2.2 ad for (i = 0; sse[i].state != -1; i++)
552 1.13.2.2 ad if (sse[i].event == see->type)
553 1.13.2.2 ad break;
554 1.13.2.2 ad
555 1.13.2.2 ad if (see->evsent && edata->state == ENVSYS_SVALID)
556 1.13.2.2 ad SME_SEND_NORMALEVENT();
557 1.13.2.2 ad
558 1.13.2.2 ad if (!see->evsent && edata->state == sse[i].state)
559 1.13.2.2 ad SME_SEND_EVENT(see->type);
560 1.13.2.2 ad
561 1.13.2.2 ad break;
562 1.13.2.2 ad /*
563 1.13.2.2 ad * if value_cur is lower than the limit, send the event...
564 1.13.2.2 ad */
565 1.13.2.2 ad case PENVSYS_EVENT_BATT_USERCAP:
566 1.13.2.2 ad case PENVSYS_EVENT_USER_CRITMIN:
567 1.13.2.2 ad if (see->evsent && edata->value_cur > see->critval)
568 1.13.2.2 ad SME_SEND_NORMALEVENT();
569 1.13.2.2 ad
570 1.13.2.2 ad if (!see->evsent && edata->value_cur < see->critval)
571 1.13.2.2 ad SME_SEND_EVENT(see->type);
572 1.13.2.2 ad
573 1.13.2.2 ad break;
574 1.13.2.2 ad /*
575 1.13.2.2 ad * if value_cur is higher than the limit, send the event...
576 1.13.2.2 ad */
577 1.13.2.2 ad case PENVSYS_EVENT_USER_CRITMAX:
578 1.13.2.2 ad if (see->evsent && edata->value_cur < see->critval)
579 1.13.2.2 ad SME_SEND_NORMALEVENT();
580 1.13.2.2 ad
581 1.13.2.2 ad if (!see->evsent && edata->value_cur > see->critval)
582 1.13.2.2 ad SME_SEND_EVENT(see->type);
583 1.13.2.2 ad
584 1.13.2.2 ad break;
585 1.13.2.2 ad /*
586 1.13.2.2 ad * if value_cur is not ENVSYS_DRIVE_ONLINE, send the event...
587 1.13.2.2 ad */
588 1.13.2.2 ad case PENVSYS_EVENT_DRIVE_STCHANGED:
589 1.13.2.2 ad /* the state has not been changed, just ignore the event */
590 1.13.2.2 ad if (edata->value_cur == see->evsent)
591 1.13.2.2 ad break;
592 1.13.2.2 ad
593 1.13.2.2 ad for (i = 0; esds[i].type != -1; i++)
594 1.13.2.2 ad if (esds[i].type == edata->value_cur)
595 1.13.2.2 ad break;
596 1.13.2.2 ad
597 1.13.2.2 ad /* copy current state description */
598 1.13.2.2 ad (void)strlcpy(see->pes.pes_statedesc, esds[i].desc,
599 1.13.2.2 ad sizeof(see->pes.pes_statedesc));
600 1.13.2.2 ad
601 1.13.2.2 ad /* state is ok again... send a normal event */
602 1.13.2.2 ad if (see->evsent && edata->value_cur == ENVSYS_DRIVE_ONLINE)
603 1.13.2.2 ad SME_SEND_NORMALEVENT();
604 1.13.2.2 ad
605 1.13.2.2 ad /* something bad happened to the drive... send the event */
606 1.13.2.2 ad if (see->evsent || edata->value_cur != ENVSYS_DRIVE_ONLINE) {
607 1.13.2.2 ad /* save current drive state */
608 1.13.2.2 ad see->evsent = edata->value_cur;
609 1.13.2.2 ad sysmon_penvsys_event(&see->pes, see->type);
610 1.13.2.2 ad }
611 1.13.2.2 ad
612 1.13.2.2 ad break;
613 1.13.2.2 ad }
614 1.13.2.2 ad /* XXX: NOT YET mutex_exit(&sme_event_mtx); */
615 1.13.2.2 ad }
616