Hi!
On a machine the system temperature sensor shows e.g. 33 which is ok.
But on sysctl hw.sensors the status is CRITICAL.
I've read the IPMI specs and i think this is because ipmi_test_threshold ignores
the fact, that some sensors have a signed value and threshold.
In my case the lower thresholds are all negative.
The following diff for sys/dev/ipmi.c should fix this problem. It checks the SDR
if the sensor returns signed values and passes the result to
ipmi_test_threshold() which then does the threshold check regarding the sign.
-- Matthias
--- ipmi.c 10 Apr 2013 01:35:55 -0000 1.68
+++ ipmi.c 19 Jun 2013 09:27:51 -0000
@@ -186,7 +186,7 @@ void ipmi_unmap_regs(struct ipmi_softc *
void *scan_sig(long, long, int, int, const void *);
-int ipmi_test_threshold(u_int8_t, u_int8_t, u_int8_t, u_int8_t);
+int ipmi_test_threshold(u_int8_t, u_int8_t, u_int8_t, u_int8_t, int);
int ipmi_sensor_status(struct ipmi_softc *, struct ipmi_sensor *,
u_int8_t *);
@@ -1287,9 +1287,14 @@ ipmi_convert(u_int8_t v, struct sdrtype1
}
int
-ipmi_test_threshold(u_int8_t v, u_int8_t valid, u_int8_t hi, u_int8_t lo)
+ipmi_test_threshold(u_int8_t v, u_int8_t valid, u_int8_t hi, u_int8_t lo,
+ int sign)
{
- dbg_printf(10, "thresh: %.2x %.2x %.2x %d\n", v, lo, hi,valid);
+ dbg_printf(10, "thresh: %.2x %.2x %.2x %d %d\n", v, lo, hi,valid, sign);
+ if (sign)
+ return ((valid & 1 && lo != 0x00 && (int8_t)v <= (int8_t)lo) ||
+ (valid & 8 && hi != 0xFF && (int8_t)v >= (int8_t)hi));
+
return ((valid & 1 && lo != 0x00 && v <= lo) ||
(valid & 8 && hi != 0xFF && v >= hi));
}
@@ -1301,6 +1306,7 @@ ipmi_sensor_status(struct ipmi_softc *sc
u_int8_t data[32];
struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
int rxlen, etype;
+ int sign = s1->units1 >> 7 & 1;
/* Get reading of sensor */
switch (psensor->i_sensor.type) {
@@ -1339,15 +1345,15 @@ ipmi_sensor_status(struct ipmi_softc *sc
data[6]);
if (ipmi_test_threshold(*reading, data[0] >> 2 ,
- data[6], data[3]))
+ data[6], data[3], sign))
return (SENSOR_S_CRIT);
if (ipmi_test_threshold(*reading, data[0] >> 1,
- data[5], data[2]))
+ data[5], data[2], sign))
return (SENSOR_S_CRIT);
if (ipmi_test_threshold(*reading, data[0] ,
- data[4], data[1]))
+ data[4], data[1], sign))
return (SENSOR_S_WARN);
break;