Module Name: src Committed By: dyoung Date: Mon Jul 20 19:11:30 UTC 2009
Modified Files: src/sys/arch/x86/include: ipmivar.h src/sys/arch/x86/x86: ipmi.c Log Message: Overhaul synchronization in ipmi(4): synchronize all access to device registers with a mutex. Convert tsleep/wakeup calls to cv_wait/cv_signal. Do not repeatedly malloc/free tiny buffers for sending/receiving commands, but reserve a command buffer in the softc. Tickle the watchdog in the sensors-refreshing thread. I am fairly certain that after the device is attached, every register access happens in the sensors-refreshing thread. Moreover, no software interrupt touches any register, now. So I may get rid of the mutex that protects register accesses, sc_cmd_mtx. To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/arch/x86/include/ipmivar.h cvs rdiff -u -r1.38 -r1.39 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/include/ipmivar.h diff -u src/sys/arch/x86/include/ipmivar.h:1.9 src/sys/arch/x86/include/ipmivar.h:1.10 --- src/sys/arch/x86/include/ipmivar.h:1.9 Mon Nov 3 12:25:53 2008 +++ src/sys/arch/x86/include/ipmivar.h Mon Jul 20 19:11:30 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: ipmivar.h,v 1.9 2008/11/03 12:25:53 cegger Exp $ */ +/* $NetBSD: ipmivar.h,v 1.10 2009/07/20 19:11:30 dyoung Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave @@ -28,6 +28,7 @@ */ #include <sys/mutex.h> +#include <sys/condvar.h> #include <dev/sysmon/sysmonvar.h> @@ -45,13 +46,6 @@ struct ipmi_thread; struct ipmi_softc; -struct ipmi_bmc_args{ - int offset; - uint8_t mask; - uint8_t value; - volatile uint8_t *v; -}; - struct ipmi_attach_args { bus_space_tag_t iaa_iot; bus_space_tag_t iaa_memt; @@ -92,22 +86,27 @@ struct lwp *sc_kthread; - struct callout sc_callout; int sc_max_retries; - int sc_retries; - int sc_wakeup; - kmutex_t sc_lock; + kmutex_t sc_poll_mtx; + kcondvar_t sc_poll_cv; + + kmutex_t sc_cmd_mtx; + kcondvar_t sc_cmd_sleep; struct ipmi_bmc_args *sc_iowait_args; struct ipmi_sensor *current_sensor; - volatile int sc_thread_running; + volatile bool sc_thread_running; + volatile bool sc_tickle_due; struct sysmon_wdog sc_wdog; struct sysmon_envsys *sc_envsys; envsys_data_t *sc_sensor; int sc_nsensors; /* total number of sensors */ int sc_nsensors_typ[ENVSYS_NSENSORS]; /* number per type */ + + char sc_buf[64]; + bool sc_buf_rsvd; }; struct ipmi_thread { @@ -115,26 +114,37 @@ volatile int running; }; -#define IPMI_WDOG_USE_NLOG 0x80 -#define IPMI_WDOG_USE_NSTOP 0x40 -#define IPMI_WDOG_USE_USE_MASK 0x07 -#define IPMI_WDOG_USE_USE_FRB2 0x01 -#define IPMI_WDOG_USE_USE_POST 0x02 -#define IPMI_WDOG_USE_USE_OSLOAD 0x03 -#define IPMI_WDOG_USE_USE_OS 0x04 -#define IPMI_WDOG_USE_USE_EOM 0x05 - -#define IPMI_WDOG_ACT_MASK 0x07 -#define IPMI_WDOG_ACT_DISABLED 0x00 -#define IPMI_WDOG_ACT_RESET 0x01 -#define IPMI_WDOG_ACT_PWROFF 0x02 -#define IPMI_WDOG_ACT_PWRCYCLE 0x03 - -#define IPMI_WDOG_ACT_PRE_MASK 0x70 -#define IPMI_WDOG_ACT_PRE_DISABLED 0x00 -#define IPMI_WDOG_ACT_PRE_SMI 0x10 -#define IPMI_WDOG_ACT_PRE_NMI 0x20 -#define IPMI_WDOG_ACT_PRE_INTERRUPT 0x30 +#define IPMI_WDOG_USE_NOLOG __BIT(7) +#define IPMI_WDOG_USE_NOSTOP __BIT(6) +#define IPMI_WDOG_USE_RSVD1 __BITS(5, 3) +#define IPMI_WDOG_USE_USE_MASK __BITS(2, 0) +#define IPMI_WDOG_USE_USE_RSVD __SHIFTIN(0, IPMI_WDOG_USE_USE_MASK); +#define IPMI_WDOG_USE_USE_FRB2 __SHIFTIN(1, IPMI_WDOG_USE_USE_MASK); +#define IPMI_WDOG_USE_USE_POST __SHIFTIN(2, IPMI_WDOG_USE_USE_MASK); +#define IPMI_WDOG_USE_USE_OSLOAD __SHIFTIN(3, IPMI_WDOG_USE_USE_MASK); +#define IPMI_WDOG_USE_USE_OS __SHIFTIN(4, IPMI_WDOG_USE_USE_MASK); +#define IPMI_WDOG_USE_USE_OEM __SHIFTIN(5, IPMI_WDOG_USE_USE_MASK); + +#define IPMI_WDOG_ACT_PRE_RSVD1 __BIT(7) +#define IPMI_WDOG_ACT_PRE_MASK __BITS(6, 4) +#define IPMI_WDOG_ACT_PRE_DISABLED __SHIFTIN(0, IPMI_WDOG_ACT_MASK) +#define IPMI_WDOG_ACT_PRE_SMI __SHIFTIN(1, IPMI_WDOG_ACT_MASK) +#define IPMI_WDOG_ACT_PRE_NMI __SHIFTIN(2, IPMI_WDOG_ACT_MASK) +#define IPMI_WDOG_ACT_PRE_INTERRUPT __SHIFTIN(3, IPMI_WDOG_ACT_MASK) +#define IPMI_WDOG_ACT_PRE_RSVD0 __BIT(3) +#define IPMI_WDOG_ACT_MASK __BITS(2, 0) +#define IPMI_WDOG_ACT_DISABLED __SHIFTIN(0, IPMI_WDOG_ACT_MASK) +#define IPMI_WDOG_ACT_RESET __SHIFTIN(1, IPMI_WDOG_ACT_MASK) +#define IPMI_WDOG_ACT_PWROFF __SHIFTIN(2, IPMI_WDOG_ACT_MASK) +#define IPMI_WDOG_ACT_PWRCYCLE __SHIFTIN(3, IPMI_WDOG_ACT_MASK) + +#define IPMI_WDOG_FLAGS_RSVD1 __BITS(7, 6) +#define IPMI_WDOG_FLAGS_OEM __BIT(5) +#define IPMI_WDOG_FLAGS_OS __BIT(4) +#define IPMI_WDOG_FLAGS_OSLOAD __BIT(3) +#define IPMI_WDOG_FLAGS_POST __BIT(2) +#define IPMI_WDOG_FLAGS_FRB2 __BIT(1) +#define IPMI_WDOG_FLAGS_RSVD0 __BIT(0) struct ipmi_set_watchdog { uint8_t wdog_use; Index: src/sys/arch/x86/x86/ipmi.c diff -u src/sys/arch/x86/x86/ipmi.c:1.38 src/sys/arch/x86/x86/ipmi.c:1.39 --- src/sys/arch/x86/x86/ipmi.c:1.38 Sat Jul 11 05:03:11 2009 +++ src/sys/arch/x86/x86/ipmi.c Mon Jul 20 19:11:30 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: ipmi.c,v 1.38 2009/07/11 05:03:11 pgoyette Exp $ */ +/* $NetBSD: ipmi.c,v 1.39 2009/07/20 19:11:30 dyoung Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.38 2009/07/11 05:03:11 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.39 2009/07/20 19:11:30 dyoung Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -95,7 +95,6 @@ int ipmi_nintr; int ipmi_dbg = 0; -int ipmi_poll = 1; int ipmi_enabled = 0; #define SENSOR_REFRESH_RATE (5 * hz) @@ -178,12 +177,15 @@ uint8_t, uint8_t, void *, uint16_t *); int get_sdr(struct ipmi_softc *, uint16_t, uint16_t *); +char *ipmi_buf_acquire(struct ipmi_softc *, size_t); +void ipmi_buf_release(struct ipmi_softc *, char *); int ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*); int ipmi_recvcmd(struct ipmi_softc *, int, int *, void *); void ipmi_delay(struct ipmi_softc *, int); int ipmi_watchdog_setmode(struct sysmon_wdog *); int ipmi_watchdog_tickle(struct sysmon_wdog *); +void ipmi_dotickle(struct ipmi_softc *); int ipmi_intr(void *); int ipmi_match(device_t, cfdata_t, void *); @@ -198,9 +200,8 @@ uint8_t bmc_read(struct ipmi_softc *, int); void bmc_write(struct ipmi_softc *, int, uint8_t); int bmc_io_wait(struct ipmi_softc *, int, uint8_t, uint8_t, const char *); -int bmc_io_wait_spin(struct ipmi_softc *, int, uint8_t, uint8_t, - const char *); -void _bmc_io_wait(void *); +int bmc_io_wait_spin(struct ipmi_softc *, int, uint8_t, uint8_t); +int bmc_io_wait_sleep(struct ipmi_softc *, int, uint8_t, uint8_t); void *bt_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *); void *cmn_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *); @@ -292,68 +293,42 @@ offset * sc->sc_if_iospacing, val); } -void -_bmc_io_wait(void *arg) +int +bmc_io_wait_sleep(struct ipmi_softc *sc, int offset, uint8_t mask, + uint8_t value) { - struct ipmi_softc *sc = arg; - struct ipmi_bmc_args *a = sc->sc_iowait_args; + int retries; + uint8_t v; - *a->v = bmc_read(sc, a->offset); - if ((*a->v & a->mask) == a->value) { - sc->sc_wakeup = 0; - wakeup(sc); - return; - } + KASSERT(mutex_owned(&sc->sc_cmd_mtx)); - if (++sc->sc_retries > sc->sc_max_retries) { - sc->sc_wakeup = 0; - wakeup(sc); - return; + for (retries = 0; retries < sc->sc_max_retries; retries++) { + v = bmc_read(sc, offset); + if ((v & mask) == value) + return v; + cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_cmd_mtx, 1); } - - callout_schedule(&sc->sc_callout, 1); + return -1; } int bmc_io_wait(struct ipmi_softc *sc, int offset, uint8_t mask, uint8_t value, const char *lbl) { - volatile uint8_t v; - int u; - struct ipmi_bmc_args args; - - u = bmc_io_wait_spin(sc, offset, mask, value, lbl); - if (cold || u != -1) - return u; - - sc->sc_retries = 0; - sc->sc_wakeup = 1; - - args.offset = offset; - args.mask = mask; - args.value = value; - args.v = &v; - sc->sc_iowait_args = &args; - - _bmc_io_wait(sc); - - while (sc->sc_wakeup) - tsleep(sc, PWAIT, lbl, 0); - - if (sc->sc_retries > sc->sc_max_retries) { - dbg_printf(1, "ipmi: bmc_io_wait fails : v=%.2x m=%.2x " - "b=%.2x %s\n", v, mask, value, lbl); - return (-1); - } + int v; - return (v); + v = bmc_io_wait_spin(sc, offset, mask, value); + if (cold || v != -1) + return v; + + return bmc_io_wait_sleep(sc, offset, mask, value); } int bmc_io_wait_spin(struct ipmi_softc *sc, int offset, uint8_t mask, - uint8_t value, const char *lbl) + uint8_t value) { - volatile uint8_t v; + uint8_t v; int count = cold ? 5000 : 500; /* ~us */ @@ -981,7 +956,7 @@ /* Block transfer needs 4 extra bytes: length/netfn/seq/cmd + data */ *txlen = len + 4; - buf = malloc(*txlen, M_DEVBUF, M_WAITOK|M_CANFAIL); + buf = ipmi_buf_acquire(sc, *txlen); if (buf == NULL) return (NULL); @@ -1010,7 +985,7 @@ /* Common needs two extra bytes: nfLun/cmd + data */ *txlen = len + 2; - buf = malloc(*txlen, M_DEVBUF, M_WAITOK|M_CANFAIL); + buf = ipmi_buf_acquire(sc, *txlen); if (buf == NULL) return (NULL); @@ -1022,7 +997,11 @@ return (buf); } -/* Send an IPMI command */ +/* + * ipmi_sendcmd: caller must hold sc_cmd_mtx. + * + * Send an IPMI command + */ int ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd, int txlen, const void *data) @@ -1062,7 +1041,7 @@ goto done; } rc = sc->sc_if->sendmsg(sc, txlen, buf); - free(buf, M_DEVBUF); + ipmi_buf_release(sc, buf); ipmi_delay(sc, 50); /* give bmc chance to digest command */ @@ -1070,6 +1049,28 @@ return (rc); } +void +ipmi_buf_release(struct ipmi_softc *sc, char *buf) +{ + KASSERT(sc->sc_buf_rsvd); + KASSERT(sc->sc_buf == buf); + sc->sc_buf_rsvd = false; +} + +char * +ipmi_buf_acquire(struct ipmi_softc *sc, size_t len) +{ + KASSERT(len <= sizeof(sc->sc_buf)); + + if (sc->sc_buf_rsvd || len > sizeof(sc->sc_buf)) + return NULL; + sc->sc_buf_rsvd = true; + return sc->sc_buf; +} + +/* + * ipmi_recvcmd: caller must hold sc_cmd_mtx. + */ int ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data) { @@ -1077,7 +1078,7 @@ int rawlen; /* Need three extra bytes: netfn/cmd/ccode + data */ - buf = malloc(maxlen + 3, M_DEVBUF, M_WAITOK|M_CANFAIL); + buf = ipmi_buf_acquire(sc, maxlen + 3); if (buf == NULL) { printf("ipmi: ipmi_recvcmd: malloc fails\n"); return (-1); @@ -1099,18 +1100,21 @@ *rxlen); dbg_dump(10, " recv", *rxlen, data); - free(buf, M_DEVBUF); + ipmi_buf_release(sc, buf); return (rc); } +/* + * ipmi_delay: caller must hold sc_cmd_mtx. + */ void ipmi_delay(struct ipmi_softc *sc, int ms) { if (cold) delay(ms * 1000); else - while (tsleep(sc, PWAIT, "ipmicmd", mstohz(ms)) != EWOULDBLOCK); + cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_cmd_mtx, mstohz(ms)); } /* Read a partial SDR entry */ @@ -1125,15 +1129,19 @@ ((uint16_t *) cmd)[1] = recordId; cmd[4] = offset; cmd[5] = length; + mutex_enter(&sc->sc_cmd_mtx); if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6, cmd)) { + mutex_exit(&sc->sc_cmd_mtx); printf("ipmi: sendcmd fails\n"); return (-1); } if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) { + mutex_exit(&sc->sc_cmd_mtx); printf("ipmi: getSdrPartial: recvcmd fails\n"); return (-1); } + mutex_exit(&sc->sc_cmd_mtx); if (nxtRecordId) *nxtRecordId = *(uint16_t *) cmd; memcpy(buffer, cmd + 2, len - 2); @@ -1152,16 +1160,20 @@ uint8_t *psdr; struct sdrhdr shdr; + mutex_enter(&sc->sc_cmd_mtx); /* Reserve SDR */ if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR, 0, NULL)) { + mutex_exit(&sc->sc_cmd_mtx); printf("ipmi: reserve send fails\n"); return (-1); } if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) { + mutex_exit(&sc->sc_cmd_mtx); printf("ipmi: reserve recv fails\n"); return (-1); } + mutex_exit(&sc->sc_cmd_mtx); /* Get SDR Header */ if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) { printf("ipmi: get header fails\n"); @@ -1380,14 +1392,19 @@ sysmon_envsys_lim_t *limits) { struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr; + bool failure; int rxlen; uint8_t data[32]; limits->sel_flags = 0; data[0] = psensor->i_num; - if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, + mutex_enter(&sc->sc_cmd_mtx); + failure = + ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) || - ipmi_recvcmd(sc, sizeof(data), &rxlen, data)) + ipmi_recvcmd(sc, sizeof(data), &rxlen, data); + mutex_exit(&sc->sc_cmd_mtx); + if (failure) return; dbg_printf(25, "recvdata: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", @@ -1485,18 +1502,21 @@ { struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr; uint8_t data[8]; - int rxlen, rv = -1; + int rxlen; envsys_data_t *edata = &sc->sc_sensor[psensor->i_envnum]; - mutex_enter(&sc->sc_lock); memset(data, 0, sizeof(data)); data[0] = psensor->i_num; + + mutex_enter(&sc->sc_cmd_mtx); if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN, SE_GET_SENSOR_READING, 1, data)) - goto done; + goto err; if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data)) - goto done; + goto err; + mutex_exit(&sc->sc_cmd_mtx); + dbg_printf(10, "values=%.2x %.2x %.2x %.2x %s\n", data[0],data[1],data[2],data[3], edata->desc); if (data[1] & IPMI_INVALID_SENSOR) { @@ -1505,10 +1525,10 @@ } else { edata->state = ipmi_sensor_status(sc, psensor, edata, data); } - rv = 0; -done: - mutex_exit(&sc->sc_lock); - return (rv); + return 0; +err: + mutex_exit(&sc->sc_cmd_mtx); + return -1; } int @@ -1675,9 +1695,6 @@ ipmi_refresh_sensors(struct ipmi_softc *sc) { - if (!ipmi_poll) - return; - if (SLIST_EMPTY(&ipmi_sensor_list)) return; @@ -1764,27 +1781,35 @@ int len; int rv = 0; + memset(&sc, 0, sizeof(sc)); + /* Map registers */ if (ipmi_map_regs(&sc, ia) != 0) return 0; sc.sc_if->probe(&sc); + mutex_init(&sc.sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); + mutex_enter(&sc.sc_cmd_mtx); /* Identify BMC device early to detect lying bios */ if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID, 0, NULL)) { + mutex_exit(&sc.sc_cmd_mtx); dbg_printf(1, ": unable to send get device id " "command\n"); goto unmap; } if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) { + mutex_exit(&sc.sc_cmd_mtx); dbg_printf(1, ": unable to retrieve device id\n"); goto unmap; } + mutex_exit(&sc.sc_cmd_mtx); dbg_dump(1, "bmc data", len, cmd); rv = 1; /* GETID worked, we got IPMI */ unmap: + mutex_destroy(&sc.sc_cmd_mtx); ipmi_unmap_regs(&sc); return rv; @@ -1801,17 +1826,17 @@ int i; int current_index_typ[ENVSYS_NSENSORS]; - sc->sc_thread_running = 1; + sc->sc_thread_running = true; /* lock around read_sensor so that no one messes with the bmc regs */ - mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); + mutex_init(&sc->sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); + cv_init(&sc->sc_cmd_sleep, "ipmicmd"); + + mutex_init(&sc->sc_poll_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); + cv_init(&sc->sc_poll_cv, "ipmi_poll"); /* setup ticker */ - sc->sc_retries = 0; - sc->sc_wakeup = 0; sc->sc_max_retries = hz * 90; /* 90 seconds max */ - callout_init(&sc->sc_callout, 0); - callout_setfunc(&sc->sc_callout, _bmc_io_wait, sc); /* Map registers */ ipmi_map_regs(sc, ia); @@ -1900,11 +1925,17 @@ sc->sc_wdog.smw_tickle = ipmi_watchdog_tickle; sysmon_wdog_register(&sc->sc_wdog); + mutex_enter(&sc->sc_poll_mtx); while (sc->sc_thread_running) { ipmi_refresh_sensors(sc); - tsleep(&sc->sc_thread_running, PWAIT, "ipmi_poll", + cv_timedwait(&sc->sc_poll_cv, &sc->sc_poll_mtx, SENSOR_REFRESH_RATE); + if (sc->sc_tickle_due) { + ipmi_dotickle(sc); + sc->sc_tickle_due = false; + } } + mutex_exit(&sc->sc_poll_mtx); kthread_exit(0); } @@ -1930,8 +1961,10 @@ int rc; struct ipmi_softc *sc = device_private(self); - sc->sc_thread_running = 0; - wakeup(&sc->sc_thread_running); + mutex_enter(&sc->sc_poll_mtx); + sc->sc_thread_running = false; + cv_signal(&sc->sc_poll_cv); + mutex_exit(&sc->sc_poll_mtx); if ((rc = sysmon_wdog_unregister(&sc->sc_wdog)) != 0) { if (rc == ERESTART) @@ -1967,8 +2000,10 @@ ipmi_unmap_regs(sc); - callout_destroy(&sc->sc_callout); - mutex_destroy(&sc->sc_lock); + cv_destroy(&sc->sc_poll_cv); + mutex_destroy(&sc->sc_poll_mtx); + cv_destroy(&sc->sc_cmd_sleep); + mutex_destroy(&sc->sc_cmd_mtx); return 0; } @@ -1979,7 +2014,7 @@ struct ipmi_softc *sc = smwdog->smw_cookie; struct ipmi_get_watchdog gwdog; struct ipmi_set_watchdog swdog; - int s, rc, len; + int rc, len; if (smwdog->smw_period < 10) return EINVAL; @@ -1988,32 +2023,31 @@ else sc->sc_wdog.smw_period = smwdog->smw_period; - s = splsoftclock(); + mutex_enter(&sc->sc_cmd_mtx); /* see if we can properly task to the watchdog */ rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, APP_GET_WATCHDOG_TIMER, 0, NULL); rc = ipmi_recvcmd(sc, sizeof(gwdog), &len, &gwdog); + mutex_exit(&sc->sc_cmd_mtx); if (rc) { printf("ipmi: APP_GET_WATCHDOG_TIMER returned 0x%x\n", rc); - splx(s); return EIO; } memset(&swdog, 0, sizeof(swdog)); /* Period is 10ths/sec */ - swdog.wdog_timeout = htole32(sc->sc_wdog.smw_period * 10); - swdog.wdog_action = 0; - if ((smwdog->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { - swdog.wdog_action |= IPMI_WDOG_ACT_DISABLED; - } else { - swdog.wdog_action |= IPMI_WDOG_ACT_RESET; - } + swdog.wdog_timeout = htole16(sc->sc_wdog.smw_period * 10); + if ((smwdog->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) + swdog.wdog_action = IPMI_WDOG_ACT_DISABLED; + else + swdog.wdog_action = IPMI_WDOG_ACT_RESET; swdog.wdog_use = IPMI_WDOG_USE_USE_OS; - rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, - APP_SET_WATCHDOG_TIMER, sizeof(swdog), &swdog); - rc = ipmi_recvcmd(sc, 0, &len, NULL); - splx(s); + mutex_enter(&sc->sc_cmd_mtx); + if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, + APP_SET_WATCHDOG_TIMER, sizeof(swdog), &swdog)) == 0) + rc = ipmi_recvcmd(sc, 0, &len, NULL); + mutex_exit(&sc->sc_cmd_mtx); if (rc) { printf("ipmi: APP_SET_WATCHDOG_TIMER returned 0x%x\n", rc); return EIO; @@ -2026,17 +2060,27 @@ ipmi_watchdog_tickle(struct sysmon_wdog *smwdog) { struct ipmi_softc *sc = smwdog->smw_cookie; - int s, rc, len; - s = splsoftclock(); + mutex_enter(&sc->sc_poll_mtx); + sc->sc_tickle_due = true; + cv_signal(&sc->sc_poll_cv); + mutex_exit(&sc->sc_poll_mtx); + return 0; +} + +void +ipmi_dotickle(struct ipmi_softc *sc) +{ + int rc, len; + + mutex_enter(&sc->sc_cmd_mtx); /* 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); - splx(s); - if (rc) { - printf("ipmi: watchdog tickle returned 0x%x\n", rc); - return EIO; + if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, + APP_RESET_WATCHDOG, 0, NULL)) == 0) + rc = ipmi_recvcmd(sc, 0, &len, NULL); + mutex_exit(&sc->sc_cmd_mtx); + if (rc != 0) { + printf("%s: watchdog tickle returned 0x%x\n", + device_xname(sc->sc_dev), rc); } - return (0); }