diff options
author | Masao Uebayashi <uebayasi@cvs.openbsd.org> | 2016-01-11 13:12:51 +0000 |
---|---|---|
committer | Masao Uebayashi <uebayasi@cvs.openbsd.org> | 2016-01-11 13:12:51 +0000 |
commit | 33c8d777e3ab58b42aef11ae51c9dee6e072dbed (patch) | |
tree | 674b5e723a3f33f1e755f8f672b2344fdd8a49e7 /sys | |
parent | ad3f810353879c8a8897b8dfcf7014acb2b3b74e (diff) |
Introduce struct ipmi_cmd and have ipmi_cmd() function. IPMI command
sequence is always a pair of send and receive; call both from ipmi_cmd().
By making ipmi_cmd() take only one argument struct ipmi_cmd *, this also
helps to prepare to call ipmi_cmd() as a task.
No functional changes intended.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ipmi.c | 200 | ||||
-rw-r--r-- | sys/dev/ipmivar.h | 19 |
2 files changed, 139 insertions, 80 deletions
diff --git a/sys/dev/ipmi.c b/sys/dev/ipmi.c index a96dacf77a8..3b5abbfa6e0 100644 --- a/sys/dev/ipmi.c +++ b/sys/dev/ipmi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipmi.c,v 1.83 2016/01/11 12:54:33 uebayasi Exp $ */ +/* $OpenBSD: ipmi.c,v 1.84 2016/01/11 13:12:50 uebayasi Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave @@ -149,9 +149,10 @@ int get_sdr_partial(struct ipmi_softc *, u_int16_t, u_int16_t, u_int8_t, u_int8_t, void *, u_int16_t *); int get_sdr(struct ipmi_softc *, u_int16_t, u_int16_t *); -int ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*); -int ipmi_recvcmd(struct ipmi_softc *, int, int *, void *); +int ipmi_sendcmd(struct ipmi_cmd *); +int ipmi_recvcmd(struct ipmi_cmd *); void ipmi_delay(struct ipmi_softc *, int); +void ipmi_cmd(void *); int ipmi_watchdog(void *, int); @@ -934,9 +935,6 @@ ipmi_smbios_probe(struct smbios_ipmi *pipmi, struct ipmi_attach_args *ia) /* * bt_buildmsg builds an IPMI message from a nfLun, cmd, and data * This is used by BT protocol - * - * Returns a buffer to an allocated message, txlen contains length - * of allocated message */ void * bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len, @@ -963,9 +961,6 @@ bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len, /* * cmn_buildmsg builds an IPMI message from a nfLun, cmd, and data * This is used by both SMIC and KCS protocols - * - * Returns a buffer to an allocated message, txlen contains length - * of allocated message */ void * cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len, @@ -989,16 +984,16 @@ cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len, /* Send an IPMI command */ int -ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd, - int txlen, const void *data) +ipmi_sendcmd(struct ipmi_cmd *c) { + struct ipmi_softc *sc = c->c_sc; u_int8_t *buf; int rc = -1; dbg_printf(50, "ipmi_sendcmd: rssa=%.2x nfln=%.2x cmd=%.2x len=%.2x\n", - rssa, NETFN_LUN(netfn, rslun), cmd, txlen); - dbg_dump(10, " send", txlen, data); - if (rssa != BMC_SA) { + c->c_rssa, NETFN_LUN(c->c_netfn, c->c_rslun), c->c_cmd, c->c_txlen); + dbg_dump(10, " send", c->c_txlen, c->c_data); + if (c->c_rssa != BMC_SA) { #if 0 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(APP_NETFN, BMC_LUN), APP_SEND_MESSAGE, 7 + txlen, NULL, &txlen); @@ -1019,15 +1014,15 @@ ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd, #endif goto done; } else - buf = sc->sc_if->buildmsg(sc, NETFN_LUN(netfn, rslun), cmd, - txlen, data, &txlen); + buf = sc->sc_if->buildmsg(sc, NETFN_LUN(c->c_netfn, c->c_rslun), c->c_cmd, + c->c_txlen, c->c_data, &c->c_txlen); if (buf == NULL) { printf("%s: sendcmd malloc fails\n", DEVNAME(sc)); goto done; } - rc = sc->sc_if->sendmsg(sc, txlen, buf); - free(buf, M_DEVBUF, txlen); + rc = sc->sc_if->sendmsg(sc, c->c_txlen, buf); + free(buf, M_DEVBUF, c->c_txlen); ipmi_delay(sc, 5); /* give bmc chance to digest command */ @@ -1035,28 +1030,30 @@ done: return (rc); } +/* Receive an IPMI command */ int -ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data) +ipmi_recvcmd(struct ipmi_cmd *c) { + struct ipmi_softc *sc = c->c_sc; u_int8_t *buf, rc = 0; int rawlen; /* Need three extra bytes: netfn/cmd/ccode + data */ - buf = malloc(maxlen + 3, M_DEVBUF, M_NOWAIT); + buf = malloc(c->c_maxrxlen + 3, M_DEVBUF, M_NOWAIT); if (buf == NULL) { printf("%s: ipmi_recvcmd: malloc fails\n", DEVNAME(sc)); return (-1); } /* Receive message from interface, copy out result data */ - if (sc->sc_if->recvmsg(sc, maxlen + 3, &rawlen, buf) || + if (sc->sc_if->recvmsg(sc, c->c_maxrxlen + 3, &rawlen, buf) || rawlen < IPMI_MSG_DATARCV) { - free(buf, M_DEVBUF, maxlen + 3); + free(buf, M_DEVBUF, c->c_maxrxlen + 3); return (-1); } - *rxlen = rawlen - IPMI_MSG_DATARCV; - if (*rxlen > 0 && data) - memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen); + c->c_rxlen = rawlen - IPMI_MSG_DATARCV; + if (c->c_rxlen > 0 && c->c_data) + memcpy(c->c_data, buf + IPMI_MSG_DATARCV, c->c_rxlen); rc = buf[IPMI_MSG_CCODE]; #ifdef IPMI_DEBUG @@ -1067,10 +1064,10 @@ ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data) dbg_printf(50, "ipmi_recvcmd: nfln=%.2x cmd=%.2x err=%.2x len=%.2x\n", buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE], - *rxlen); - dbg_dump(10, " recv", *rxlen, data); + c->c_rxlen); + dbg_dump(10, " recv", c->c_rxlen, c->c_data); - free(buf, M_DEVBUF, maxlen + 3); + free(buf, M_DEVBUF, c->c_maxrxlen + 3); ipmi_delay(sc, 5); /* give bmc chance to digest command */ @@ -1088,6 +1085,19 @@ ipmi_delay(struct ipmi_softc *sc, int period) continue; } +void +ipmi_cmd(void *arg) +{ + struct ipmi_cmd *c = arg; + + c->c_sc->sc_cmd = c; + if (ipmi_sendcmd(c)) { + panic("%s: sendcmd fails", DEVNAME(c->c_sc)); + } + c->c_ccode = ipmi_recvcmd(c); + c->c_sc->sc_cmd = NULL; +} + /* Read a partial SDR entry */ int get_sdr_partial(struct ipmi_softc *sc, u_int16_t recordId, u_int16_t reserveId, @@ -1100,15 +1110,20 @@ get_sdr_partial(struct ipmi_softc *sc, u_int16_t recordId, u_int16_t reserveId, ((u_int16_t *) cmd)[1] = recordId; cmd[4] = offset; cmd[5] = length; - if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6, - cmd)) { - printf("%s: sendcmd fails\n", DEVNAME(sc)); - return (-1); - } - if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) { - printf("%s: getSdrPartial: recvcmd fails\n", DEVNAME(sc)); - return (-1); - } + + struct ipmi_cmd c; + c.c_sc = sc; + c.c_rssa = BMC_SA; + c.c_rslun = BMC_LUN; + c.c_netfn = STORAGE_NETFN; + c.c_cmd = STORAGE_GET_SDR; + c.c_txlen = 6; + c.c_maxrxlen = 8 + length; + c.c_rxlen = 0; + c.c_data = cmd; + ipmi_cmd(&c); + len = c.c_rxlen; + if (nxtRecordId) *nxtRecordId = *(uint16_t *) cmd; if (len > 2) @@ -1129,15 +1144,18 @@ get_sdr(struct ipmi_softc *sc, u_int16_t recid, u_int16_t *nxtrec) struct sdrhdr shdr; /* Reserve SDR */ - if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR, - 0, NULL)) { - printf("%s: reserve send fails\n", DEVNAME(sc)); - return (1); - } - if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) { - printf("%s: reserve recv fails\n", DEVNAME(sc)); - return (1); - } + struct ipmi_cmd c; + c.c_sc = sc; + c.c_rssa = BMC_SA; + c.c_rslun = BMC_LUN; + c.c_netfn = STORAGE_NETFN; + c.c_cmd = STORAGE_RESERVE_SDR; + c.c_txlen = 0; + c.c_maxrxlen = sizeof(resid); + c.c_rxlen = 0; + c.c_data = &resid; + ipmi_cmd(&c); + /* Get SDR Header */ if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) { printf("%s: get header fails\n", DEVNAME(sc)); @@ -1366,19 +1384,25 @@ read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor) { struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr; u_int8_t data[8]; - int rxlen, rv = -1; + int rv = -1; if (!cold) rw_enter_write(&sc->sc_lock); memset(data, 0, sizeof(data)); data[0] = psensor->i_num; - if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN, - SE_GET_SENSOR_READING, 1, data)) - goto done; - if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data)) - goto done; + struct ipmi_cmd c; + c.c_sc = sc; + c.c_rssa = s1->owner_id; + c.c_rslun = s1->owner_lun; + c.c_netfn = SE_NETFN; + c.c_cmd = SE_GET_SENSOR_READING; + c.c_txlen = 1; + c.c_maxrxlen = sizeof(data); + c.c_rxlen = 0; + c.c_data = data; + ipmi_cmd(&c); dbg_printf(10, "values=%.2x %.2x %.2x %.2x %s\n", data[0],data[1],data[2],data[3], psensor->i_sensor.desc); @@ -1388,7 +1412,6 @@ read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor) psensor->i_sensor.flags |= SENSOR_FINVALID; psensor->i_sensor.status = ipmi_sensor_status(sc, psensor, data); rv = 0; -done: if (!cold) rw_exit_write(&sc->sc_lock); return (rv); @@ -1575,7 +1598,7 @@ void ipmi_poll_thread(void *arg) { struct ipmi_thread *thread = arg; - struct ipmi_softc *sc = thread->sc; + struct ipmi_softc *sc = thread->sc; u_int16_t rec; /* Scan SDRs, add sensors */ @@ -1655,7 +1678,6 @@ ipmi_match(struct device *parent, void *match, void *aux) struct ipmi_attach_args *ia = aux; struct cfdata *cf = match; u_int8_t cmd[32]; - int len; int rv = 0; if (strcmp(ia->iaa_name, cf->cf_driver->cd_name)) @@ -1668,19 +1690,19 @@ ipmi_match(struct device *parent, void *match, void *aux) sc.sc_if->probe(&sc); /* Identify BMC device early to detect lying bios */ - if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID, - 0, NULL)) { - dbg_printf(1, ": unable to send get device id " - "command\n"); - goto unmap; - } - if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) { - dbg_printf(1, ": unable to retrieve device id\n"); - goto unmap; - } - - dbg_dump(1, "bmc data", len, cmd); -unmap: + struct ipmi_cmd c; + c.c_sc = ≻ + c.c_rssa = BMC_SA; + c.c_rslun = BMC_LUN; + c.c_netfn = APP_NETFN; + c.c_cmd = APP_GET_DEVICE_ID; + c.c_txlen = 0; + c.c_maxrxlen = sizeof(cmd); + c.c_rxlen = 0; + c.c_data = cmd; + ipmi_cmd(&c); + + dbg_dump(1, "bmc data", c.c_rxlen, cmd); rv = 1; /* GETID worked, we got IPMI */ ipmi_unmap_regs(&sc); } @@ -1752,15 +1774,25 @@ ipmi_watchdog(void *arg, int period) { struct ipmi_softc *sc = arg; uint8_t wdog[IPMI_GET_WDOG_MAX]; - int s, rc, len; + int s; + struct ipmi_cmd c; if (sc->sc_wdog_period == period) { if (period != 0) { s = splsoftclock(); + /* tickle the watchdog */ - rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, - APP_RESET_WATCHDOG, 0, NULL); - rc = ipmi_recvcmd(sc, 0, &len, NULL); + c.c_sc = sc; + c.c_rssa = BMC_SA; + c.c_rslun = BMC_LUN; + c.c_netfn = APP_NETFN; + c.c_cmd = APP_RESET_WATCHDOG; + c.c_txlen = 0; + c.c_maxrxlen = 0; + c.c_rxlen = 0; + c.c_data = NULL; + ipmi_cmd(&c); + splx(s); } return (period); @@ -1770,10 +1802,17 @@ ipmi_watchdog(void *arg, int period) period = MIN_PERIOD; s = splsoftclock(); - /* XXX what to do if poking wdog fails? */ - rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, - APP_GET_WATCHDOG_TIMER, 0, NULL); - rc = ipmi_recvcmd(sc, IPMI_GET_WDOG_MAX, &len, wdog); + + c.c_sc = sc; + c.c_rssa = BMC_SA; + c.c_rslun = BMC_LUN; + c.c_netfn = APP_NETFN; + c.c_cmd = APP_GET_WATCHDOG_TIMER; + c.c_txlen = 0; + c.c_maxrxlen = IPMI_GET_WDOG_MAX; + c.c_rxlen = 0; + c.c_data = wdog; + ipmi_cmd(&c); /* Period is 10ths/sec */ uint16_t timo = htole16(period * 10); @@ -1785,9 +1824,12 @@ ipmi_watchdog(void *arg, int period) wdog[IPMI_SET_WDOG_ACTION] |= (period == 0) ? IPMI_WDOG_DISABLED : IPMI_WDOG_REBOOT; - rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, - APP_SET_WATCHDOG_TIMER, IPMI_SET_WDOG_MAX, wdog); - rc = ipmi_recvcmd(sc, 0, &len, NULL); + c.c_cmd = APP_SET_WATCHDOG_TIMER; + c.c_txlen = IPMI_SET_WDOG_MAX; + c.c_maxrxlen = 0; + c.c_rxlen = 0; + c.c_data = wdog; + ipmi_cmd(&c); splx(s); diff --git a/sys/dev/ipmivar.h b/sys/dev/ipmivar.h index 486fad5b959..35dd85c18ba 100644 --- a/sys/dev/ipmivar.h +++ b/sys/dev/ipmivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ipmivar.h,v 1.21 2016/01/11 12:54:33 uebayasi Exp $ */ +/* $OpenBSD: ipmivar.h,v 1.22 2016/01/11 13:12:50 uebayasi Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave @@ -77,6 +77,22 @@ struct ipmi_if { int (*probe)(struct ipmi_softc *); }; +struct ipmi_cmd { + struct ipmi_softc *c_sc; + + int c_rssa; + int c_rslun; + int c_netfn; + int c_cmd; + + int c_txlen; + int c_maxrxlen; + int c_rxlen; + + void *c_data; + u_int c_ccode; +}; + struct ipmi_softc { struct device sc_dev; @@ -89,6 +105,7 @@ struct ipmi_softc { bus_space_handle_t sc_ioh; int sc_btseq; + struct ipmi_cmd *sc_cmd; int sc_wdog_period; |