summaryrefslogtreecommitdiff
path: root/sys/dev/ipmi.c
diff options
context:
space:
mode:
authorMasao Uebayashi <uebayasi@cvs.openbsd.org>2016-01-12 10:44:33 +0000
committerMasao Uebayashi <uebayasi@cvs.openbsd.org>2016-01-12 10:44:33 +0000
commit0dd1a4bcabf03e4a229afcee1ba6e40950a93182 (patch)
treeef0be4469c32ee348e8ea69c3e91f3c3bb91f0de /sys/dev/ipmi.c
parent0b4ec507d9fe71f6738a00a04daf84423ab159c2 (diff)
Use task to execute command except polling context.
Diffstat (limited to 'sys/dev/ipmi.c')
-rw-r--r--sys/dev/ipmi.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/sys/dev/ipmi.c b/sys/dev/ipmi.c
index 3fc7759410c..50833d1e872 100644
--- a/sys/dev/ipmi.c
+++ b/sys/dev/ipmi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipmi.c,v 1.89 2016/01/12 09:11:59 uebayasi Exp $ */
+/* $OpenBSD: ipmi.c,v 1.90 2016/01/12 10:44:32 uebayasi Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave
@@ -153,7 +153,10 @@ int get_sdr(struct ipmi_softc *, u_int16_t, u_int16_t *);
int ipmi_sendcmd(struct ipmi_cmd *);
int ipmi_recvcmd(struct ipmi_cmd *);
void ipmi_delay(struct ipmi_softc *, int);
-void ipmi_cmd(void *);
+void ipmi_cmd(struct ipmi_cmd *);
+void ipmi_cmd_poll(struct ipmi_cmd *);
+void ipmi_cmd_wait(struct ipmi_cmd *);
+void ipmi_cmd_wait_cb(void *);
int ipmi_watchdog(void *, int);
void ipmi_watchdog_tickle(void *);
@@ -1069,9 +1072,18 @@ ipmi_delay(struct ipmi_softc *sc, int period)
}
void
-ipmi_cmd(void *arg)
+ipmi_cmd(struct ipmi_cmd *c)
{
- struct ipmi_cmd *c = arg;
+ if (cold || panicstr != NULL)
+ ipmi_cmd_poll(c);
+ else
+ ipmi_cmd_wait(c);
+}
+
+void
+ipmi_cmd_poll(struct ipmi_cmd *c)
+{
+ mtx_enter(&c->c_sc->sc_cmd_mtx);
c->c_sc->sc_cmd = c;
if (ipmi_sendcmd(c)) {
@@ -1079,6 +1091,33 @@ ipmi_cmd(void *arg)
}
c->c_ccode = ipmi_recvcmd(c);
c->c_sc->sc_cmd = NULL;
+
+ mtx_leave(&c->c_sc->sc_cmd_mtx);
+}
+
+void
+ipmi_cmd_wait(struct ipmi_cmd *c)
+{
+ struct task t;
+ int res;
+
+ task_set(&t, ipmi_cmd_wait_cb, c);
+ res = task_add(c->c_sc->sc_cmd_taskq, &t);
+ KASSERT(res == 1);
+
+ tsleep(c, PWAIT, "ipmicmd", 0);
+
+ res = task_del(c->c_sc->sc_cmd_taskq, &t);
+ KASSERT(res == 0);
+}
+
+void
+ipmi_cmd_wait_cb(void *arg)
+{
+ struct ipmi_cmd *c = arg;
+
+ ipmi_cmd_poll(c);
+ wakeup(c);
}
/* Read a partial SDR entry */
@@ -1665,6 +1704,7 @@ ipmi_match(struct device *parent, void *match, void *aux)
return (0);
/* XXX local softc is wrong wrong wrong */
+ mtx_init(&sc.sc_cmd_mtx, IPL_NONE);
strlcpy(sc.sc_dev.dv_xname, "ipmi0", sizeof(sc.sc_dev.dv_xname));
/* Map registers */
@@ -1736,6 +1776,9 @@ ipmi_attach(struct device *parent, struct device *self, void *aux)
sc->sc_wakeup = 0;
sc->sc_max_retries = 50; /* 50 * 1/100 = 0.5 seconds max */
timeout_set(&sc->sc_timeout, _bmc_io_wait, sc);
+
+ sc->sc_cmd_taskq = taskq_create("ipmicmd", 1, IPL_NONE, TASKQ_MPSAFE);
+ mtx_init(&sc->sc_cmd_mtx, IPL_NONE);
}
int