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);
}