summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2010-01-11 03:51:58 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2010-01-11 03:51:58 +0000
commitf2b52e135572d9b6db0a7750f6e49ceb6dc9c86f (patch)
treefa1a76d502bcd56b22eff9717180a4330bad7c7a /sys/dev/ic
parent07b6c47bf3506b1d17f7c5d0a4996c64403ffe9d (diff)
rework the polling code to use the semantic krw@ proposed.
intercept the ccb_done handling so polled commands set a flag that mpi_poll tests on. when ccb_done sets the variable, the poll loop breaks and mpi_poll runs the original ccb_done handler for the ccb completion. this is a lot simpler than the previous implementation and removes a mutex. ok beck@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/mpi.c85
-rw-r--r--sys/dev/ic/mpivar.h4
2 files changed, 34 insertions, 55 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c
index be8b4864e99..4fe99841887 100644
--- a/sys/dev/ic/mpi.c
+++ b/sys/dev/ic/mpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpi.c,v 1.133 2010/01/09 23:15:06 krw Exp $ */
+/* $OpenBSD: mpi.c,v 1.134 2010/01/11 03:51:57 dlg Exp $ */
/*
* Copyright (c) 2005, 2006, 2009 David Gwynne <dlg@openbsd.org>
@@ -92,12 +92,12 @@ struct mpi_ccb *mpi_get_ccb(struct mpi_softc *);
void mpi_put_ccb(struct mpi_softc *, struct mpi_ccb *);
int mpi_alloc_replies(struct mpi_softc *);
void mpi_push_replies(struct mpi_softc *);
-u_int32_t mpi_pop_reply(struct mpi_softc *);
void mpi_push_reply(struct mpi_softc *, struct mpi_rcb *);
void mpi_start(struct mpi_softc *, struct mpi_ccb *);
int mpi_poll(struct mpi_softc *, struct mpi_ccb *, int);
-struct mpi_ccb *mpi_reply(struct mpi_softc *, u_int32_t);
+void mpi_poll_done(struct mpi_ccb *);
+void mpi_reply(struct mpi_softc *, u_int32_t);
void mpi_wait(struct mpi_softc *sc, struct mpi_ccb *);
void mpi_wait_done(struct mpi_ccb *);
@@ -173,7 +173,7 @@ void mpi_refresh_sensors(void *);
#define mpi_write_db(s, v) mpi_write((s), MPI_DOORBELL, (v))
#define mpi_read_intr(s) mpi_read((s), MPI_INTR_STATUS)
#define mpi_write_intr(s, v) mpi_write((s), MPI_INTR_STATUS, (v))
-#define mpi_pop_reply_db(s) mpi_read((s), MPI_REPLY_QUEUE)
+#define mpi_pop_reply(s) mpi_read((s), MPI_REPLY_QUEUE)
#define mpi_push_reply_db(s, v) mpi_write((s), MPI_REPLY_QUEUE, (v))
#define mpi_wait_db_int(s) mpi_wait_ne((s), MPI_INTR_STATUS, \
@@ -205,8 +205,6 @@ mpi_attach(struct mpi_softc *sc)
struct scsibus_attach_args saa;
struct mpi_ccb *ccb;
- mtx_init(&sc->sc_reply_mtx, IPL_BIO);
-
printf("\n");
/* disable interrupts */
@@ -822,34 +820,22 @@ mpi_detach(struct mpi_softc *sc)
}
-u_int32_t
-mpi_pop_reply(struct mpi_softc *sc)
-{
- u_int32_t reg;
-
- mtx_enter(&sc->sc_reply_mtx);
- reg = mpi_pop_reply_db(sc);
- mtx_leave(&sc->sc_reply_mtx);
-
- return (reg);
-}
-
int
mpi_intr(void *arg)
{
struct mpi_softc *sc = arg;
- struct mpi_ccb *ccb = NULL;
u_int32_t reg;
+ int rv = 0;
while ((reg = mpi_pop_reply(sc)) != 0xffffffff) {
- ccb = mpi_reply(sc, reg);
- ccb->ccb_done(ccb);
+ mpi_reply(sc, reg);
+ rv = 1;
}
- return ((ccb == NULL) ? 0 : 1);
+ return (rv);
}
-struct mpi_ccb *
+void
mpi_reply(struct mpi_softc *sc, u_int32_t reg)
{
struct mpi_ccb *ccb;
@@ -897,7 +883,7 @@ mpi_reply(struct mpi_softc *sc, u_int32_t reg)
ccb->ccb_state = MPI_CCB_READY;
ccb->ccb_rcb = rcb;
- return (ccb);
+ ccb->ccb_done(ccb);
}
struct mpi_dmamem *
@@ -1124,23 +1110,26 @@ mpi_start(struct mpi_softc *sc, struct mpi_ccb *ccb)
int
mpi_poll(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
{
- struct mpi_ccb_list completed =
- TAILQ_HEAD_INITIALIZER(completed);
- struct mpi_ccb *nccb = NULL;
+ void (*done)(struct mpi_ccb *);
+ void *cookie;
+ int rv = 1;
u_int32_t reg;
- int rv = 0;
DNPRINTF(MPI_D_INTR, "%s: mpi_poll timeout %d\n", DEVNAME(sc),
timeout);
- mtx_enter(&sc->sc_reply_mtx);
+ done = ccb->ccb_done;
+ cookie = ccb->ccb_cookie;
+
+ ccb->ccb_done = mpi_poll_done;
+ ccb->ccb_cookie = &rv;
+
mpi_start(sc, ccb);
- do {
- reg = mpi_pop_reply_db(sc);
+ while (rv == 1) {
+ reg = mpi_pop_reply(sc);
if (reg == 0xffffffff) {
if (timeout-- == 0) {
printf("%s: timeout\n", DEVNAME(sc));
- rv = 1;
goto timeout;
}
@@ -1148,33 +1137,25 @@ mpi_poll(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout)
continue;
}
- nccb = mpi_reply(sc, reg);
-
- /*
- * The ccb used for event notification can come out of the
- * reply doorbell multiple times. Avoid enqueuing it here for
- * completion outside the reply mutex since that can screw the
- * completed TAILQ up. We know it will not cause new ccbs to be
- * generated and issued, so it is safe to complete here.
- */
- if (nccb == sc->sc_evt_ccb)
- nccb->ccb_done(nccb);
- else
- TAILQ_INSERT_TAIL(&completed, nccb, ccb_link);
+ mpi_reply(sc, reg);
+ }
- } while (ccb != nccb);
- mtx_leave(&sc->sc_reply_mtx);
+ ccb->ccb_cookie = cookie;
+ done(ccb);
timeout:
- while ((nccb = TAILQ_FIRST(&completed)) != NULL) {
- TAILQ_REMOVE(&completed, nccb, ccb_link);
- nccb->ccb_done(nccb);
- }
-
return (rv);
}
void
+mpi_poll_done(struct mpi_ccb *ccb)
+{
+ int *rv = ccb->ccb_cookie;
+
+ *rv = 0;
+}
+
+void
mpi_wait(struct mpi_softc *sc, struct mpi_ccb *ccb)
{
struct mutex cookie = MUTEX_INITIALIZER(IPL_BIO);
diff --git a/sys/dev/ic/mpivar.h b/sys/dev/ic/mpivar.h
index e3431224b53..9e29bf027c2 100644
--- a/sys/dev/ic/mpivar.h
+++ b/sys/dev/ic/mpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpivar.h,v 1.28 2010/01/03 06:47:58 dlg Exp $ */
+/* $OpenBSD: mpivar.h,v 1.29 2010/01/11 03:51:57 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -112,8 +112,6 @@ struct mpi_softc {
bus_size_t sc_ios;
bus_dma_tag_t sc_dmat;
- struct mutex sc_reply_mtx;
-
u_int8_t sc_porttype;
int sc_maxcmds;
int sc_maxchdepth;