I have some Dells that report various things in ipmi sensors that aren't
currently handled by ipmi(4) feeding to sysctl hw.sensors. It actually
has 100+ in all (visible in ipmitool); most are on/off indicators for
things including power good at various points, presence of various
cables, something to do with RAID battery, etc.
Seems like it would be overkill to add most of them to hw.sensors, but
I find the power consumption quite useful/interesting (and sane to add,
as it matches what is often available on laptops).
Currently ipmi(4) only uses the reported _sensor type_ to identify
a sensor; in the case of these, there is only "current" which covers
both power and current, so the diff below uses the _unit type_ instead.
$ sysctl hw.sensors
hw.sensors.cpu0.temp0=44.00 degC
hw.sensors.mfi0.drive0=online (sd0), OK
hw.sensors.ipmi0.temp0=24.00 degC (Inlet Temp), OK
hw.sensors.ipmi0.temp1=47.00 degC (Temp), OK
hw.sensors.ipmi0.fan0=5520 RPM (Fan1A), OK
hw.sensors.ipmi0.fan1=5400 RPM (Fan1B), OK
hw.sensors.ipmi0.fan2=5520 RPM (Fan2A), OK
hw.sensors.ipmi0.fan3=5280 RPM (Fan2B), OK
hw.sensors.ipmi0.fan4=5520 RPM (Fan3A), OK
hw.sensors.ipmi0.fan5=5160 RPM (Fan3B), OK
hw.sensors.ipmi0.fan6=5280 RPM (Fan4A), OK
hw.sensors.ipmi0.fan7=5280 RPM (Fan4B), OK
hw.sensors.ipmi0.fan8=5640 RPM (Fan5A), OK
hw.sensors.ipmi0.fan9=5160 RPM (Fan5B), OK
hw.sensors.ipmi0.volt0=230.00 VDC (Voltage 1), OK
hw.sensors.ipmi0.volt1=240.00 VDC (Voltage 2), OK
hw.sensors.ipmi0.power0=98.00 W (Pwr Consumption), OK
hw.sensors.ipmi0.current0=0.20 A (Current 1), OK
hw.sensors.ipmi0.current1=0.20 A (Current 2), OK
hw.sensors.ipmi0.indicator0=Off (Intrusion), OK
hw.sensors.ipmi0.indicator1=On (Status), OK
hw.sensors.ipmi0.indicator2=On (Status), OK
Also note the voltages above are reported in VDC; that is unchanged
by this diff - ipmi only has "volts" but the sensors framework
has separate vdc/vac so unless we add a new type (which IIRC has
ABI effects) we have to just pick one.
Any comments?
Index: ipmi.c
===================================================================
RCS file: /cvs/src/sys/dev/ipmi.c,v
retrieving revision 1.115
diff -u -p -r1.115 ipmi.c
--- ipmi.c 23 Jan 2021 12:10:08 -0000 1.115
+++ ipmi.c 11 Feb 2022 18:12:22 -0000
@@ -67,12 +67,23 @@ int ipmi_enabled = 0;
#define IPMI_BTMSG_DATASND 4
#define IPMI_BTMSG_DATARCV 5
+/* IPMI 2.0, Table 42-3: Sensor Type Codes */
#define IPMI_SENSOR_TYPE_TEMP 0x0101
#define IPMI_SENSOR_TYPE_VOLT 0x0102
+#define IPMI_SENSOR_TYPE_CURRENT 0x0103
#define IPMI_SENSOR_TYPE_FAN 0x0104
#define IPMI_SENSOR_TYPE_INTRUSION 0x6F05
#define IPMI_SENSOR_TYPE_PWRSUPPLY 0x6F08
+/* IPMI 2.0, Table 43-15: Sensor Unit Type Codes */
+#define IPMI_UNIT_TYPE_DEGREE_C 1
+#define IPMI_UNIT_TYPE_DEGREE_F 2
+#define IPMI_UNIT_TYPE_DEGREE_K 3
+#define IPMI_UNIT_TYPE_VOLTS 4
+#define IPMI_UNIT_TYPE_AMPS 5
+#define IPMI_UNIT_TYPE_WATTS 6
+#define IPMI_UNIT_TYPE_RPM 18
+
#define IPMI_NAME_UNICODE 0x00
#define IPMI_NAME_BCDPLUS 0x01
#define IPMI_NAME_ASCII6BIT 0x02
@@ -147,7 +158,7 @@ void bt_buildmsg(struct ipmi_cmd *);
void cmn_buildmsg(struct ipmi_cmd *);
int getbits(u_int8_t *, int, int);
-int ipmi_sensor_type(int, int, int);
+int ipmi_sensor_type(int, int, int, int);
void ipmi_refresh_sensors(struct ipmi_softc *sc);
int ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia);
@@ -1217,6 +1228,18 @@ ipmi_sensor_status(struct ipmi_softc *sc
psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6);
break;
+ case SENSOR_VOLTS_AC:
+ psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6);
+ break;
+
+ case SENSOR_AMPS:
+ psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6);
+ break;
+
+ case SENSOR_WATTS:
+ psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6);
+ break;
+
case SENSOR_FANRPM:
psensor->i_sensor.value = ipmi_convert(reading[0], s1, 0);
if (((s1->units1>>3)&0x7) == 0x3)
@@ -1231,6 +1254,7 @@ ipmi_sensor_status(struct ipmi_softc *sc
switch (etype) {
case IPMI_SENSOR_TYPE_TEMP:
case IPMI_SENSOR_TYPE_VOLT:
+ case IPMI_SENSOR_TYPE_CURRENT:
case IPMI_SENSOR_TYPE_FAN:
/* non-recoverable threshold */
if (reading[2] & ((1 << 5) | (1 << 2)))
@@ -1309,17 +1333,26 @@ read_sensor(struct ipmi_softc *sc, struc
}
int
-ipmi_sensor_type(int type, int ext_type, int entity)
+ipmi_sensor_type(int type, int ext_type, int units2, int entity)
{
- switch (ext_type << 8L | type) {
- case IPMI_SENSOR_TYPE_TEMP:
- return (SENSOR_TEMP);
+ switch (units2) {
+ case IPMI_UNIT_TYPE_AMPS:
+ return (SENSOR_AMPS);
- case IPMI_SENSOR_TYPE_VOLT:
+ case IPMI_UNIT_TYPE_RPM:
+ return (SENSOR_FANRPM);
+
+ /* XXX sensors framework distinguishes AC/DC but ipmi does not */
+ case IPMI_UNIT_TYPE_VOLTS:
return (SENSOR_VOLTS_DC);
- case IPMI_SENSOR_TYPE_FAN:
- return (SENSOR_FANRPM);
+ case IPMI_UNIT_TYPE_WATTS:
+ return (SENSOR_WATTS);
+ }
+
+ switch (ext_type << 8L | type) {
+ case IPMI_SENSOR_TYPE_TEMP:
+ return (SENSOR_TEMP);
case IPMI_SENSOR_TYPE_PWRSUPPLY:
if (entity == IPMI_ENTITY_PWRSUPPLY)
@@ -1376,14 +1409,13 @@ add_child_sensors(struct ipmi_softc *sc,
{
int typ, idx;
struct ipmi_sensor *psensor;
-#ifdef IPMI_DEBUG
struct sdrtype1 *s1 = (struct sdrtype1 *)psdr;
-#endif
- typ = ipmi_sensor_type(sensor_type, ext_type, entity);
+ typ = ipmi_sensor_type(sensor_type, ext_type, s1->units2, entity);
if (typ == -1) {
dbg_printf(5, "Unknown sensor type:%.2x et:%.2x sn:%.2x "
- "name:%s\n", sensor_type, ext_type, sensor_num, name);
+ "units2:%u name:%s\n", sensor_type, ext_type, sensor_num,
+ s1->units2, name);
return 0;
}
for (idx = 0; idx < count; idx++) {