From fd99d2664d7e69529c075988c48ca3cdc4b4c53a Mon Sep 17 00:00:00 2001 From: yasuoka Date: Wed, 7 Jan 2015 07:49:18 +0000 Subject: [PATCH] Fix impi(4) to make watchdog work and not to panic. diff from uebayasi jsg ok uebayasi --- sys/dev/ipmi.c | 27 +++++++++++++++++---------- sys/dev/ipmivar.h | 28 ++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/sys/dev/ipmi.c b/sys/dev/ipmi.c index b53d643ac90..012d081c2de 100644 --- a/sys/dev/ipmi.c +++ b/sys/dev/ipmi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipmi.c,v 1.74 2014/12/10 12:27:57 mikeb Exp $ */ +/* $OpenBSD: ipmi.c,v 1.75 2015/01/07 07:49:18 yasuoka Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave @@ -285,7 +285,7 @@ bmc_io_wait(struct ipmi_softc *sc, int offset, u_int8_t mask, u_int8_t value, volatile u_int8_t v; struct ipmi_bmc_args args; - if (cold) + if (cold || sc->sc_poll) return (bmc_io_wait_cold(sc, offset, mask, value, lbl)); sc->sc_retries = 0; @@ -1049,7 +1049,8 @@ ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data) 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, maxlen + 3, &rawlen, buf) || + rawlen < IPMI_MSG_DATARCV) return (-1); *rxlen = rawlen - IPMI_MSG_DATARCV; @@ -1079,7 +1080,7 @@ void ipmi_delay(struct ipmi_softc *sc, int period) { /* period is in 10 ms increments */ - if (cold) + if (cold || sc->sc_poll) delay(period * 10000); else while (tsleep(sc, PWAIT, "ipmicmd", period) != EWOULDBLOCK) @@ -1778,16 +1779,18 @@ int ipmi_watchdog(void *arg, int period) { struct ipmi_softc *sc = arg; - struct ipmi_watchdog wdog; + uint8_t wdog[IPMI_GET_WDOG_MAX]; int s, rc, len; if (sc->sc_wdog_period == period) { if (period != 0) { s = splsoftclock(); + sc->sc_poll = 1; /* 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); + sc->sc_poll = 0; splx(s); } return (period); @@ -1797,21 +1800,25 @@ ipmi_watchdog(void *arg, int period) period = 10; s = splsoftclock(); + sc->sc_poll = 1; /* 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, sizeof(wdog), &len, &wdog); + rc = ipmi_recvcmd(sc, IPMI_GET_WDOG_MAX, &len, wdog); /* Period is 10ths/sec */ - wdog.wdog_timeout = htole32(period * 10); - wdog.wdog_action &= ~IPMI_WDOG_MASK; - wdog.wdog_action |= (period == 0) ? IPMI_WDOG_DISABLED : + uint16_t timo = htole16(period * 10); + + memcpy(&wdog[IPMI_SET_WDOG_TIMOL], &timo, 2); + wdog[IPMI_SET_WDOG_ACTION] &= ~IPMI_WDOG_MASK; + 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, sizeof(wdog), &wdog); + APP_SET_WATCHDOG_TIMER, IPMI_SET_WDOG_MAX, wdog); rc = ipmi_recvcmd(sc, 0, &len, NULL); + sc->sc_poll = 0; splx(s); sc->sc_wdog_period = period; diff --git a/sys/dev/ipmivar.h b/sys/dev/ipmivar.h index 636d49cbd57..53a9bfc1ad8 100644 --- a/sys/dev/ipmivar.h +++ b/sys/dev/ipmivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ipmivar.h,v 1.18 2007/03/22 16:55:31 deraadt Exp $ */ +/* $OpenBSD: ipmivar.h,v 1.19 2015/01/07 07:49:18 yasuoka Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave @@ -105,6 +105,8 @@ struct ipmi_softc { struct ipmi_sensor *current_sensor; struct ksensordev sc_sensordev; + + int sc_poll; }; struct ipmi_thread { @@ -123,13 +125,23 @@ struct ipmi_thread { #define IPMI_WDOG_PRE_NMI 0x02 #define IPMI_WDOG_PRE_INTERRUPT 0x03 -struct ipmi_watchdog { - u_int8_t wdog_timer; - u_int8_t wdog_action; - u_int8_t wdog_pretimeout; - u_int8_t wdog_flags; - u_int16_t wdog_timeout; -} __packed; +#define IPMI_SET_WDOG_TIMER 0 +#define IPMI_SET_WDOG_ACTION 1 +#define IPMI_SET_WDOG_PRETIMO 2 +#define IPMI_SET_WDOG_FLAGS 3 +#define IPMI_SET_WDOG_TIMOL 4 +#define IPMI_SET_WDOG_TIMOM 5 +#define IPMI_SET_WDOG_MAX 6 + +#define IPMI_GET_WDOG_TIMER IPMI_SET_WDOG_TIMER +#define IPMI_GET_WDOG_ACTION IPMI_SET_WDOG_ACTION +#define IPMI_GET_WDOG_PRETIMO IPMI_SET_WDOG_PRETIMO +#define IPMI_GET_WDOG_FLAGS IPMI_SET_WDOG_FLAGS +#define IPMI_GET_WDOG_TIMOL IPMI_SET_WDOG_TIMOL +#define IPMI_GET_WDOG_TIMOM IPMI_SET_WDOG_TIMOM +#define IPMI_GET_WDOG_PRECDL 6 +#define IPMI_GET_WDOG_PRECDM 7 +#define IPMI_GET_WDOG_MAX 8 void ipmi_create_thread(void *); void ipmi_poll_thread(void *); -- 2.20.1