summaryrefslogtreecommitdiff
path: root/sys/dev/i2o/ioprbs.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2011-04-03 17:55:08 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2011-04-03 17:55:08 +0000
commitc350f312257ee11741757d8460540f8b9cd0ffad (patch)
treeaf20a52264fc8bf0d218ea5b0a6a358ab55b4d64 /sys/dev/i2o/ioprbs.c
parent1694bdb65ba4658d65db07434faa8daacde44437 (diff)
back iopools out, it was never compiled.
Diffstat (limited to 'sys/dev/i2o/ioprbs.c')
-rw-r--r--sys/dev/i2o/ioprbs.c71
1 files changed, 52 insertions, 19 deletions
diff --git a/sys/dev/i2o/ioprbs.c b/sys/dev/i2o/ioprbs.c
index 08981337c90..57f9c48524e 100644
--- a/sys/dev/i2o/ioprbs.c
+++ b/sys/dev/i2o/ioprbs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioprbs.c,v 1.26 2011/04/03 16:53:20 dlg Exp $ */
+/* $OpenBSD: ioprbs.c,v 1.27 2011/04/03 17:55:07 dlg Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -99,8 +99,8 @@ struct scsi_xfer *ioprbs_dequeue(struct ioprbs_softc *);
void ioprbs_enqueue(struct ioprbs_softc *, struct scsi_xfer *, int);
void ioprbs_enqueue_ccb(struct ioprbs_softc *, struct ioprbs_ccb *);
int ioprbs_exec_ccb(struct ioprbs_ccb *);
-void ioprbs_free_ccb(void *, void *);
-void *ioprbs_get_ccb(void *);
+void ioprbs_free_ccb(struct ioprbs_softc *, struct ioprbs_ccb *);
+struct ioprbs_ccb *ioprbs_get_ccb(struct ioprbs_softc *, int);
void ioprbs_internal_cache_cmd(struct scsi_xfer *);
void ioprbs_intr(struct device *, struct iop_msg *, void *);
void ioprbs_intr_event(struct device *, struct iop_msg *, void *);
@@ -186,8 +186,6 @@ ioprbs_attach(struct device *parent, struct device *self, void *aux)
TAILQ_INIT(&sc->sc_free_ccb);
TAILQ_INIT(&sc->sc_ccbq);
LIST_INIT(&sc->sc_queue);
- mtx_init(&sc->sc_ccb_mtx);
- scsi_iopool_init(&sc->sc_iopool, sc, iopbrs_get_ccb, iopbrs_free_ccb);
/* Initialize the ccbs */
for (i = 0; i < IOPRBS_MAX_CCBS; i++)
@@ -400,7 +398,7 @@ ioprbs_scsi_cmd(xs)
{
struct scsi_link *link = xs->sc_link;
struct ioprbs_softc *sc = link->adapter_softc;
- struct ioprbs_ccb *ccb = xs->io;
+ struct ioprbs_ccb *ccb;
u_int32_t blockno, blockcnt;
struct scsi_rw *rw;
struct scsi_rw_big *rwb;
@@ -488,6 +486,18 @@ ioprbs_scsi_cmd(xs)
}
}
+ ccb = ioprbs_get_ccb(sc, xs->flags);
+
+ /*
+ * We are out of commands, try again in a little while.
+ */
+ if (ccb == NULL) {
+ xs->error = XS_NO_CCB;
+ scsi_done(xs);
+ splx(s);
+ return;
+ }
+
ccb->ic_blockno = blockno;
ccb->ic_blockcnt = blockcnt;
ccb->ic_xs = xs;
@@ -565,6 +575,7 @@ ioprbs_intr(struct device *dv, struct iop_msg *im, void *reply)
iop_msg_unmap(iop, im);
iop_msg_free(iop, im);
scsi_done(xs);
+ ioprbs_free_ccb(sc, ccb);
}
void
@@ -746,33 +757,55 @@ ioprbs_internal_cache_cmd(xs)
xs->error = XS_NOERROR;
}
-void *
-ioprbs_get_ccb(void *cookie)
+struct ioprbs_ccb *
+ioprbs_get_ccb(sc, flags)
+ struct ioprbs_softc *sc;
+ int flags;
{
- struct iopbrs_softc *sc = cookie;
struct ioprbs_ccb *ccb;
+ int s;
+
+ DPRINTF(("ioprbs_get_ccb(%p, 0x%x) ", sc, flags));
+
+ s = splbio();
- mtx_enter(&sc->sc_ccb_mtx);
- ccb = TAILQ_FIRST(&sc->sc_free_ccb);
- if (ccb)
- TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ic_chain);
- mtx_leave(&sc->sc_ccb_mtx);
+ for (;;) {
+ ccb = TAILQ_FIRST(&sc->sc_free_ccb);
+ if (ccb != NULL)
+ break;
+ if (flags & SCSI_NOSLEEP)
+ goto bail_out;
+ tsleep(&sc->sc_free_ccb, PRIBIO, "ioprbs_ccb", 0);
+ }
+
+ TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ic_chain);
/* initialise the command */
ccb->ic_flags = 0;
+ bail_out:
+ splx(s);
return (ccb);
}
void
-ioprbs_free_ccb(void *cookie, void *io)
+ioprbs_free_ccb(sc, ccb)
+ struct ioprbs_softc *sc;
+ struct ioprbs_ccb *ccb;
{
- struct iopbrs_softc *sc = cookie;
- struct ioprbs_ccb *ccb = io;
+ int s;
+
+ DPRINTF(("ioprbs_free_ccb(%p, %p) ", sc, ccb));
+
+ s = splbio();
- mtx_enter(&sc->sc_ccb_mtx);
TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, ic_chain);
- mtx_leave(&sc->sc_ccb_mtx);
+
+ /* If the free list was empty, wake up potential waiters. */
+ if (TAILQ_NEXT(ccb, ic_chain) == NULL)
+ wakeup(&sc->sc_free_ccb);
+
+ splx(s);
}
void