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;

Reply via email to