Current-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
ipmi(4) sensor driver update
After the recent update to sysmon_envsys(9) I've started reviewing some
of the existing sensor drivers with an eye to providing some enhanced
functionality.
The sys/arch/x86/x86/ipmi.c driver is the next candidate on my review
list, and it appears that the driver has access to some alarm limits
even if they've not been set by userland. Furthermore, it appears that
the current driver uses these "built-in" alarm limits for setting the
sensor state, overriding any limits that might be specified by the user.
The attached file contains an update to the ipmi(4) driver that will
1) expose the built-in limits to user-land (via envstat(8)), and
2) allow user-specified limits to override the built-in limits.
I don't have any ipmi hardware myself, to test these changes, so I'd
appreciate it if someone who has ipmi would verify that these changes
(a) don't break anything and hopefully (b) successfully implement
features 1 & 2 above.
-------------------------------------------------------------------------
| Paul Goyette | PGP DSS Key fingerprint: | E-mail addresses: |
| Customer Service | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette at juniper.net |
| Kernel Developer | | pgoyette at netbsd.org |
-------------------------------------------------------------------------
Index: sys/arch/x86/x86/ipmi.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/ipmi.c,v
retrieving revision 1.35
diff -u -p -r1.35 ipmi.c
--- sys/arch/x86/x86/ipmi.c 1 Jun 2009 20:36:43 -0000 1.35
+++ sys/arch/x86/x86/ipmi.c 14 Jun 2009 19:27:58 -0000
@@ -89,6 +89,7 @@ struct ipmi_sensor {
char i_envdesc[64];
int i_envtype; /* envsys compatible type */
int i_envnum; /* envsys index */
+ sysmon_envsys_lim_t *i_limits;
SLIST_ENTRY(ipmi_sensor) i_list;
};
@@ -214,8 +215,11 @@ void ipmi_unmap_regs(struct ipmi_softc *
void *scan_sig(long, long, int, int, const void *);
-int ipmi_test_threshold_lo(uint8_t, uint8_t, uint8_t);
-int ipmi_test_threshold_hi(uint8_t, uint8_t, uint8_t);
+int32_t ipmi_convert_sensor(uint8_t *, struct ipmi_sensor *);
+void ipmi_get_limits(struct sysmon_envsys *, envsys_data_t *,
+ sysmon_envsys_lim_t *);
+int ipmi_get_sensor_limits(struct ipmi_softc *, struct ipmi_sensor *,
+ sysmon_envsys_lim_t *);
int ipmi_sensor_status(struct ipmi_softc *, struct ipmi_sensor *,
envsys_data_t *, uint8_t *);
@@ -1307,46 +1311,104 @@ ipmi_convert(uint8_t v, struct sdrtype1
return (val);
}
-int
-ipmi_test_threshold_hi(uint8_t v, uint8_t valid, uint8_t hi)
-{
- dbg_printf(10, "thresh_hi: %.2x %.2x %d\n", v, hi, valid);
- return (valid & 8 && hi != 0xFF && v >= hi);
-}
-
-int
-ipmi_test_threshold_lo(uint8_t v, uint8_t valid, uint8_t lo)
-{
- dbg_printf(10, "thresh_lo: %.2x %.2x %d\n", v, lo, valid);
- return (valid & 1 && lo != 0x00 && v <= lo);
-}
-
-int
-ipmi_sensor_status(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
- envsys_data_t *edata, uint8_t *reading)
+int32_t
+ipmi_convert_sensor(uint8_t *reading, struct ipmi_sensor *psensor)
{
- uint8_t data[32];
struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
- int rxlen, etype;
- /* Get reading of sensor */
- switch (edata->units) {
+ int32_t val;
+
+ switch (psensor->i_envtype) {
case ENVSYS_STEMP:
- edata->value_cur = ipmi_convert(reading[0], s1, 6);
- edata->value_cur += 273150000;
+ val = ipmi_convert(reading[0], s1, 6) + 273150000;
break;
case ENVSYS_SVOLTS_DC:
- edata->value_cur = ipmi_convert(reading[0], s1, 6);
+ val = ipmi_convert(reading[0], s1, 6);
break;
case ENVSYS_SFANRPM:
- edata->value_cur = ipmi_convert(reading[0], s1, 0);
+ val = ipmi_convert(reading[0], s1, 0);
if (((s1->units1>>3)&0x7) == 0x3)
- edata->value_cur *= 60; /* RPS -> RPM */
+ val *= 60; /* RPS -> RPM */
break;
default:
+ val = 0;
break;
}
+ return val;
+}
+
+void
+ipmi_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
+ sysmon_envsys_lim_t *limits)
+{
+ struct ipmi_sensor *ipmi_s;
+ struct ipmi_softc *sc = sme->sme_cookie;
+
+ /* Find the ipmi_sensor corresponding to this edata */
+ SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
+ if (ipmi_s->i_envnum == edata->sensor) {
+ (void)ipmi_get_sensor_limits(sc, ipmi_s, limits);
+ ipmi_s->i_limits = limits;
+ return;
+ }
+ }
+ return;
+}
+
+int
+ipmi_get_sensor_limits(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
+ sysmon_envsys_lim_t *limits)
+{
+ struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
+ int rxlen;
+ uint8_t data[32];
+
+ data[0] = psensor->i_num;
+ if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun,
+ SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) ||
+ ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
+ return -1;
+
+ dbg_printf(25, "recvdata: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
+
+ limits->sel_flags = 0;
+ if (data[0] & 0x20) {
+ limits->sel_critmax = ipmi_convert_sensor(&data[6], psensor);
+ limits->sel_flags |= PROP_CRITMAX;
+ }
+ if (data[0] & 0x10) {
+ limits->sel_critmax = ipmi_convert_sensor(&data[5], psensor);
+ limits->sel_flags |= PROP_CRITMAX;
+ }
+ if (data[0] & 0x08) {
+ limits->sel_warnmax = ipmi_convert_sensor(&data[4], psensor);
+ limits->sel_flags |= PROP_WARNMAX;
+ }
+ if (data[0] & 0x04) {
+ limits->sel_critmin = ipmi_convert_sensor(&data[3], psensor);
+ limits->sel_flags |= PROP_CRITMIN;
+ }
+ if (data[0] & 0x02) {
+ limits->sel_critmin = ipmi_convert_sensor(&data[2], psensor);
+ limits->sel_flags |= PROP_CRITMIN;
+ }
+ if (data[0] & 0x01) {
+ limits->sel_warnmin = ipmi_convert_sensor(&data[1], psensor);
+ limits->sel_flags |= PROP_WARNMIN;
+ }
+ return 0;
+}
+
+int
+ipmi_sensor_status(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
+ envsys_data_t *edata, uint8_t *reading)
+{
+ int etype;
+
+ /* Get reading of sensor */
+ edata->value_cur = ipmi_convert_sensor(reading, psensor);
/* Return Sensor Status */
etype = (psensor->i_etype << 8) + psensor->i_stype;
@@ -1354,34 +1416,25 @@ ipmi_sensor_status(struct ipmi_softc *sc
case IPMI_SENSOR_TYPE_TEMP:
case IPMI_SENSOR_TYPE_VOLT:
case IPMI_SENSOR_TYPE_FAN:
- data[0] = psensor->i_num;
- if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun,
- SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) ||
- ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
- return ENVSYS_SVALID;
-
- dbg_printf(25, "recvdata: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
- data[0], data[1], data[2], data[3], data[4], data[5],
- data[6]);
-
- if (ipmi_test_threshold_hi(*reading, data[0] >> 2 , data[6]))
- return ENVSYS_SCRITOVER;
+ if (psensor->i_limits == NULL)
+ break;
- if (ipmi_test_threshold_hi(*reading, data[0] >> 1, data[5]))
+ if (psensor->i_limits->sel_flags & PROP_CRITMAX &&
+ edata->value_cur > psensor->i_limits->sel_critmax)
return ENVSYS_SCRITOVER;
- if (ipmi_test_threshold_hi(*reading, data[0] , data[4]))
+ if (psensor->i_limits->sel_flags & PROP_WARNMAX &&
+ edata->value_cur > psensor->i_limits->sel_warnmax)
return ENVSYS_SWARNOVER;
- if (ipmi_test_threshold_lo(*reading, data[0] >> 2 , data[3]))
- return ENVSYS_SCRITUNDER;
+ if (psensor->i_limits->sel_flags & PROP_WARNMIN &&
+ edata->value_cur > psensor->i_limits->sel_warnmin)
+ return ENVSYS_SWARNUNDER;
- if (ipmi_test_threshold_lo(*reading, data[0] >> 1, data[2]))
+ if (psensor->i_limits->sel_flags & PROP_CRITMIN &&
+ edata->value_cur > psensor->i_limits->sel_critmin)
return ENVSYS_SCRITUNDER;
- if (ipmi_test_threshold_lo(*reading, data[0] , data[1]))
- return ENVSYS_SWARNUNDER;
-
break;
case IPMI_SENSOR_TYPE_INTRUSION:
@@ -1775,18 +1828,26 @@ ipmi_thread(void *cookie)
i = current_index_typ[ipmi_s->i_envtype];
current_index_typ[ipmi_s->i_envtype]++;
ipmi_s->i_envnum = i;
+ ipmi_s->i_limits = NULL;
sc->sc_sensor[i].units = ipmi_s->i_envtype;
sc->sc_sensor[i].state = ENVSYS_SINVALID;
sc->sc_sensor[i].monitor = true;
/*
* Monitor threshold limits in the sensors.
*/
- sc->sc_sensor[i].flags |= ENVSYS_FMONCRITICAL;
- sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS;
+ switch (sc->sc_sensor[i].units) {
+ case ENVSYS_STEMP:
+ case ENVSYS_SVOLTS_DC:
+ case ENVSYS_SFANRPM:
+ sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS;
+ break;
+ default:
+ sc->sc_sensor[i].flags |= ENVSYS_FMONCRITICAL;
+ }
(void)strlcpy(sc->sc_sensor[i].desc, ipmi_s->i_envdesc,
sizeof(sc->sc_sensor[i].desc));
if (sysmon_envsys_sensor_attach(sc->sc_envsys,
- &sc->sc_sensor[i]))
+ &sc->sc_sensor[i]))
continue;
}
Home |
Main Index |
Thread Index |
Old Index