KSENSOR(9E) | Driver Entry Points | KSENSOR(9E) |
ksensor
— kernel
sensor framework
#include
<sys/sensors.h>
Volatile - This interface is still evolving in illumos. API and ABI stability is not guaranteed.
The ksensor, kernel sensor, framework provides a means for drivers to provide various kinds of sensor information to userland such as temperature, voltage, current, and control sensors. Sensors are exposed in /dev/sensors and the framework takes care of managing minor nodes and ioctl interfaces. The driver does not need to expose a character device interface nor are its minor nodes used.
Sensors are broken into different types. The types describe the shape of the value that can be read from the sensor itself. Currently, scalar sensors are the only supported sensor type. A scalar sensor has several properties:
In addition to the type, sensors also have a notion of a kind, which indicates what kind of physical property the sensor measures. The kernel defines the kinds currently:
SENSOR_KIND_TEMPERATURE
SENSOR_KIND_VOLTAGE
SENSOR_KIND_CURRENT
SENSOR_KIND_SYNTHETIC
The smntemp(4D) driver exposes the AMD Tctl sensor, which is a control temperature value. This is not a measurement in degrees C, but rather is a value from 0 to 100 where 100 indicates that a thermal shutdown is imminent. This value is synthesized and transformed from several different temperature samples and goes through its own algorithm, but critically the resulting synthetic Tctl sensor does not represent a temperature, but is used to power cooling control loops.
SENSOR_KIND_UNKNOWN
From here, a given measurement that occurs also has a unit that is associated with it. The following sensors are supported:
SENSOR_UNIT_CELSIUS
SENSOR_UNIT_FAHRENHEIT
SENSOR_UNIT_KELVIN
SENSOR_UNIT_VOLTS
SENSOR_UNIT_AMPS
SENSOR_UNIT_NONE
SENSOR_KIND_SYNTHETIC
sensors.SENSOR_UNIT_UNKNOWN
When a sensor is created with ksensor_create(9F) it must specify both a name and a class, which influence how the sensor shows up under /dev/sensors. The class is a ‘:’ delineated string (the same conceptually as a minor node's type, see ddi_create_minor_node(9F)) that describes the type of sensor. They begin with “ddi_sensor” and then are followed by the sensor's kind and then, after another colon, something that describes what type of hardware it corresponds to. The framework takes care of defining the class for PCI devices that create sensors with ksensor_create_scalar_pcidev(9F) and provides the following classes otherwise:
DDI_NT_SENSOR_TEMP_CPU
DDI_NT_SENSOR_TEMP_PCH
In general, drivers shouldn't create arbitrary classes that aren't defined by the framework as then they won't be tied into system services, like topology provided by the fault management architecture.
Where the class effectively indicates the directory structure under /dev/sensors, the name of the sensor corresponds to the name of the device that will be created. The semantics of the name determine a bit on the interface used. While the PCI sensor creation routines are tied into things such that the name is usually something descriptive, for other sensors that use ksensor_create(9F), usually the name is part of a contract with something in userland that will consume it like FMA.
Sensors are tied to an instance of a driver (i.e. a particular dev_info_t) and are identified through an opaque id_t identifier that is unique in the system.
To create a ksensor, a driver must call either ksensor_create(9F) or ksensor_create_scalar_pcidev(9F) in its attach(9E) entry point. A ksensor cannot be created outside of a driver's attach(9E) entry point. Once created, the sensor will persist until the driver removes the sensors with ksensor_remove(9F) which can only be called during detach(9E) or attach(9E).
As part of creating a ksensor, a driver must supply an operations vector described in ksensor_ops(9E). This provides both metadata and data about the sensor itself. The framework provides the following guarantees and constraints around when the operation vectors will be called:
The ksensor framework is intended for cases where there are registers or schemes that can only be accessed by the kernel itself. A good case of this is where sensors are available through PCI configuration space or a memory-mapped BAR. Other devices like optical transceivers have an array of sensors, but are only accessible through an additional I/O interface like mac_capab_transceiver(9E). In cases where there are a lot of semantics and parsing required, or the kernel cannot wholly own the device, it can make more sense to instead leverage a different interface and allow another part of the system like FMA to amalgamate the different sensors using additional components in userland.
The right call will vary based on the device and interface. The main point here is that while the ksensor framework exists, it doesn't have to be the only way that sensors are provided for consumption. But it is here to be used where it makes sense!
ksensor(4D), attach(9E), detach(9E), ksensor_ops(9E), ddi_create_minor_node(9F), ksensor_create(9F), ksensor_create_scalar_pcidev(9F), ksensor_kind(9F)
May 10, 2024 | OmniOS |