1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2024 Oxide Computer Company
14 */
15
16 /*
17 * Kernel Sensor Framework
18 *
19 * The kernel sensor framework exists to provide a simple and straightforward
20 * means for various parts of the system to declare and instantiate sensor
21 * information. Between this and the ksensor character device
22 * (uts/common/io/ksensor/ksensor_drv.c) this exposes per-device sensors and
23 * character devices.
24 *
25 * --------------------------
26 * Driver and User Interfaces
27 * --------------------------
28 *
29 * Each sensor that is registered with the framework is exposed as a character
30 * device under /dev/sensors. The device class and node name are often ':'
31 * delineated and must begin with 'ddi_sensor'. Everything after 'ddi_sensor'
32 * will be created in a directory under /dev/sensors. So for example the Intel
33 * PCH driver uses a class "ddi_sensor:temperature:pch" and a node name of
34 * 'ts.%d'. This creates the node /dev/sensors/temperature/pch/ts.0. The
35 * devfsadm plugin automatically handles the creation of directories which makes
36 * the addition of additional sensor types easy to create.
37 *
38 * Strictly speaking, any device can manage their own sensors and minor nodes by
39 * using the appropriate class and implementing the corresponding ioctls. That
40 * was how the first kernel sensors were written; however, there are a lot of
41 * issues with that which led to this:
42 *
43 * 1. Every driver had to actually implement character devices.
44 *
45 * 2. Every driver had to duplicate a lot of the logic around open(9E),
46 * close(9E), and ioctl(9E).
47 *
48 * 3. Drivers that tied into frameworks like mac(9E) or SCSAv3 needed a lot more
49 * work to fit into this model. For example, because the minor state is
50 * shared between all the instances and the frameworks, they would have
51 * required shared, global state that they don't have today.
52 *
53 * Ultimately, having an operations vector and a callback argument makes work a
54 * lot simpler for the producers of sensor data and that simplicity makes it
55 * worthwhile to take on additional effort and work here.
56 *
57 * ----------
58 * Components
59 * ----------
60 *
61 * The ksensor framework is made of a couple of different pieces:
62 *
63 * 1. This glue that is a part of genunix.
64 * 2. The ksensor character device driver.
65 * 3. Sensor providers, which are generally drivers that register with the
66 * ksensor framework.
67 *
68 * The implementation of (1) is all in this file. The implementation of (2) is
69 * in uts/common/io/ksensor/ksensor_drv.c. The implementation of (3) is found in
70 * all of the different leaf devices. Examples of (3) include pchtemp(4D) and
71 * igb(4D).
72 *
73 * We separate numbers one and two into two different components for a few
74 * reasons. The most important thing is that drivers that provide sensors should
75 * not be dependent on some other part of the system having been loaded. This
76 * makes a compelling argument for it being a part of the core kernel. However,
77 * like other subsystems (e.g. kstats, smbios, etc.), it's useful to separate
78 * out the thing that provides the interface to users with the thing that is
79 * used to glue together providers in the kernel. There's the added benefit that
80 * it's practically simpler to spin up a pseudo-device through a module.
81 *
82 * The ksensor character device driver (2) registers with the main genunix
83 * ksensor code (1) when it attaches and when it detaches. The kernel only
84 * allows a single driver to be attached to it. When that character device
85 * driver attaches, the ksensor framework will walk through all of the currently
86 * registered sensors and inform the character device driver of the nodes that
87 * it needs to create. While the character device driver is attached, the
88 * ksensor framework will also call back into it when a sensor needs to be
89 * removed.
90 *
91 * Generally speaking, this distinction of responsibilities allows the kernel
92 * sensor character device driver to attach and detach without impact to the
93 * sensor providers or them even being notified at all, it's all transparent to
94 * them.
95 *
96 * ------------------------------
97 * Sensor Lifetime and detach(9E)
98 * ------------------------------
99 *
100 * Traditionally, a device driver may be detached by the broader kernel whenever
101 * the kernel desires it. On debug builds this happens by a dedicated thread. On
102 * a non-debug build this may happen due to memory pressure or as an attempt to
103 * reclaim idle resources (though this is much less common). However, when the
104 * module is detached, the system remembers that minor nodes previously existed
105 * and that entries in /devices had been created. When something proceeds to
106 * access an entry in /devices again, the system will use that to bring a driver
107 * back to life. It doesn't matter whether it's a pseudo-device driver or
108 * something else, this can happen.
109 *
110 * One downside to the sensor framework, is that we need to emulate this
111 * behavior which leads to some amount of complexity here. But this is a
112 * worthwhile tradeoff as it makes things much simpler for providers and it's
113 * not too hard for us to emulate this behavior.
114 *
115 * When a sensor provider registers the sensor, the sensor becomes available to
116 * the system. When the sensor provider unregisters with the system, which
117 * happens during its detach routine, then we note that it has been detached;
118 * however, we don't delete its minor node and if something accesses it, we
119 * attempt to load the driver again, the same way that devfs (the file system
120 * behind /devices) does.
121 *
122 * For each dev_info_t that registers a sensor we register a callback such that
123 * when the device is removed, e.g. someone called rem_drv or physically pulls
124 * the device, then we'll be able to finally clean up the device. This lifetime
125 * can be represented in the following image:
126 *
127 * |
128 * |
129 * +-----<-------------------------------------+
130 * | |
131 * | . . call ksensor_create() |
132 * v |
133 * +-------+ |
134 * | Valid | |
135 * +-------+ |
136 * | ^
137 * | . . call ksensor_remove() |
138 * v |
139 * +---------+ |
140 * | Invalid | |
141 * +---------+ |
142 * | | |
143 * | | . . user uses sensor again |
144 * | | |
145 * | +-------------------+ |
146 * | | |
147 * | v |
148 * | +---------------+ |
149 * | | Attatching... |-->---------+
150 * | +---------------+
151 * | . . ddi unbind cb |
152 * | |
153 * v | . . attatch fails or
154 * +---------+ | no call to ksensor_create()
155 * | Deleted |--<---------------+ again
156 * +---------+
157 *
158 * When the DDI unbind callback is called, we know that the device is going to
159 * be removed. However, this happens within a subtle context with a majority of
160 * the device tree held (at least the dip's parent). In particular, another
161 * thread may be trying to obtain a hold on it and be blocked in
162 * ndi_devi_enter(). As the callback thread holds that, that could lead to a
163 * deadlock. As a result, we clean things up in two phases. One during the
164 * synchronous callback and the other via a taskq. In the first phase we
165 * logically do the following:
166 *
167 * o Remove the dip from the list of ksensor dips and set the flag that
168 * indicates that it's been removed.
169 * o Remove all of the sensors from the global avl to make sure that new
170 * threads cannot look it up.
171 *
172 * Then, after the taskq is dispatched, we do the following in taskq context:
173 *
174 * o Tell the ksensor driver that it should remove the minor node.
175 * o Block on each sensor until it is no-longer busy and then clean it up.
176 * o Clean up the ksensor_dip_t.
177 *
178 * ------------------
179 * Accessing a Sensor
180 * ------------------
181 *
182 * Access to a particular sensor is serialized in the system. In addition to
183 * that, a number of steps are required to access one that is not unlike
184 * accessing a character device. When a given sensor is held the KSENSOR_F_BUSY
185 * flag is set in the ksensor_flags member. In addition, as part of taking a
186 * hold a number of side effects occur that ensure that the sensor provider's
187 * dev_info_t is considered busy and can't be detached.
188 *
189 * To obtain a hold on a sensor the following logical steps are required (see
190 * ksensor_hold_by_id() for the implementation):
191 *
192 * 1. Map the minor to the ksensor_t via the avl tree
193 * 2. Check that the ksensor's dip is valid
194 * 3. If the sensor is busy, wait until it is no longer so, and restart from
195 * the top. Otherwise, mark the sensor as busy.
196 * 4. Enter the parent and place a hold on the sensor provider's dip.
197 * 5. Once again check if the dip is removed or not because we have to drop
198 * locks during that operation.
199 * 6. Check if the ksensor has the valid flag set. If not, attempt to configure
200 * the dip.
201 * 7. Assuming the sensor is now valid, we can return it.
202 *
203 * After this point, the sensor is considered valid for use. Once the consumer
204 * is finished with the sensor, it should be released by calling
205 * ksensor_release().
206 *
207 * An important aspect of the above scheme is that the KSENSOR_F_BUSY flag is
208 * required to progress through the validation and holding of the device. This
209 * makes sure that only one thread is attempting to attach it at a given time. A
210 * reasonable future optimization would be to amortize this cost in open(9E)
211 * and close(9E) of the minor and to bump a count as it being referenced as long
212 * as it is open.
213 *
214 * -----------------------------
215 * Character Device Registration
216 * -----------------------------
217 *
218 * The 'ksensor' character device driver can come and go. To support this, the
219 * ksensor framework communicates with the ksensor character device by a
220 * well-defined set of callbacks, used to indicate sensor addition and removal.
221 * The ksensor character device is found in uts/common/io/ksensor/ksensor_drv.c.
222 * The ksensor character device is responsible for creating and destroying minor
223 * nodes.
224 *
225 * Each ksensor_t has a flag, KSENSOR_F_NOTIFIED, that is used to indicate
226 * whether or not the registered driver has been notified of the sensor. When a
227 * callback is first registered, we'll walk through the entire list of nodes to
228 * make sure that its minor has been created. When unregistering, the minor node
229 * remove callback will not be called; however, this can generally by dealt with
230 * by calling something like ddi_remove_minor_node(dip, NULL).
231 *
232 * -------
233 * Locking
234 * -------
235 *
236 * The following rules apply to dealing with lock ordering:
237 *
238 * 1. The global ksensor_g_mutex protects all global data and must be taken
239 * before a ksensor_t's individual mutex.
240 *
241 * 2. A thread should not hold any two ksensor_t's mutex at any time.
242 *
243 * 3. No locks should be held when attempting to grab or manipulate a
244 * dev_info_t, e.g. ndi_devi_enter().
245 *
246 * 4. Unless the ksensor is actively being held, whenever a ksensor is found,
247 * one must check whether the ksensor_dip_t flag KSENSOR_DIP_F_REMOVED is
248 * set or not and whether the ksensor_t's KSENSOR_F_VALID flag is set.
249 */
250
251 #include <sys/types.h>
252 #include <sys/file.h>
253 #include <sys/errno.h>
254 #include <sys/cred.h>
255 #include <sys/ddi.h>
256 #include <sys/stat.h>
257 #include <sys/sunddi.h>
258 #include <sys/sunndi.h>
259 #include <sys/esunddi.h>
260 #include <sys/ksensor_impl.h>
261 #include <sys/ddi_impldefs.h>
262 #include <sys/pci.h>
263 #include <sys/avl.h>
264 #include <sys/list.h>
265 #include <sys/stddef.h>
266 #include <sys/sysmacros.h>
267 #include <sys/fs/dv_node.h>
268
269 typedef enum {
270 /*
271 * This flag indicates that the subscribing ksensor character device has
272 * been notified about this flag.
273 */
274 KSENSOR_F_NOTIFIED = 1 << 0,
275 /*
276 * This indicates that the sensor is currently valid, meaning that the
277 * ops vector and argument are safe to use. This is removed when a
278 * driver with a sensor is detached.
279 */
280 KSENSOR_F_VALID = 1 << 1,
281 /*
282 * Indicates that a client has a hold on the sensor for some purpose.
283 * This must be set before trying to get an NDI hold. Once this is set
284 * and a NDI hold is in place, it is safe to use the operations vector
285 * and argument.
286 */
287 KSENSOR_F_BUSY = 1 << 2,
288 } ksensor_flags_t;
289
290 typedef enum {
291 KSENSOR_DIP_F_REMOVED = 1 << 0
292 } ksensor_dip_flags_t;
293
294 typedef struct {
295 list_node_t ksdip_link;
296 ksensor_dip_flags_t ksdip_flags;
297 dev_info_t *ksdip_dip;
298 ddi_unbind_callback_t ksdip_cb;
299 list_t ksdip_sensors;
300 } ksensor_dip_t;
301
302 typedef struct {
303 kmutex_t ksensor_mutex;
304 kcondvar_t ksensor_cv;
305 ksensor_flags_t ksensor_flags;
306 list_node_t ksensor_dip_list;
307 avl_node_t ksensor_id_avl;
308 uint_t ksensor_nwaiters;
309 ksensor_dip_t *ksensor_ksdip;
310 char *ksensor_name;
311 char *ksensor_class;
312 id_t ksensor_id;
313 const ksensor_ops_t *ksensor_ops;
314 void *ksensor_arg;
315 } ksensor_t;
316
317 static kmutex_t ksensor_g_mutex;
318 static id_space_t *ksensor_ids;
319 static list_t ksensor_dips;
320 static avl_tree_t ksensor_avl;
321 static dev_info_t *ksensor_cb_dip;
322 static ksensor_create_f ksensor_cb_create;
323 static ksensor_remove_f ksensor_cb_remove;
324
325 static int
ksensor_avl_compare(const void * l,const void * r)326 ksensor_avl_compare(const void *l, const void *r)
327 {
328 const ksensor_t *kl = l;
329 const ksensor_t *kr = r;
330
331 if (kl->ksensor_id > kr->ksensor_id) {
332 return (1);
333 } else if (kl->ksensor_id < kr->ksensor_id) {
334 return (-1);
335 } else {
336 return (0);
337 }
338 }
339
340 static ksensor_t *
ksensor_find_by_id(id_t id)341 ksensor_find_by_id(id_t id)
342 {
343 ksensor_t k, *ret;
344
345 ASSERT(MUTEX_HELD(&ksensor_g_mutex));
346
347 k.ksensor_id = id;
348 return (avl_find(&ksensor_avl, &k, NULL));
349
350 }
351
352 static ksensor_t *
ksensor_search_ksdip(ksensor_dip_t * ksdip,const char * name,const char * class)353 ksensor_search_ksdip(ksensor_dip_t *ksdip, const char *name, const char *class)
354 {
355 ksensor_t *s;
356
357 ASSERT(MUTEX_HELD(&ksensor_g_mutex));
358
359 for (s = list_head(&ksdip->ksdip_sensors); s != NULL;
360 s = list_next(&ksdip->ksdip_sensors, s)) {
361 if (strcmp(s->ksensor_name, name) == 0 &&
362 strcmp(s->ksensor_class, class) == 0) {
363 return (s);
364 }
365 }
366
367 return (NULL);
368 }
369
370 static void
ksensor_free_sensor(ksensor_t * sensor)371 ksensor_free_sensor(ksensor_t *sensor)
372 {
373 strfree(sensor->ksensor_name);
374 strfree(sensor->ksensor_class);
375 id_free(ksensor_ids, sensor->ksensor_id);
376 mutex_destroy(&sensor->ksensor_mutex);
377 kmem_free(sensor, sizeof (ksensor_t));
378 }
379
380 static void
ksensor_free_dip(ksensor_dip_t * ksdip)381 ksensor_free_dip(ksensor_dip_t *ksdip)
382 {
383 list_destroy(&ksdip->ksdip_sensors);
384 kmem_free(ksdip, sizeof (ksensor_dip_t));
385 }
386
387 static void
ksensor_dip_unbind_taskq(void * arg)388 ksensor_dip_unbind_taskq(void *arg)
389 {
390 ksensor_dip_t *k = arg;
391 ksensor_t *sensor;
392
393 /*
394 * First notify an attached driver that the nodes are going away
395 * before we block and wait on them.
396 */
397 mutex_enter(&ksensor_g_mutex);
398 for (sensor = list_head(&k->ksdip_sensors); sensor != NULL;
399 sensor = list_next(&k->ksdip_sensors, sensor)) {
400 mutex_enter(&sensor->ksensor_mutex);
401 if (sensor->ksensor_flags & KSENSOR_F_NOTIFIED) {
402 ksensor_cb_remove(sensor->ksensor_id,
403 sensor->ksensor_name);
404 sensor->ksensor_flags &= ~KSENSOR_F_NOTIFIED;
405 }
406 mutex_exit(&sensor->ksensor_mutex);
407 }
408 mutex_exit(&ksensor_g_mutex);
409
410 /*
411 * Now that the driver has destroyed its minor, wait for anything that's
412 * still there.
413 */
414 while ((sensor = list_remove_head(&k->ksdip_sensors)) != NULL) {
415 mutex_enter(&sensor->ksensor_mutex);
416 while ((sensor->ksensor_flags & KSENSOR_F_BUSY) != 0 ||
417 sensor->ksensor_nwaiters > 0) {
418 cv_wait(&sensor->ksensor_cv, &sensor->ksensor_mutex);
419 }
420 mutex_exit(&sensor->ksensor_mutex);
421 ksensor_free_sensor(sensor);
422 }
423 ksensor_free_dip(k);
424 }
425
426 static void
ksensor_dip_unbind_cb(void * arg,dev_info_t * dip)427 ksensor_dip_unbind_cb(void *arg, dev_info_t *dip)
428 {
429 ksensor_dip_t *k = arg;
430 ksensor_t *sensor;
431
432 /*
433 * Remove the dip and the associated sensors from global visibility.
434 * This will ensure that no new clients can find this; however, others
435 * may have extent attempts to grab it (but lost the race in an NDI
436 * hold).
437 */
438 mutex_enter(&ksensor_g_mutex);
439 list_remove(&ksensor_dips, k);
440 k->ksdip_flags |= KSENSOR_DIP_F_REMOVED;
441 for (sensor = list_head(&k->ksdip_sensors); sensor != NULL;
442 sensor = list_next(&k->ksdip_sensors, sensor)) {
443 avl_remove(&ksensor_avl, sensor);
444 }
445 mutex_exit(&ksensor_g_mutex);
446
447 (void) taskq_dispatch(system_taskq, ksensor_dip_unbind_taskq, k,
448 TQ_SLEEP);
449 }
450
451 static ksensor_dip_t *
ksensor_dip_create(dev_info_t * dip)452 ksensor_dip_create(dev_info_t *dip)
453 {
454 ksensor_dip_t *k;
455
456 k = kmem_zalloc(sizeof (ksensor_dip_t), KM_SLEEP);
457 k->ksdip_dip = dip;
458 k->ksdip_cb.ddiub_cb = ksensor_dip_unbind_cb;
459 k->ksdip_cb.ddiub_arg = k;
460 list_create(&k->ksdip_sensors, sizeof (ksensor_t),
461 offsetof(ksensor_t, ksensor_dip_list));
462 e_ddi_register_unbind_callback(dip, &k->ksdip_cb);
463
464 return (k);
465 }
466
467 static ksensor_dip_t *
ksensor_dip_find(dev_info_t * dip)468 ksensor_dip_find(dev_info_t *dip)
469 {
470 ksensor_dip_t *k;
471
472 ASSERT(MUTEX_HELD(&ksensor_g_mutex));
473 for (k = list_head(&ksensor_dips); k != NULL;
474 k = list_next(&ksensor_dips, k)) {
475 if (dip == k->ksdip_dip) {
476 return (k);
477 }
478 }
479
480 return (NULL);
481 }
482
483 int
ksensor_create(dev_info_t * dip,const ksensor_ops_t * ops,void * arg,const char * name,const char * class,id_t * idp)484 ksensor_create(dev_info_t *dip, const ksensor_ops_t *ops, void *arg,
485 const char *name, const char *class, id_t *idp)
486 {
487 ksensor_dip_t *ksdip;
488 ksensor_t *sensor;
489
490 if (dip == NULL || ops == NULL || name == NULL || class == NULL ||
491 idp == NULL) {
492 return (EINVAL);
493 }
494
495 if (!DEVI_IS_ATTACHING(dip)) {
496 return (EAGAIN);
497 }
498
499 mutex_enter(&ksensor_g_mutex);
500 ksdip = ksensor_dip_find(dip);
501 if (ksdip == NULL) {
502 ksdip = ksensor_dip_create(dip);
503 list_insert_tail(&ksensor_dips, ksdip);
504 }
505
506 sensor = ksensor_search_ksdip(ksdip, name, class);
507 if (sensor != NULL) {
508 ASSERT3P(sensor->ksensor_ksdip, ==, ksdip);
509 if ((sensor->ksensor_flags & KSENSOR_F_VALID) != 0) {
510 mutex_exit(&ksensor_g_mutex);
511 dev_err(dip, CE_WARN, "tried to create sensor %s:%s "
512 "which is currently active", class, name);
513 return (EEXIST);
514 }
515
516 sensor->ksensor_ops = ops;
517 sensor->ksensor_arg = arg;
518 } else {
519 sensor = kmem_zalloc(sizeof (ksensor_t), KM_SLEEP);
520 sensor->ksensor_ksdip = ksdip;
521 sensor->ksensor_name = ddi_strdup(name, KM_SLEEP);
522 sensor->ksensor_class = ddi_strdup(class, KM_SLEEP);
523 sensor->ksensor_id = id_alloc(ksensor_ids);
524 sensor->ksensor_ops = ops;
525 sensor->ksensor_arg = arg;
526 list_insert_tail(&ksdip->ksdip_sensors, sensor);
527 avl_add(&ksensor_avl, sensor);
528 }
529
530 sensor->ksensor_flags |= KSENSOR_F_VALID;
531
532 if (ksensor_cb_create != NULL) {
533
534 if (ksensor_cb_create(sensor->ksensor_id, sensor->ksensor_class,
535 sensor->ksensor_name) == 0) {
536 sensor->ksensor_flags |= KSENSOR_F_NOTIFIED;
537 }
538 }
539
540 *idp = sensor->ksensor_id;
541 mutex_exit(&ksensor_g_mutex);
542
543 return (0);
544 }
545
546 int
ksensor_create_scalar_pcidev(dev_info_t * dip,uint64_t kind,const ksensor_ops_t * ops,void * arg,const char * name,id_t * idp)547 ksensor_create_scalar_pcidev(dev_info_t *dip, uint64_t kind,
548 const ksensor_ops_t *ops, void *arg, const char *name, id_t *idp)
549 {
550 char *pci_name, *type;
551 const char *class;
552 int *regs, ret;
553 uint_t nregs;
554 uint16_t bus, dev;
555
556 switch (kind) {
557 case SENSOR_KIND_TEMPERATURE:
558 class = "ddi_sensor:temperature:pci";
559 break;
560 case SENSOR_KIND_VOLTAGE:
561 class = "ddi_sensor:voltage:pci";
562 break;
563 case SENSOR_KIND_CURRENT:
564 class = "ddi_sensor:current:pci";
565 break;
566 default:
567 return (ENOTSUP);
568 }
569
570 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, "device_type",
571 &type) != DDI_PROP_SUCCESS) {
572 return (EINVAL);
573 }
574
575 if (strcmp(type, "pciex") != 0 && strcmp(type, "pci") != 0) {
576 ddi_prop_free(type);
577 return (EINVAL);
578 }
579 ddi_prop_free(type);
580
581 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 0, "reg",
582 ®s, &nregs) != DDI_PROP_SUCCESS) {
583 return (EINVAL);
584 }
585
586 if (nregs < 1) {
587 ddi_prop_free(regs);
588 return (EIO);
589 }
590
591 bus = PCI_REG_BUS_G(regs[0]);
592 dev = PCI_REG_DEV_G(regs[0]);
593 ddi_prop_free(regs);
594
595 pci_name = kmem_asprintf("%x.%x:%s", bus, dev, name);
596
597 ret = ksensor_create(dip, ops, arg, pci_name, class, idp);
598 strfree(pci_name);
599 return (ret);
600 }
601
602 /*
603 * When a driver removes a sensor, we basically mark it as invalid. This happens
604 * because drivers can detach and we will need to reattach them when the sensor
605 * is used again.
606 */
607 int
ksensor_remove(dev_info_t * dip,id_t id)608 ksensor_remove(dev_info_t *dip, id_t id)
609 {
610 ksensor_dip_t *kdip;
611 ksensor_t *sensor;
612
613 if (!DEVI_IS_ATTACHING(dip) && !DEVI_IS_DETACHING(dip)) {
614 return (EAGAIN);
615 }
616
617 mutex_enter(&ksensor_g_mutex);
618 kdip = ksensor_dip_find(dip);
619 if (kdip == NULL) {
620 mutex_exit(&ksensor_g_mutex);
621 return (ENOENT);
622 }
623
624 for (sensor = list_head(&kdip->ksdip_sensors); sensor != NULL;
625 sensor = list_next(&kdip->ksdip_sensors, sensor)) {
626 if (sensor->ksensor_id == id || id == KSENSOR_ALL_IDS) {
627 mutex_enter(&sensor->ksensor_mutex);
628 sensor->ksensor_flags &= ~KSENSOR_F_VALID;
629 sensor->ksensor_ops = NULL;
630 sensor->ksensor_arg = NULL;
631 mutex_exit(&sensor->ksensor_mutex);
632 }
633 }
634 mutex_exit(&ksensor_g_mutex);
635 return (0);
636 }
637
638 static void
ksensor_release(ksensor_t * sensor)639 ksensor_release(ksensor_t *sensor)
640 {
641 dev_info_t *pdip;
642
643 ddi_release_devi(sensor->ksensor_ksdip->ksdip_dip);
644
645 mutex_enter(&sensor->ksensor_mutex);
646 sensor->ksensor_flags &= ~KSENSOR_F_BUSY;
647 cv_broadcast(&sensor->ksensor_cv);
648 mutex_exit(&sensor->ksensor_mutex);
649 }
650
651 static int
ksensor_hold_by_id(id_t id,ksensor_t ** outp)652 ksensor_hold_by_id(id_t id, ksensor_t **outp)
653 {
654 ksensor_t *sensor;
655 dev_info_t *pdip;
656
657 restart:
658 mutex_enter(&ksensor_g_mutex);
659 sensor = ksensor_find_by_id(id);
660 if (sensor == NULL) {
661 mutex_exit(&ksensor_g_mutex);
662 *outp = NULL;
663 return (ESTALE);
664 }
665
666 if ((sensor->ksensor_ksdip->ksdip_flags & KSENSOR_DIP_F_REMOVED) != 0) {
667 mutex_exit(&ksensor_g_mutex);
668 *outp = NULL;
669 return (ESTALE);
670 }
671
672 mutex_enter(&sensor->ksensor_mutex);
673 if ((sensor->ksensor_flags & KSENSOR_F_BUSY) != 0) {
674 mutex_exit(&ksensor_g_mutex);
675 sensor->ksensor_nwaiters++;
676 while ((sensor->ksensor_flags & KSENSOR_F_BUSY) != 0) {
677 int cv = cv_wait_sig(&sensor->ksensor_cv,
678 &sensor->ksensor_mutex);
679 if (cv == 0) {
680 sensor->ksensor_nwaiters--;
681 cv_broadcast(&sensor->ksensor_cv);
682 mutex_exit(&sensor->ksensor_mutex);
683 *outp = NULL;
684 return (EINTR);
685 }
686 }
687 sensor->ksensor_nwaiters--;
688 cv_broadcast(&sensor->ksensor_cv);
689 mutex_exit(&sensor->ksensor_mutex);
690 goto restart;
691 }
692
693 /*
694 * We have obtained ownership of the sensor. At this point, we should
695 * check to see if it's valid or not.
696 */
697 sensor->ksensor_flags |= KSENSOR_F_BUSY;
698 pdip = ddi_get_parent(sensor->ksensor_ksdip->ksdip_dip);
699 mutex_exit(&sensor->ksensor_mutex);
700 mutex_exit(&ksensor_g_mutex);
701
702 /*
703 * Grab a reference on the device node to ensure that it won't go away.
704 */
705 ndi_devi_enter(pdip);
706 e_ddi_hold_devi(sensor->ksensor_ksdip->ksdip_dip);
707 ndi_devi_exit(pdip);
708
709 /*
710 * Now that we have an NDI hold, check if it's valid or not. It may have
711 * become invalid while we were waiting due to a race.
712 */
713 mutex_enter(&ksensor_g_mutex);
714 if ((sensor->ksensor_ksdip->ksdip_flags & KSENSOR_DIP_F_REMOVED) != 0) {
715 mutex_exit(&ksensor_g_mutex);
716 ksensor_release(sensor);
717 return (ESTALE);
718 }
719
720 mutex_enter(&sensor->ksensor_mutex);
721 if ((sensor->ksensor_flags & KSENSOR_F_VALID) == 0) {
722 mutex_exit(&sensor->ksensor_mutex);
723 mutex_exit(&ksensor_g_mutex);
724 (void) ndi_devi_config(pdip, NDI_NO_EVENT);
725 mutex_enter(&ksensor_g_mutex);
726 mutex_enter(&sensor->ksensor_mutex);
727
728 /*
729 * If we attempted to reattach it and it isn't now valid, fail
730 * this request.
731 */
732 if ((sensor->ksensor_ksdip->ksdip_flags &
733 KSENSOR_DIP_F_REMOVED) != 0 ||
734 (sensor->ksensor_flags & KSENSOR_F_VALID) == 0) {
735 mutex_exit(&sensor->ksensor_mutex);
736 mutex_exit(&ksensor_g_mutex);
737 ksensor_release(sensor);
738 return (ESTALE);
739 }
740 }
741 mutex_exit(&sensor->ksensor_mutex);
742 mutex_exit(&ksensor_g_mutex);
743 *outp = sensor;
744
745 return (0);
746 }
747
748 int
ksensor_op_kind(id_t id,sensor_ioctl_kind_t * kind)749 ksensor_op_kind(id_t id, sensor_ioctl_kind_t *kind)
750 {
751 int ret;
752 ksensor_t *sensor;
753
754 if ((ret = ksensor_hold_by_id(id, &sensor)) != 0) {
755 return (ret);
756 }
757
758 ret = sensor->ksensor_ops->kso_kind(sensor->ksensor_arg, kind);
759 ksensor_release(sensor);
760
761 return (ret);
762 }
763
764 int
ksensor_op_scalar(id_t id,sensor_ioctl_scalar_t * scalar)765 ksensor_op_scalar(id_t id, sensor_ioctl_scalar_t *scalar)
766 {
767 int ret;
768 ksensor_t *sensor;
769
770 if ((ret = ksensor_hold_by_id(id, &sensor)) != 0) {
771 return (ret);
772 }
773
774 ret = sensor->ksensor_ops->kso_scalar(sensor->ksensor_arg, scalar);
775 ksensor_release(sensor);
776
777 return (ret);
778 }
779
780 void
ksensor_unregister(dev_info_t * reg_dip)781 ksensor_unregister(dev_info_t *reg_dip)
782 {
783 ksensor_t *sensor;
784
785 mutex_enter(&ksensor_g_mutex);
786 if (ksensor_cb_dip != reg_dip) {
787 dev_err(reg_dip, CE_PANIC, "asked to unregister illegal dip");
788 }
789
790 for (sensor = avl_first(&ksensor_avl); sensor != NULL; sensor =
791 AVL_NEXT(&ksensor_avl, sensor)) {
792 mutex_enter(&sensor->ksensor_mutex);
793 sensor->ksensor_flags &= ~KSENSOR_F_NOTIFIED;
794 mutex_exit(&sensor->ksensor_mutex);
795 }
796
797 ksensor_cb_dip = NULL;
798 ksensor_cb_create = NULL;
799 ksensor_cb_remove = NULL;
800 mutex_exit(&ksensor_g_mutex);
801 }
802
803 int
ksensor_register(dev_info_t * reg_dip,ksensor_create_f create,ksensor_remove_f remove)804 ksensor_register(dev_info_t *reg_dip, ksensor_create_f create,
805 ksensor_remove_f remove)
806 {
807 ksensor_t *sensor;
808
809 mutex_enter(&ksensor_g_mutex);
810 if (ksensor_cb_dip != NULL) {
811 dev_err(reg_dip, CE_WARN, "kernel sensors are already "
812 "registered");
813 mutex_exit(&ksensor_g_mutex);
814 return (EEXIST);
815 }
816
817 ksensor_cb_dip = reg_dip;
818 ksensor_cb_create = create;
819 ksensor_cb_remove = remove;
820
821 for (sensor = avl_first(&ksensor_avl); sensor != NULL; sensor =
822 AVL_NEXT(&ksensor_avl, sensor)) {
823 mutex_enter(&sensor->ksensor_mutex);
824 ASSERT0(sensor->ksensor_flags & KSENSOR_F_NOTIFIED);
825
826 if (ksensor_cb_create(sensor->ksensor_id, sensor->ksensor_class,
827 sensor->ksensor_name) == 0) {
828 sensor->ksensor_flags |= KSENSOR_F_NOTIFIED;
829 }
830
831 mutex_exit(&sensor->ksensor_mutex);
832 }
833
834 mutex_exit(&ksensor_g_mutex);
835
836 return (0);
837 }
838
839 int
ksensor_kind_temperature(void * unused,sensor_ioctl_kind_t * k)840 ksensor_kind_temperature(void *unused, sensor_ioctl_kind_t *k)
841 {
842 k->sik_kind = SENSOR_KIND_TEMPERATURE;
843 return (0);
844 }
845
846 int
ksensor_kind_current(void * unused,sensor_ioctl_kind_t * k)847 ksensor_kind_current(void *unused, sensor_ioctl_kind_t *k)
848 {
849 k->sik_kind = SENSOR_KIND_CURRENT;
850 return (0);
851 }
852
853 int
ksensor_kind_voltage(void * unused,sensor_ioctl_kind_t * k)854 ksensor_kind_voltage(void *unused, sensor_ioctl_kind_t *k)
855 {
856 k->sik_kind = SENSOR_KIND_VOLTAGE;
857 return (0);
858 }
859
860 void
ksensor_init(void)861 ksensor_init(void)
862 {
863 mutex_init(&ksensor_g_mutex, NULL, MUTEX_DRIVER, NULL);
864 list_create(&ksensor_dips, sizeof (ksensor_dip_t),
865 offsetof(ksensor_dip_t, ksdip_link));
866 ksensor_ids = id_space_create("ksensor", 1, L_MAXMIN32);
867 avl_create(&ksensor_avl, ksensor_avl_compare, sizeof (ksensor_t),
868 offsetof(ksensor_t, ksensor_id_avl));
869 }
870