Module Name: src Committed By: pgoyette Date: Mon Jun 29 12:30:09 UTC 2009
Modified Files: src/sys/arch/x86/x86: ipmi.c Log Message: Adapt to new features available in sysmon_envsys: 1) expose the built-in limits to user-land (via envstat(8)), and 2) allow user-specified limits to override the built-in limits. No comments received from current-users@ over 2-week period. To generate a diff of this commit: cvs rdiff -u -r1.35 -r1.36 src/sys/arch/x86/x86/ipmi.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/x86/ipmi.c diff -u src/sys/arch/x86/x86/ipmi.c:1.35 src/sys/arch/x86/x86/ipmi.c:1.36 --- src/sys/arch/x86/x86/ipmi.c:1.35 Mon Jun 1 20:36:43 2009 +++ src/sys/arch/x86/x86/ipmi.c Mon Jun 29 12:30:09 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: ipmi.c,v 1.35 2009/06/01 20:36:43 pgoyette Exp $ */ +/* $NetBSD: ipmi.c,v 1.36 2009/06/29 12:30:09 pgoyette Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.35 2009/06/01 20:36:43 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.36 2009/06/29 12:30:09 pgoyette Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -89,6 +89,7 @@ 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 *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 @@ 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 @@ 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: @@ -1770,23 +1823,33 @@ } sc->sc_envsys = sysmon_envsys_create(); + sc->sc_envsys->sme_cookie = sc; + sc->sc_envsys->sme_get_limits = ipmi_get_limits; SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) { 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; }