summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2011-04-19 23:59:12 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2011-04-19 23:59:12 +0000
commitfa2a1c77a2883751ee9a3754acbce700a4b9098b (patch)
tree09ba9962a86acba5ab4a2ad792a7ed725fcce7e8
parent3249f56ac424bb7e860d503782462cf753eb95dc (diff)
Iopoolification. Much simpler version than the one revived at k2k11.
This one works. For me at least. Botch spotted by matthew@. ok matthew@ dlg@
-rw-r--r--sys/dev/ic/gdt_common.c87
-rw-r--r--sys/dev/ic/gdtvar.h5
2 files changed, 44 insertions, 48 deletions
diff --git a/sys/dev/ic/gdt_common.c b/sys/dev/ic/gdt_common.c
index 292fa122958..7b4268b119c 100644
--- a/sys/dev/ic/gdt_common.c
+++ b/sys/dev/ic/gdt_common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gdt_common.c,v 1.56 2011/04/19 21:17:07 krw Exp $ */
+/* $OpenBSD: gdt_common.c,v 1.57 2011/04/19 23:59:11 krw Exp $ */
/*
* Copyright (c) 1999, 2000, 2003 Niklas Hallqvist. All rights reserved.
@@ -69,8 +69,8 @@ void gdt_enqueue(struct gdt_softc *, struct scsi_xfer *, int);
void gdt_enqueue_ccb(struct gdt_softc *, struct gdt_ccb *);
void gdt_eval_mapping(u_int32_t, int *, int *, int *);
int gdt_exec_ccb(struct gdt_ccb *);
-void gdt_free_ccb(struct gdt_softc *, struct gdt_ccb *);
-struct gdt_ccb *gdt_get_ccb(struct gdt_softc *, int);
+void gdt_ccb_free(void *, void *);
+void *gdt_ccb_alloc(void *);
void gdt_internal_cache_cmd(struct scsi_xfer *);
int gdt_internal_cmd(struct gdt_softc *, u_int8_t, u_int16_t,
u_int32_t, u_int32_t, u_int32_t);
@@ -131,6 +131,9 @@ gdt_attach(struct gdt_softc *sc)
TAILQ_INIT(&sc->sc_ucmdq);
LIST_INIT(&sc->sc_queue);
+ mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
+ scsi_iopool_init(&sc->sc_iopool, sc, gdt_ccb_alloc, gdt_ccb_free);
+
/* Initialize the ccbs */
for (i = 0; i < GDT_MAXCMDS; i++) {
sc->sc_ccbs[i].gc_cmd_index = i + 2;
@@ -156,6 +159,7 @@ gdt_attach(struct gdt_softc *sc)
sc->sc_link.adapter_buswidth =
(sc->sc_class & GDT_FC) ? GDT_MAXID : GDT_MAX_HDRIVES;
sc->sc_link.adapter_target = sc->sc_link.adapter_buswidth;
+ sc->sc_link.pool = &sc->sc_iopool;
if (!gdt_internal_cmd(sc, GDT_SCREENSERVICE, GDT_INIT, 0, 0, 0)) {
printf("screen service initialization error %d\n",
@@ -676,22 +680,13 @@ gdt_scsi_cmd(struct scsi_xfer *xs)
}
}
- ccb = gdt_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 = xs->io;
ccb->gc_blockno = blockno;
ccb->gc_blockcnt = blockcnt;
ccb->gc_xs = xs;
ccb->gc_timeout = xs->timeout;
ccb->gc_service = GDT_CACHESERVICE;
+ ccb->gc_flags = 0;
gdt_ccb_set_cmd(ccb, GDT_GCF_SCSI);
if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
@@ -712,7 +707,6 @@ gdt_scsi_cmd(struct scsi_xfer *xs)
"loading dma map\n",
error);
- gdt_free_ccb(sc, ccb);
xs->error = XS_DRIVER_STUFFUP;
scsi_done(xs);
goto ready;
@@ -731,7 +725,7 @@ gdt_scsi_cmd(struct scsi_xfer *xs)
printf("%s: command %d timed out\n",
DEVNAME(sc),
ccb->gc_cmd_index);
- xs->error = XS_NO_CCB;
+ xs->error = XS_TIMEOUT;
scsi_done(xs);
splx(s);
return;
@@ -859,7 +853,6 @@ gdt_exec_ccb(struct gdt_ccb *ccb)
sc->sc_cmd_off + sc->sc_cmd_len + GDT_DPMEM_COMMAND_OFFSET >
sc->sc_ic_all_size) {
printf("%s: DPMEM overflow\n", DEVNAME(sc));
- gdt_free_ccb(sc, ccb);
xs->error = XS_BUSY;
#if 1 /* XXX */
__level--;
@@ -1081,7 +1074,6 @@ gdt_intr(void *arg)
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, ccb->gc_dmamap_xfer);
}
- gdt_free_ccb(sc, ccb);
switch (prev_cmd) {
case GDT_GCF_UNUSED:
/* XXX Not yet implemented */
@@ -1159,7 +1151,7 @@ int
gdt_internal_cmd(struct gdt_softc *sc, u_int8_t service, u_int16_t opcode,
u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
{
- int retries;
+ int retries, rslt;
struct gdt_ccb *ccb;
GDT_DPRINTF(GDT_D_CMD, ("gdt_internal_cmd(%p, %d, %d, %d, %d, %d) ",
@@ -1168,13 +1160,17 @@ gdt_internal_cmd(struct gdt_softc *sc, u_int8_t service, u_int16_t opcode,
bzero(sc->sc_cmd, GDT_CMD_SZ);
for (retries = GDT_RETRIES; ; ) {
- ccb = gdt_get_ccb(sc, SCSI_NOSLEEP);
+ ccb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP);
if (ccb == NULL) {
printf("%s: no free command index found\n",
DEVNAME(sc));
return (0);
}
ccb->gc_service = service;
+ ccb->gc_xs = NULL;
+ ccb->gc_blockno = ccb->gc_blockcnt = 0;
+ ccb->gc_timeout = ccb->gc_flags = 0;
+ ccb->gc_service = GDT_CACHESERVICE;
gdt_ccb_set_cmd(ccb, GDT_GCF_INTERNAL);
sc->sc_set_sema0(sc);
@@ -1220,7 +1216,11 @@ gdt_internal_cmd(struct gdt_softc *sc, u_int8_t service, u_int16_t opcode,
sc->sc_copy_cmd(sc, ccb);
sc->sc_release_event(sc, ccb);
DELAY(20);
- if (!gdt_wait(sc, ccb, GDT_POLL_TIMEOUT))
+
+ rslt = gdt_wait(sc, ccb, GDT_POLL_TIMEOUT);
+ scsi_io_put(&sc->sc_iopool, ccb);
+
+ if (!rslt)
return (0);
if (sc->sc_status != GDT_S_BSY || --retries == 0)
break;
@@ -1229,48 +1229,41 @@ gdt_internal_cmd(struct gdt_softc *sc, u_int8_t service, u_int16_t opcode,
return (sc->sc_status == GDT_S_OK);
}
-struct gdt_ccb *
-gdt_get_ccb(struct gdt_softc *sc, int flags)
+void *
+gdt_ccb_alloc(void *xsc)
{
+ struct gdt_softc *sc = xsc;
struct gdt_ccb *ccb;
- int s;
- GDT_DPRINTF(GDT_D_QUEUE, ("gdt_get_ccb(%p, 0x%x) ", sc, flags));
+ GDT_DPRINTF(GDT_D_QUEUE, ("gdt_ccb_alloc(%p) ", sc));
- s = splbio();
+ mtx_enter(&sc->sc_ccb_mtx);
+ ccb = TAILQ_FIRST(&sc->sc_free_ccb);
+ if (ccb != NULL)
+ TAILQ_REMOVE(&sc->sc_free_ccb, ccb, gc_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, "gdt_ccb", 0);
- }
-
- TAILQ_REMOVE(&sc->sc_free_ccb, ccb, gc_chain);
-
- bail_out:
- splx(s);
return (ccb);
}
void
-gdt_free_ccb(struct gdt_softc *sc, struct gdt_ccb *ccb)
+gdt_ccb_free(void *xsc, void *xccb)
{
- int s;
-
- GDT_DPRINTF(GDT_D_QUEUE, ("gdt_free_ccb(%p, %p) ", sc, ccb));
+ struct gdt_softc *sc = xsc;
+ struct gdt_ccb *ccb = xccb;
+ int wake = 0;
- s = splbio();
+ GDT_DPRINTF(GDT_D_QUEUE, ("gdt_ccb_free(%p, %p) ", sc, ccb));
+ mtx_enter(&sc->sc_ccb_mtx);
TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, gc_chain);
-
/* If the free list was empty, wake up potential waiters. */
if (TAILQ_NEXT(ccb, gc_chain) == NULL)
- wakeup(&sc->sc_free_ccb);
+ wake = 1;
+ mtx_leave(&sc->sc_ccb_mtx);
- splx(s);
+ if (wake)
+ wakeup(&sc->sc_free_ccb);
}
void
diff --git a/sys/dev/ic/gdtvar.h b/sys/dev/ic/gdtvar.h
index ede129d8353..d2cd6c9567a 100644
--- a/sys/dev/ic/gdtvar.h
+++ b/sys/dev/ic/gdtvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: gdtvar.h,v 1.18 2011/04/19 21:17:07 krw Exp $ */
+/* $OpenBSD: gdtvar.h,v 1.19 2011/04/19 23:59:11 krw Exp $ */
/*
* Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
@@ -297,6 +297,9 @@ struct gdt_softc {
LIST_HEAD(, scsi_xfer) sc_queue;
struct scsi_xfer *sc_queuelast;
+ struct mutex sc_ccb_mtx;
+ struct scsi_iopool sc_iopool;
+
int sc_ndevs;
u_int16_t sc_cmd_len;