diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2011-04-19 23:59:12 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2011-04-19 23:59:12 +0000 |
commit | fa2a1c77a2883751ee9a3754acbce700a4b9098b (patch) | |
tree | 09ba9962a86acba5ab4a2ad792a7ed725fcce7e8 | |
parent | 3249f56ac424bb7e860d503782462cf753eb95dc (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.c | 87 | ||||
-rw-r--r-- | sys/dev/ic/gdtvar.h | 5 |
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; |