diff options
Diffstat (limited to 'sys/dev/ic/mpi.c')
-rw-r--r-- | sys/dev/ic/mpi.c | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c index 256bdc93308..8f5f5341eed 100644 --- a/sys/dev/ic/mpi.c +++ b/sys/dev/ic/mpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpi.c,v 1.128 2010/01/03 06:47:58 dlg Exp $ */ +/* $OpenBSD: mpi.c,v 1.129 2010/01/03 07:05:43 dlg Exp $ */ /* * Copyright (c) 2005, 2006, 2009 David Gwynne <dlg@openbsd.org> @@ -99,6 +99,9 @@ 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_wait(struct mpi_softc *sc, struct mpi_ccb *); +void mpi_wait_done(struct mpi_ccb *); + int mpi_cfg_spi_port(struct mpi_softc *); void mpi_squash_ppr(struct mpi_softc *); void mpi_run_ppr(struct mpi_softc *); @@ -1171,6 +1174,38 @@ timeout: return (rv); } +void +mpi_wait(struct mpi_softc *sc, struct mpi_ccb *ccb) +{ + struct mutex cookie = MUTEX_INITIALIZER(IPL_BIO); + void (*done)(struct mpi_ccb *); + + done = ccb->ccb_done; + ccb->ccb_done = mpi_wait_done; + + /* XXX this will wait forever for the ccb to complete */ + + mpi_start(sc, ccb); + + mtx_enter(&cookie); + while (ccb->ccb_cookie != NULL) + msleep(ccb, &cookie, PRIBIO, "mpiwait", 0); + mtx_leave(&cookie); + + done(ccb); +} + +void +mpi_wait_done(struct mpi_ccb *ccb) +{ + struct mutex *cookie = ccb->ccb_cookie; + + mtx_enter(cookie); + ccb->ccb_cookie = NULL; + wakeup_one(ccb); + mtx_leave(cookie); +} + int mpi_scsi_cmd(struct scsi_xfer *xs) { @@ -2479,7 +2514,6 @@ mpi_req_cfg_header(struct mpi_softc *sc, u_int8_t type, u_int8_t number, struct mpi_ecfg_hdr *ehdr = p; int etype = 0; int rv = 0; - int s; DNPRINTF(MPI_D_MISC, "%s: mpi_req_cfg_header type: %#x number: %x " "address: 0x%08x flags: 0x%b\n", DEVNAME(sc), type, number, @@ -2511,21 +2545,15 @@ mpi_req_cfg_header(struct mpi_softc *sc, u_int8_t type, u_int8_t number, cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL); + ccb->ccb_done = mpi_empty_done; if (ISSET(flags, MPI_PG_POLL)) { - ccb->ccb_done = mpi_empty_done; if (mpi_poll(sc, ccb, 50000) != 0) { DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc)); return (1); } - } else { - ccb->ccb_done = (void (*)(struct mpi_ccb *))wakeup; - s = splbio(); - mpi_start(sc, ccb); - while (ccb->ccb_state != MPI_CCB_READY) - tsleep(ccb, PRIBIO, "mpipghdr", 0); - splx(s); - } + } else + mpi_wait(sc, ccb); if (ccb->ccb_rcb == NULL) panic("%s: unable to fetch config header\n", DEVNAME(sc)); @@ -2581,7 +2609,6 @@ mpi_req_cfg_page(struct mpi_softc *sc, u_int32_t address, int flags, char *kva; int page_length; int rv = 0; - int s; DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page address: %d read: %d type: %x\n", DEVNAME(sc), address, read, hdr->page_type); @@ -2633,21 +2660,15 @@ mpi_req_cfg_page(struct mpi_softc *sc, u_int32_t address, int flags, if (!read) bcopy(page, kva, len); + ccb->ccb_done = mpi_empty_done; if (ISSET(flags, MPI_PG_POLL)) { - ccb->ccb_done = mpi_empty_done; if (mpi_poll(sc, ccb, 50000) != 0) { DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc)); return (1); } - } else { - ccb->ccb_done = (void (*)(struct mpi_ccb *))wakeup; - s = splbio(); - mpi_start(sc, ccb); - while (ccb->ccb_state != MPI_CCB_READY) - tsleep(ccb, PRIBIO, "mpipghdr", 0); - splx(s); - } + } else + mpi_wait(sc, ccb); if (ccb->ccb_rcb == NULL) { mpi_put_ccb(sc, ccb); |