1eb3a3472SHasso Tepper /* $OpenBSD: kern_sensors.c,v 1.19 2007/06/04 18:42:05 deraadt Exp $ */
2eb3a3472SHasso Tepper
3eb3a3472SHasso Tepper /*
4bce291d6SAlex Hornung * (MPSAFE)
5bce291d6SAlex Hornung *
6eb3a3472SHasso Tepper * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
7eb3a3472SHasso Tepper * Copyright (c) 2006 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
8eb3a3472SHasso Tepper *
9eb3a3472SHasso Tepper * Permission to use, copy, modify, and distribute this software for any
10eb3a3472SHasso Tepper * purpose with or without fee is hereby granted, provided that the above
11eb3a3472SHasso Tepper * copyright notice and this permission notice appear in all copies.
12eb3a3472SHasso Tepper *
13eb3a3472SHasso Tepper * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14eb3a3472SHasso Tepper * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15eb3a3472SHasso Tepper * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16eb3a3472SHasso Tepper * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17eb3a3472SHasso Tepper * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18eb3a3472SHasso Tepper * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19eb3a3472SHasso Tepper * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20eb3a3472SHasso Tepper */
21eb3a3472SHasso Tepper
22eb3a3472SHasso Tepper #include <sys/param.h>
23eb3a3472SHasso Tepper #include <sys/systm.h>
24eb3a3472SHasso Tepper #include <sys/kernel.h>
25eb3a3472SHasso Tepper #include <sys/malloc.h>
26eb3a3472SHasso Tepper #include <sys/kthread.h>
27eb3a3472SHasso Tepper #include <sys/queue.h>
28eb3a3472SHasso Tepper #include <sys/types.h>
29eb3a3472SHasso Tepper #include <sys/time.h>
30bce291d6SAlex Hornung #include <sys/spinlock.h>
31bce291d6SAlex Hornung #include <sys/spinlock2.h>
32eb3a3472SHasso Tepper #include <sys/lock.h>
33a6f507ccSSepherosa Ziehau #include <sys/cpu_topology.h>
34eb3a3472SHasso Tepper
35eb3a3472SHasso Tepper #include <sys/sysctl.h>
36eb3a3472SHasso Tepper #include <sys/sensors.h>
37eb3a3472SHasso Tepper
382dc01a00SSepherosa Ziehau static int sensordev_idmax;
392dc01a00SSepherosa Ziehau static TAILQ_HEAD(sensordev_list, ksensordev) sensordev_list =
4027305eacSSepherosa Ziehau TAILQ_HEAD_INITIALIZER(sensordev_list);
41eb3a3472SHasso Tepper
428ef41b85SSepherosa Ziehau static struct ksensordev *sensordev_get(int);
438ef41b85SSepherosa Ziehau static struct ksensor *sensor_find(struct ksensordev *, enum sensor_type,
448ef41b85SSepherosa Ziehau int);
45eb3a3472SHasso Tepper
46eb3a3472SHasso Tepper struct sensor_task {
47eb3a3472SHasso Tepper void *arg;
48eb3a3472SHasso Tepper void (*func)(void *);
49eb3a3472SHasso Tepper
50eb3a3472SHasso Tepper int period;
51cec73927SMatthew Dillon time_t nextrun; /* time_uptime */
5272a4f168SSepherosa Ziehau int running;
53f95d9b17SSepherosa Ziehau int cpuid;
54eb3a3472SHasso Tepper TAILQ_ENTRY(sensor_task) entry;
55eb3a3472SHasso Tepper };
56f95d9b17SSepherosa Ziehau TAILQ_HEAD(sensor_tasklist, sensor_task);
57f95d9b17SSepherosa Ziehau
58f95d9b17SSepherosa Ziehau struct sensor_taskthr {
59f95d9b17SSepherosa Ziehau struct sensor_tasklist list;
60f95d9b17SSepherosa Ziehau struct lock lock;
61f95d9b17SSepherosa Ziehau };
62eb3a3472SHasso Tepper
638ef41b85SSepherosa Ziehau static void sensor_task_thread(void *);
64f95d9b17SSepherosa Ziehau static void sensor_task_schedule(struct sensor_taskthr *,
65f95d9b17SSepherosa Ziehau struct sensor_task *);
668dc374faSSepherosa Ziehau
67dfb94396SSepherosa Ziehau static void sensordev_sysctl_install(struct ksensordev *);
68dfb94396SSepherosa Ziehau static void sensordev_sysctl_deinstall(struct ksensordev *);
69dfb94396SSepherosa Ziehau static void sensor_sysctl_install(struct ksensordev *,
70dfb94396SSepherosa Ziehau struct ksensor *);
71dfb94396SSepherosa Ziehau static void sensor_sysctl_deinstall(struct ksensordev *,
72dfb94396SSepherosa Ziehau struct ksensor *);
73eb3a3472SHasso Tepper
74f95d9b17SSepherosa Ziehau static struct sensor_taskthr sensor_task_threads[MAXCPU];
75a6f507ccSSepherosa Ziehau static int sensor_task_default_cpu;
76f95d9b17SSepherosa Ziehau
77eb3a3472SHasso Tepper void
sensordev_install(struct ksensordev * sensdev)78eb3a3472SHasso Tepper sensordev_install(struct ksensordev *sensdev)
79eb3a3472SHasso Tepper {
8027305eacSSepherosa Ziehau struct ksensordev *v, *after = NULL;
8127305eacSSepherosa Ziehau int num = 0;
82eb3a3472SHasso Tepper
83e50eb75eSSepherosa Ziehau SYSCTL_XLOCK();
84e50eb75eSSepherosa Ziehau
8527305eacSSepherosa Ziehau TAILQ_FOREACH(v, &sensordev_list, list) {
8627305eacSSepherosa Ziehau if (v->num == num) {
8727305eacSSepherosa Ziehau ++num;
8827305eacSSepherosa Ziehau after = v;
8927305eacSSepherosa Ziehau } else if (v->num > num) {
90eb3a3472SHasso Tepper break;
91eb3a3472SHasso Tepper }
9227305eacSSepherosa Ziehau }
9327305eacSSepherosa Ziehau
9427305eacSSepherosa Ziehau sensdev->num = num;
9527305eacSSepherosa Ziehau if (after == NULL) {
9627305eacSSepherosa Ziehau KKASSERT(sensdev->num == 0);
9727305eacSSepherosa Ziehau TAILQ_INSERT_HEAD(&sensordev_list, sensdev, list);
9827305eacSSepherosa Ziehau } else {
9927305eacSSepherosa Ziehau TAILQ_INSERT_AFTER(&sensordev_list, after, sensdev, list);
10027305eacSSepherosa Ziehau }
101eb3a3472SHasso Tepper
1022dc01a00SSepherosa Ziehau /* Save max sensor device id */
1032dc01a00SSepherosa Ziehau sensordev_idmax = TAILQ_LAST(&sensordev_list, sensordev_list)->num + 1;
1042dc01a00SSepherosa Ziehau
105dfb94396SSepherosa Ziehau /* Install sysctl node for this sensor device */
106dfb94396SSepherosa Ziehau sensordev_sysctl_install(sensdev);
107e50eb75eSSepherosa Ziehau
108e50eb75eSSepherosa Ziehau SYSCTL_XUNLOCK();
109eb3a3472SHasso Tepper }
110eb3a3472SHasso Tepper
111eb3a3472SHasso Tepper void
sensor_attach(struct ksensordev * sensdev,struct ksensor * sens)112eb3a3472SHasso Tepper sensor_attach(struct ksensordev *sensdev, struct ksensor *sens)
113eb3a3472SHasso Tepper {
114eb3a3472SHasso Tepper struct ksensor *v, *nv;
115eb3a3472SHasso Tepper struct ksensors_head *sh;
116eb3a3472SHasso Tepper int i;
117eb3a3472SHasso Tepper
118e50eb75eSSepherosa Ziehau SYSCTL_XLOCK();
119e50eb75eSSepherosa Ziehau
120eb3a3472SHasso Tepper sh = &sensdev->sensors_list;
121eb3a3472SHasso Tepper if (sensdev->sensors_count == 0) {
122eb3a3472SHasso Tepper for (i = 0; i < SENSOR_MAX_TYPES; i++)
123eb3a3472SHasso Tepper sensdev->maxnumt[i] = 0;
124eb3a3472SHasso Tepper sens->numt = 0;
125eb3a3472SHasso Tepper SLIST_INSERT_HEAD(sh, sens, list);
126eb3a3472SHasso Tepper } else {
127eb3a3472SHasso Tepper for (v = SLIST_FIRST(sh);
128eb3a3472SHasso Tepper (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
129*d314b0e9SSascha Wildner if (v->type == sens->type &&
130*d314b0e9SSascha Wildner (v->type != nv->type || nv->numt - v->numt > 1))
131eb3a3472SHasso Tepper break;
132eb3a3472SHasso Tepper /* sensors of the same type go after each other */
133eb3a3472SHasso Tepper if (v->type == sens->type)
134eb3a3472SHasso Tepper sens->numt = v->numt + 1;
135eb3a3472SHasso Tepper else
136eb3a3472SHasso Tepper sens->numt = 0;
137eb3a3472SHasso Tepper SLIST_INSERT_AFTER(v, sens, list);
138eb3a3472SHasso Tepper }
139e50eb75eSSepherosa Ziehau /*
140e50eb75eSSepherosa Ziehau * We only increment maxnumt[] if the sensor was added
141eb3a3472SHasso Tepper * to the last position of sensors of this type
142eb3a3472SHasso Tepper */
143eb3a3472SHasso Tepper if (sensdev->maxnumt[sens->type] == sens->numt)
144eb3a3472SHasso Tepper sensdev->maxnumt[sens->type]++;
145eb3a3472SHasso Tepper sensdev->sensors_count++;
146e50eb75eSSepherosa Ziehau
147dfb94396SSepherosa Ziehau /* Install sysctl node for this sensor */
148dfb94396SSepherosa Ziehau sensor_sysctl_install(sensdev, sens);
149dfb94396SSepherosa Ziehau
150e50eb75eSSepherosa Ziehau SYSCTL_XUNLOCK();
151eb3a3472SHasso Tepper }
152eb3a3472SHasso Tepper
153eb3a3472SHasso Tepper void
sensordev_deinstall(struct ksensordev * sensdev)154eb3a3472SHasso Tepper sensordev_deinstall(struct ksensordev *sensdev)
155eb3a3472SHasso Tepper {
1562dc01a00SSepherosa Ziehau struct ksensordev *last;
1572dc01a00SSepherosa Ziehau
158e50eb75eSSepherosa Ziehau SYSCTL_XLOCK();
159e50eb75eSSepherosa Ziehau
16027305eacSSepherosa Ziehau TAILQ_REMOVE(&sensordev_list, sensdev, list);
161eb3a3472SHasso Tepper
1622dc01a00SSepherosa Ziehau /* Adjust max sensor device id */
1632dc01a00SSepherosa Ziehau last = TAILQ_LAST(&sensordev_list, sensordev_list);
1642dc01a00SSepherosa Ziehau if (last != NULL)
1652dc01a00SSepherosa Ziehau sensordev_idmax = last->num + 1;
1662dc01a00SSepherosa Ziehau else
1672dc01a00SSepherosa Ziehau sensordev_idmax = 0;
1682dc01a00SSepherosa Ziehau
169dfb94396SSepherosa Ziehau /*
170dfb94396SSepherosa Ziehau * Deinstall sensor device's sysctl node; this also
171dfb94396SSepherosa Ziehau * removes all attached sensors' sysctl nodes.
172dfb94396SSepherosa Ziehau */
173dfb94396SSepherosa Ziehau sensordev_sysctl_deinstall(sensdev);
174e50eb75eSSepherosa Ziehau
175e50eb75eSSepherosa Ziehau SYSCTL_XUNLOCK();
176eb3a3472SHasso Tepper }
177eb3a3472SHasso Tepper
178eb3a3472SHasso Tepper void
sensor_detach(struct ksensordev * sensdev,struct ksensor * sens)179eb3a3472SHasso Tepper sensor_detach(struct ksensordev *sensdev, struct ksensor *sens)
180eb3a3472SHasso Tepper {
181eb3a3472SHasso Tepper struct ksensors_head *sh;
182eb3a3472SHasso Tepper
183e50eb75eSSepherosa Ziehau SYSCTL_XLOCK();
184e50eb75eSSepherosa Ziehau
185eb3a3472SHasso Tepper sh = &sensdev->sensors_list;
186eb3a3472SHasso Tepper sensdev->sensors_count--;
187eb3a3472SHasso Tepper SLIST_REMOVE(sh, sens, ksensor, list);
188e50eb75eSSepherosa Ziehau /*
189e50eb75eSSepherosa Ziehau * We only decrement maxnumt[] if this is the tail
190eb3a3472SHasso Tepper * sensor of this type
191eb3a3472SHasso Tepper */
192eb3a3472SHasso Tepper if (sens->numt == sensdev->maxnumt[sens->type] - 1)
193eb3a3472SHasso Tepper sensdev->maxnumt[sens->type]--;
194e50eb75eSSepherosa Ziehau
195dfb94396SSepherosa Ziehau /* Deinstall sensor's sysctl node */
196dfb94396SSepherosa Ziehau sensor_sysctl_deinstall(sensdev, sens);
197dfb94396SSepherosa Ziehau
198e50eb75eSSepherosa Ziehau SYSCTL_XUNLOCK();
199eb3a3472SHasso Tepper }
200eb3a3472SHasso Tepper
2018ef41b85SSepherosa Ziehau static struct ksensordev *
sensordev_get(int num)202eb3a3472SHasso Tepper sensordev_get(int num)
203eb3a3472SHasso Tepper {
204eb3a3472SHasso Tepper struct ksensordev *sd;
205eb3a3472SHasso Tepper
206b750642bSSascha Wildner SYSCTL_ASSERT_LOCKED();
207e50eb75eSSepherosa Ziehau
20827305eacSSepherosa Ziehau TAILQ_FOREACH(sd, &sensordev_list, list) {
209e50eb75eSSepherosa Ziehau if (sd->num == num)
210eb3a3472SHasso Tepper return (sd);
211bce291d6SAlex Hornung }
212eb3a3472SHasso Tepper return (NULL);
213eb3a3472SHasso Tepper }
214eb3a3472SHasso Tepper
2158ef41b85SSepherosa Ziehau static struct ksensor *
sensor_find(struct ksensordev * sensdev,enum sensor_type type,int numt)216eb3a3472SHasso Tepper sensor_find(struct ksensordev *sensdev, enum sensor_type type, int numt)
217eb3a3472SHasso Tepper {
218eb3a3472SHasso Tepper struct ksensor *s;
219eb3a3472SHasso Tepper struct ksensors_head *sh;
220eb3a3472SHasso Tepper
221b750642bSSascha Wildner SYSCTL_ASSERT_LOCKED();
222e50eb75eSSepherosa Ziehau
223eb3a3472SHasso Tepper sh = &sensdev->sensors_list;
224bce291d6SAlex Hornung SLIST_FOREACH(s, sh, list) {
225e50eb75eSSepherosa Ziehau if (s->type == type && s->numt == numt)
226eb3a3472SHasso Tepper return (s);
227bce291d6SAlex Hornung }
228eb3a3472SHasso Tepper return (NULL);
229eb3a3472SHasso Tepper }
230eb3a3472SHasso Tepper
2311bedd63aSSepherosa Ziehau void
sensor_task_register(void * arg,void (* func)(void *),int period)232eb3a3472SHasso Tepper sensor_task_register(void *arg, void (*func)(void *), int period)
233eb3a3472SHasso Tepper {
234f8f01153SSepherosa Ziehau sensor_task_register2(arg, func, period, -1);
235eb3a3472SHasso Tepper }
236eb3a3472SHasso Tepper
237eb3a3472SHasso Tepper void
sensor_task_unregister(void * arg)238eb3a3472SHasso Tepper sensor_task_unregister(void *arg)
239eb3a3472SHasso Tepper {
240a6f507ccSSepherosa Ziehau struct sensor_taskthr *thr;
241eb3a3472SHasso Tepper struct sensor_task *st;
242eb3a3472SHasso Tepper
243a6f507ccSSepherosa Ziehau thr = &sensor_task_threads[sensor_task_default_cpu];
244f95d9b17SSepherosa Ziehau lockmgr(&thr->lock, LK_EXCLUSIVE);
245f95d9b17SSepherosa Ziehau TAILQ_FOREACH(st, &thr->list, entry)
246eb3a3472SHasso Tepper if (st->arg == arg)
247eb3a3472SHasso Tepper st->running = 0;
248f95d9b17SSepherosa Ziehau lockmgr(&thr->lock, LK_RELEASE);
249f95d9b17SSepherosa Ziehau }
250f95d9b17SSepherosa Ziehau
251f95d9b17SSepherosa Ziehau void
sensor_task_unregister2(struct sensor_task * st)252f95d9b17SSepherosa Ziehau sensor_task_unregister2(struct sensor_task *st)
253f95d9b17SSepherosa Ziehau {
254f95d9b17SSepherosa Ziehau struct sensor_taskthr *thr;
255f95d9b17SSepherosa Ziehau
256f95d9b17SSepherosa Ziehau KASSERT(st->cpuid >= 0 && st->cpuid < ncpus,
257f95d9b17SSepherosa Ziehau ("invalid task cpuid %d", st->cpuid));
258f95d9b17SSepherosa Ziehau thr = &sensor_task_threads[st->cpuid];
259f95d9b17SSepherosa Ziehau
260f95d9b17SSepherosa Ziehau /*
261f95d9b17SSepherosa Ziehau * Hold the lock then zero-out running, so upon returning
262f95d9b17SSepherosa Ziehau * to the caller, the task will no longer run.
263f95d9b17SSepherosa Ziehau */
264f95d9b17SSepherosa Ziehau lockmgr(&thr->lock, LK_EXCLUSIVE);
265f95d9b17SSepherosa Ziehau st->running = 0;
266f95d9b17SSepherosa Ziehau lockmgr(&thr->lock, LK_RELEASE);
267f95d9b17SSepherosa Ziehau }
268f95d9b17SSepherosa Ziehau
269f95d9b17SSepherosa Ziehau struct sensor_task *
sensor_task_register2(void * arg,void (* func)(void *),int period,int cpu)270f95d9b17SSepherosa Ziehau sensor_task_register2(void *arg, void (*func)(void *), int period, int cpu)
271f95d9b17SSepherosa Ziehau {
272f95d9b17SSepherosa Ziehau struct sensor_taskthr *thr;
273f95d9b17SSepherosa Ziehau struct sensor_task *st;
274f95d9b17SSepherosa Ziehau
275f8f01153SSepherosa Ziehau if (cpu < 0)
276a6f507ccSSepherosa Ziehau cpu = sensor_task_default_cpu;
277f95d9b17SSepherosa Ziehau KASSERT(cpu >= 0 && cpu < ncpus, ("invalid cpuid %d", cpu));
278f95d9b17SSepherosa Ziehau thr = &sensor_task_threads[cpu];
279f95d9b17SSepherosa Ziehau
280f95d9b17SSepherosa Ziehau st = kmalloc(sizeof(struct sensor_task), M_DEVBUF, M_WAITOK);
281f95d9b17SSepherosa Ziehau
282f95d9b17SSepherosa Ziehau lockmgr(&thr->lock, LK_EXCLUSIVE);
283f95d9b17SSepherosa Ziehau st->arg = arg;
284f95d9b17SSepherosa Ziehau st->func = func;
285f95d9b17SSepherosa Ziehau st->period = period;
286f95d9b17SSepherosa Ziehau st->cpuid = cpu;
287f95d9b17SSepherosa Ziehau
288f95d9b17SSepherosa Ziehau st->running = 1;
289f95d9b17SSepherosa Ziehau
290f95d9b17SSepherosa Ziehau st->nextrun = 0;
291f95d9b17SSepherosa Ziehau TAILQ_INSERT_HEAD(&thr->list, st, entry);
292f95d9b17SSepherosa Ziehau
293f95d9b17SSepherosa Ziehau wakeup(&thr->list);
294f95d9b17SSepherosa Ziehau
295f95d9b17SSepherosa Ziehau lockmgr(&thr->lock, LK_RELEASE);
296f95d9b17SSepherosa Ziehau
297f95d9b17SSepherosa Ziehau return st;
298eb3a3472SHasso Tepper }
299eb3a3472SHasso Tepper
3008ef41b85SSepherosa Ziehau static void
sensor_task_thread(void * xthr)301f95d9b17SSepherosa Ziehau sensor_task_thread(void *xthr)
302eb3a3472SHasso Tepper {
303f95d9b17SSepherosa Ziehau struct sensor_taskthr *thr = xthr;
304eb3a3472SHasso Tepper struct sensor_task *st, *nst;
305eb3a3472SHasso Tepper time_t now;
306eb3a3472SHasso Tepper
307f95d9b17SSepherosa Ziehau lockmgr(&thr->lock, LK_EXCLUSIVE);
308cd8ab232SMatthew Dillon
3098dc374faSSepherosa Ziehau for (;;) {
310f95d9b17SSepherosa Ziehau while (TAILQ_EMPTY(&thr->list))
311f95d9b17SSepherosa Ziehau lksleep(&thr->list, &thr->lock, 0, "waittask", 0);
3128dc374faSSepherosa Ziehau
313f95d9b17SSepherosa Ziehau while ((nst = TAILQ_FIRST(&thr->list))->nextrun >
314a6a80759SSepherosa Ziehau (now = time_uptime)) {
315f95d9b17SSepherosa Ziehau lksleep(&thr->list, &thr->lock, 0,
316a6a80759SSepherosa Ziehau "timeout", (nst->nextrun - now) * hz);
317a6a80759SSepherosa Ziehau }
318eb3a3472SHasso Tepper
319eb3a3472SHasso Tepper while ((st = nst) != NULL) {
320eb3a3472SHasso Tepper nst = TAILQ_NEXT(st, entry);
321eb3a3472SHasso Tepper
322eb3a3472SHasso Tepper if (st->nextrun > now)
323eb3a3472SHasso Tepper break;
324eb3a3472SHasso Tepper
325eb3a3472SHasso Tepper /* take it out while we work on it */
326f95d9b17SSepherosa Ziehau TAILQ_REMOVE(&thr->list, st, entry);
327eb3a3472SHasso Tepper
328eb3a3472SHasso Tepper if (!st->running) {
329eb3a3472SHasso Tepper kfree(st, M_DEVBUF);
330eb3a3472SHasso Tepper continue;
331eb3a3472SHasso Tepper }
332eb3a3472SHasso Tepper
333eb3a3472SHasso Tepper /* run the task */
334eb3a3472SHasso Tepper st->func(st->arg);
335eb3a3472SHasso Tepper /* stick it back in the tasklist */
336f95d9b17SSepherosa Ziehau sensor_task_schedule(thr, st);
337eb3a3472SHasso Tepper }
338eb3a3472SHasso Tepper }
339eb3a3472SHasso Tepper
340f95d9b17SSepherosa Ziehau lockmgr(&thr->lock, LK_RELEASE);
341eb3a3472SHasso Tepper }
342eb3a3472SHasso Tepper
3438ef41b85SSepherosa Ziehau static void
sensor_task_schedule(struct sensor_taskthr * thr,struct sensor_task * st)344f95d9b17SSepherosa Ziehau sensor_task_schedule(struct sensor_taskthr *thr, struct sensor_task *st)
345eb3a3472SHasso Tepper {
346eb3a3472SHasso Tepper struct sensor_task *cst;
347eb3a3472SHasso Tepper
348f95d9b17SSepherosa Ziehau KASSERT(lockstatus(&thr->lock, curthread) == LK_EXCLUSIVE,
349c1bc662cSSepherosa Ziehau ("sensor task lock is not held"));
350c1bc662cSSepherosa Ziehau
351cec73927SMatthew Dillon st->nextrun = time_uptime + st->period;
352eb3a3472SHasso Tepper
353f95d9b17SSepherosa Ziehau TAILQ_FOREACH(cst, &thr->list, entry) {
354eb3a3472SHasso Tepper if (cst->nextrun > st->nextrun) {
355eb3a3472SHasso Tepper TAILQ_INSERT_BEFORE(cst, st, entry);
356eb3a3472SHasso Tepper return;
357eb3a3472SHasso Tepper }
358eb3a3472SHasso Tepper }
359eb3a3472SHasso Tepper
360eb3a3472SHasso Tepper /* must be an empty list, or at the end of the list */
361f95d9b17SSepherosa Ziehau TAILQ_INSERT_TAIL(&thr->list, st, entry);
362eb3a3472SHasso Tepper }
363eb3a3472SHasso Tepper
364eb3a3472SHasso Tepper /*
365eb3a3472SHasso Tepper * sysctl glue code
366eb3a3472SHasso Tepper */
3678ef41b85SSepherosa Ziehau static int sysctl_handle_sensordev(SYSCTL_HANDLER_ARGS);
3688ef41b85SSepherosa Ziehau static int sysctl_handle_sensor(SYSCTL_HANDLER_ARGS);
3698ef41b85SSepherosa Ziehau static int sysctl_sensors_handler(SYSCTL_HANDLER_ARGS);
370eb3a3472SHasso Tepper
371eb3a3472SHasso Tepper SYSCTL_NODE(_hw, OID_AUTO, sensors, CTLFLAG_RD, NULL,
372eb3a3472SHasso Tepper "Hardware Sensors sysctl internal magic");
373eb3a3472SHasso Tepper SYSCTL_NODE(_hw, HW_SENSORS, _sensors, CTLFLAG_RD, sysctl_sensors_handler,
374eb3a3472SHasso Tepper "Hardware Sensors XP MIB interface");
375eb3a3472SHasso Tepper
3762dc01a00SSepherosa Ziehau SYSCTL_INT(_hw_sensors, OID_AUTO, dev_idmax, CTLFLAG_RD,
3772dc01a00SSepherosa Ziehau &sensordev_idmax, 0, "Max sensor device id");
3782dc01a00SSepherosa Ziehau
3798ef41b85SSepherosa Ziehau static void
sensordev_sysctl_install(struct ksensordev * sensdev)380dfb94396SSepherosa Ziehau sensordev_sysctl_install(struct ksensordev *sensdev)
381eb3a3472SHasso Tepper {
382eb3a3472SHasso Tepper struct sysctl_ctx_list *cl = &sensdev->clist;
383eb3a3472SHasso Tepper struct ksensor *s;
384eb3a3472SHasso Tepper struct ksensors_head *sh = &sensdev->sensors_list;
385eb3a3472SHasso Tepper
386b750642bSSascha Wildner SYSCTL_ASSERT_LOCKED();
387e50eb75eSSepherosa Ziehau
388dfb94396SSepherosa Ziehau KASSERT(sensdev->oid == NULL,
389dfb94396SSepherosa Ziehau ("sensor device %s sysctl node already installed", sensdev->xname));
390dfb94396SSepherosa Ziehau
391eb3a3472SHasso Tepper sysctl_ctx_init(cl);
3922ce2b389SSepherosa Ziehau sensdev->oid = SYSCTL_ADD_NODE(cl, SYSCTL_STATIC_CHILDREN(_hw_sensors),
3932ce2b389SSepherosa Ziehau sensdev->num, sensdev->xname, CTLFLAG_RD, NULL, "");
3942ce2b389SSepherosa Ziehau if (sensdev->oid == NULL) {
3952ce2b389SSepherosa Ziehau kprintf("sensor: add sysctl tree for %s failed\n",
3962ce2b389SSepherosa Ziehau sensdev->xname);
3972ce2b389SSepherosa Ziehau return;
3982ce2b389SSepherosa Ziehau }
3992ce2b389SSepherosa Ziehau
400dfb94396SSepherosa Ziehau /* Install sysctl nodes for sensors attached to this sensor device */
401dfb94396SSepherosa Ziehau SLIST_FOREACH(s, sh, list)
402dfb94396SSepherosa Ziehau sensor_sysctl_install(sensdev, s);
403dfb94396SSepherosa Ziehau }
404dfb94396SSepherosa Ziehau
405dfb94396SSepherosa Ziehau static void
sensor_sysctl_install(struct ksensordev * sensdev,struct ksensor * sens)406dfb94396SSepherosa Ziehau sensor_sysctl_install(struct ksensordev *sensdev, struct ksensor *sens)
407dfb94396SSepherosa Ziehau {
408eb3a3472SHasso Tepper char n[32];
409eb3a3472SHasso Tepper
410b750642bSSascha Wildner SYSCTL_ASSERT_LOCKED();
411dfb94396SSepherosa Ziehau
412dfb94396SSepherosa Ziehau if (sensdev->oid == NULL) {
413dfb94396SSepherosa Ziehau /* Sensor device sysctl node is not installed yet */
414dfb94396SSepherosa Ziehau return;
415dfb94396SSepherosa Ziehau }
416dfb94396SSepherosa Ziehau
417dfb94396SSepherosa Ziehau ksnprintf(n, sizeof(n), "%s%d", sensor_type_s[sens->type], sens->numt);
418dfb94396SSepherosa Ziehau KASSERT(sens->oid == NULL,
419dfb94396SSepherosa Ziehau ("sensor %s:%s sysctl node already installed", sensdev->xname, n));
420dfb94396SSepherosa Ziehau
421dfb94396SSepherosa Ziehau sens->oid = SYSCTL_ADD_PROC(&sensdev->clist,
422dfb94396SSepherosa Ziehau SYSCTL_CHILDREN(sensdev->oid), OID_AUTO, n,
423dfb94396SSepherosa Ziehau CTLTYPE_STRUCT | CTLFLAG_RD, sens, 0, sysctl_handle_sensor,
424dfb94396SSepherosa Ziehau "S,sensor", "");
425dfb94396SSepherosa Ziehau }
426dfb94396SSepherosa Ziehau
427dfb94396SSepherosa Ziehau static void
sensordev_sysctl_deinstall(struct ksensordev * sensdev)428dfb94396SSepherosa Ziehau sensordev_sysctl_deinstall(struct ksensordev *sensdev)
429dfb94396SSepherosa Ziehau {
430b750642bSSascha Wildner SYSCTL_ASSERT_LOCKED();
431dfb94396SSepherosa Ziehau
432dfb94396SSepherosa Ziehau if (sensdev->oid != NULL) {
433dfb94396SSepherosa Ziehau sysctl_ctx_free(&sensdev->clist);
434dfb94396SSepherosa Ziehau sensdev->oid = NULL;
435eb3a3472SHasso Tepper }
436eb3a3472SHasso Tepper }
437eb3a3472SHasso Tepper
4388ef41b85SSepherosa Ziehau static void
sensor_sysctl_deinstall(struct ksensordev * sensdev,struct ksensor * sens)439dfb94396SSepherosa Ziehau sensor_sysctl_deinstall(struct ksensordev *sensdev, struct ksensor *sens)
440eb3a3472SHasso Tepper {
441b750642bSSascha Wildner SYSCTL_ASSERT_LOCKED();
442e50eb75eSSepherosa Ziehau
443dfb94396SSepherosa Ziehau if (sensdev->oid != NULL && sens->oid != NULL) {
444dfb94396SSepherosa Ziehau sysctl_ctx_entry_del(&sensdev->clist, sens->oid);
445dfb94396SSepherosa Ziehau sysctl_remove_oid(sens->oid, 1, 0);
446dfb94396SSepherosa Ziehau }
447dfb94396SSepherosa Ziehau sens->oid = NULL;
448eb3a3472SHasso Tepper }
449eb3a3472SHasso Tepper
4508ef41b85SSepherosa Ziehau static int
sysctl_handle_sensordev(SYSCTL_HANDLER_ARGS)451eb3a3472SHasso Tepper sysctl_handle_sensordev(SYSCTL_HANDLER_ARGS)
452eb3a3472SHasso Tepper {
453eb3a3472SHasso Tepper struct ksensordev *ksd = arg1;
454eb3a3472SHasso Tepper struct sensordev *usd;
455eb3a3472SHasso Tepper int error;
456eb3a3472SHasso Tepper
457eb3a3472SHasso Tepper if (req->newptr)
458eb3a3472SHasso Tepper return (EPERM);
459eb3a3472SHasso Tepper
460eb3a3472SHasso Tepper /* Grab a copy, to clear the kernel pointers */
461e7b4468cSSascha Wildner usd = kmalloc(sizeof(*usd), M_TEMP, M_WAITOK | M_ZERO);
462eb3a3472SHasso Tepper usd->num = ksd->num;
463eb3a3472SHasso Tepper strlcpy(usd->xname, ksd->xname, sizeof(usd->xname));
464eb3a3472SHasso Tepper memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt));
465eb3a3472SHasso Tepper usd->sensors_count = ksd->sensors_count;
466eb3a3472SHasso Tepper
467eb3a3472SHasso Tepper error = SYSCTL_OUT(req, usd, sizeof(struct sensordev));
468eb3a3472SHasso Tepper
469eb3a3472SHasso Tepper kfree(usd, M_TEMP);
470eb3a3472SHasso Tepper return (error);
471eb3a3472SHasso Tepper }
472eb3a3472SHasso Tepper
4738ef41b85SSepherosa Ziehau static int
sysctl_handle_sensor(SYSCTL_HANDLER_ARGS)474eb3a3472SHasso Tepper sysctl_handle_sensor(SYSCTL_HANDLER_ARGS)
475eb3a3472SHasso Tepper {
476eb3a3472SHasso Tepper struct ksensor *ks = arg1;
477eb3a3472SHasso Tepper struct sensor *us;
478eb3a3472SHasso Tepper int error;
479eb3a3472SHasso Tepper
480eb3a3472SHasso Tepper if (req->newptr)
481eb3a3472SHasso Tepper return (EPERM);
482eb3a3472SHasso Tepper
483eb3a3472SHasso Tepper /* Grab a copy, to clear the kernel pointers */
484e7b4468cSSascha Wildner us = kmalloc(sizeof(*us), M_TEMP, M_WAITOK | M_ZERO);
485eb3a3472SHasso Tepper memcpy(us->desc, ks->desc, sizeof(ks->desc));
486eb3a3472SHasso Tepper us->tv = ks->tv;
487eb3a3472SHasso Tepper us->value = ks->value;
488eb3a3472SHasso Tepper us->type = ks->type;
489eb3a3472SHasso Tepper us->status = ks->status;
490eb3a3472SHasso Tepper us->numt = ks->numt;
491eb3a3472SHasso Tepper us->flags = ks->flags;
492eb3a3472SHasso Tepper
493eb3a3472SHasso Tepper error = SYSCTL_OUT(req, us, sizeof(struct sensor));
494eb3a3472SHasso Tepper
495eb3a3472SHasso Tepper kfree(us, M_TEMP);
496eb3a3472SHasso Tepper return (error);
497eb3a3472SHasso Tepper }
498eb3a3472SHasso Tepper
4998ef41b85SSepherosa Ziehau static int
sysctl_sensors_handler(SYSCTL_HANDLER_ARGS)500eb3a3472SHasso Tepper sysctl_sensors_handler(SYSCTL_HANDLER_ARGS)
501eb3a3472SHasso Tepper {
502eb3a3472SHasso Tepper int *name = arg1;
503eb3a3472SHasso Tepper u_int namelen = arg2;
504eb3a3472SHasso Tepper struct ksensordev *ksd;
505eb3a3472SHasso Tepper struct ksensor *ks;
506eb3a3472SHasso Tepper int dev, numt;
507eb3a3472SHasso Tepper enum sensor_type type;
508eb3a3472SHasso Tepper
509eb3a3472SHasso Tepper if (namelen != 1 && namelen != 3)
510eb3a3472SHasso Tepper return (ENOTDIR);
511eb3a3472SHasso Tepper
512eb3a3472SHasso Tepper dev = name[0];
513eb3a3472SHasso Tepper if ((ksd = sensordev_get(dev)) == NULL)
514eb3a3472SHasso Tepper return (ENOENT);
515eb3a3472SHasso Tepper
516eb3a3472SHasso Tepper if (namelen == 1)
517eb3a3472SHasso Tepper return (sysctl_handle_sensordev(NULL, ksd, 0, req));
518eb3a3472SHasso Tepper
519eb3a3472SHasso Tepper type = name[1];
520eb3a3472SHasso Tepper numt = name[2];
521eb3a3472SHasso Tepper
522eb3a3472SHasso Tepper if ((ks = sensor_find(ksd, type, numt)) == NULL)
523eb3a3472SHasso Tepper return (ENOENT);
524eb3a3472SHasso Tepper return (sysctl_handle_sensor(NULL, ks, 0, req));
525eb3a3472SHasso Tepper }
5268dc374faSSepherosa Ziehau
5278dc374faSSepherosa Ziehau static void
sensor_sysinit(void * arg __unused)5288dc374faSSepherosa Ziehau sensor_sysinit(void *arg __unused)
5298dc374faSSepherosa Ziehau {
530a6f507ccSSepherosa Ziehau const cpu_node_t *node;
531f95d9b17SSepherosa Ziehau int cpu;
5328dc374faSSepherosa Ziehau
533a6f507ccSSepherosa Ziehau /*
534a6f507ccSSepherosa Ziehau * By default, stick sensor tasks to the cpu belonging to
535a6f507ccSSepherosa Ziehau * the first cpu package, since most of the time accessing
536a6f507ccSSepherosa Ziehau * sensor devices from the first cpu package will be faster,
537a6f507ccSSepherosa Ziehau * e.g. through DMI or DMI2 on Intel CPUs; no QPI will be
538a6f507ccSSepherosa Ziehau * generated.
539a6f507ccSSepherosa Ziehau */
540a6f507ccSSepherosa Ziehau node = get_cpu_node_by_chipid(0);
541a6f507ccSSepherosa Ziehau if (node != NULL && node->child_no > 0)
542a6f507ccSSepherosa Ziehau sensor_task_default_cpu = BSRCPUMASK(node->members);
543a6f507ccSSepherosa Ziehau else
544a6f507ccSSepherosa Ziehau sensor_task_default_cpu = ncpus - 1;
545a6f507ccSSepherosa Ziehau if (bootverbose) {
546a6f507ccSSepherosa Ziehau kprintf("sensors: tasks default to cpu%d\n",
547a6f507ccSSepherosa Ziehau sensor_task_default_cpu);
548a6f507ccSSepherosa Ziehau }
549a6f507ccSSepherosa Ziehau
550f95d9b17SSepherosa Ziehau for (cpu = 0; cpu < ncpus; ++cpu) {
551f95d9b17SSepherosa Ziehau struct sensor_taskthr *thr = &sensor_task_threads[cpu];
552f95d9b17SSepherosa Ziehau int error;
553f95d9b17SSepherosa Ziehau
554f95d9b17SSepherosa Ziehau TAILQ_INIT(&thr->list);
555f95d9b17SSepherosa Ziehau lockinit(&thr->lock, "sensorthr", 0, LK_CANRECURSE);
556f95d9b17SSepherosa Ziehau
557f95d9b17SSepherosa Ziehau error = kthread_create_cpu(sensor_task_thread, thr, NULL, cpu,
558f95d9b17SSepherosa Ziehau "sensors %d", cpu);
5598dc374faSSepherosa Ziehau if (error)
5601c05a629SSepherosa Ziehau panic("sensors kthread on cpu%d failed: %d", cpu, error);
5618dc374faSSepherosa Ziehau }
562f95d9b17SSepherosa Ziehau }
5638dc374faSSepherosa Ziehau SYSINIT(sensor, SI_SUB_PRE_DRIVERS, SI_ORDER_ANY, sensor_sysinit, NULL);
564