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 2023 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 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 * 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 * 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 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 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 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 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 * 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 * 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 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 547 ksensor_create_scalar_pcidev(dev_info_t *dip, uint_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 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 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 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 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 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 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 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 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 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 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 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