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