As with cac(4). You can test now or can break later.

.... Ken

Index: ic/gdt_common.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/gdt_common.c,v
retrieving revision 1.55
diff -u -p -r1.55 gdt_common.c
--- ic/gdt_common.c     12 Oct 2010 00:53:32 -0000      1.55
+++ ic/gdt_common.c     13 Oct 2010 11:09:09 -0000
@@ -61,16 +61,12 @@ int gdt_maxcmds = GDT_MAXCMDS;
 #define GDT_DRIVER_SUBVERSION 2
 
 int    gdt_async_event(struct gdt_softc *, int);
-void   gdt_chain(struct gdt_softc *);
 void   gdt_clear_events(struct gdt_softc *);
 void   gdt_copy_internal_data(struct scsi_xfer *, u_int8_t *, size_t);
-struct scsi_xfer *gdt_dequeue(struct gdt_softc *);
-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);
@@ -82,9 +78,7 @@ int   gdt_ioctl_disk(struct gdt_softc *, s
 int    gdt_ioctl_alarm(struct gdt_softc *, struct bioc_alarm *);
 int    gdt_ioctl_setstate(struct gdt_softc *, struct bioc_setstate *);
 #endif /* NBIO > 0 */
-void   gdt_raw_scsi_cmd(struct scsi_xfer *);
 void   gdt_scsi_cmd(struct scsi_xfer *);
-void   gdt_start_ccbs(struct gdt_softc *);
 int    gdt_sync_event(struct gdt_softc *, int, u_int8_t,
     struct scsi_xfer *);
 void   gdt_timeout(void *);
@@ -99,10 +93,6 @@ struct scsi_adapter gdt_switch = {
        gdt_scsi_cmd, gdtminphys, 0, 0,
 };
 
-struct scsi_adapter gdt_raw_switch = {
-       gdt_raw_scsi_cmd, gdtminphys, 0, 0,
-};
-
 int gdt_cnt = 0;
 u_int8_t gdt_polling;
 u_int8_t gdt_from_wait;
@@ -132,9 +122,8 @@ gdt_attach(struct gdt_softc *sc)
        gdt_clear_events(sc);
 
        TAILQ_INIT(&sc->sc_free_ccb);
-       TAILQ_INIT(&sc->sc_ccbq);
-       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++) {
@@ -484,26 +473,6 @@ gdt_attach(struct gdt_softc *sc)
 
        config_found(&sc->sc_dev, &saa, scsiprint);
 
-       sc->sc_raw_link = malloc(sc->sc_bus_cnt * sizeof (struct scsi_link),
-           M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (sc->sc_raw_link == NULL)
-               panic("gdt_attach");
-
-       for (i = 0; i < sc->sc_bus_cnt; i++) {
-               /* Fill in the prototype scsi_link. */
-               sc->sc_raw_link[i].adapter_softc = sc;
-               sc->sc_raw_link[i].adapter = &gdt_raw_switch;
-               sc->sc_raw_link[i].adapter_target = 7;
-               sc->sc_raw_link[i].openings = 4;        /* XXX a guess */
-               sc->sc_raw_link[i].adapter_buswidth =
-                   (sc->sc_class & GDT_FC) ? GDT_MAXID : 16;   /* XXX */
-
-               bzero(&saa, sizeof(saa));
-               saa.saa_sc_link = &sc->sc_raw_link[i];
-
-               config_found(&sc->sc_dev, &saa, scsiprint);
-       }
-
        gdt_polling = 0;
        return (0);
 }
@@ -531,43 +500,6 @@ gdt_eval_mapping(u_int32_t size, int *cy
 }
 
 /*
- * Insert a command into the driver queue, either at the front or at the tail.
- * It's ok to overload the freelist link as these structures are never on
- * the freelist at this time.
- */
-void
-gdt_enqueue(struct gdt_softc *sc, struct scsi_xfer *xs, int infront)
-{
-       if (infront || LIST_FIRST(&sc->sc_queue) == NULL) {
-               if (LIST_FIRST(&sc->sc_queue) == NULL)
-                       sc->sc_queuelast = xs;
-               LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
-               return;
-       }
-       LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
-       sc->sc_queuelast = xs;
-}
-
-/*
- * Pull a command off the front of the driver queue.
- */
-struct scsi_xfer *
-gdt_dequeue(struct gdt_softc *sc)
-{
-       struct scsi_xfer *xs;
-
-       xs = LIST_FIRST(&sc->sc_queue);
-       if (xs == NULL)
-               return (NULL);
-       LIST_REMOVE(xs, free_list);
-
-       if (LIST_FIRST(&sc->sc_queue) == NULL)
-               sc->sc_queuelast = NULL;
-
-       return (xs);
-}
-
-/*
  * Start a SCSI operation on a cache device.
  * XXX Polled operation is not yet complete.  What kind of locking do we need?
  */
@@ -576,18 +508,13 @@ gdt_scsi_cmd(struct scsi_xfer *xs)
 {
        struct scsi_link *link = xs->sc_link;
        struct gdt_softc *sc = link->adapter_softc;
-       u_int8_t target = link->target;
        struct gdt_ccb *ccb;
-#if 0
-       struct gdt_ucmd *ucmd;
-#endif
-       u_int32_t blockno, blockcnt;
        struct scsi_rw *rw;
        struct scsi_rw_big *rwb;
        bus_dmamap_t xfer;
-       int error;
-       int s;
-       int polled;
+       u_int32_t blockno, blockcnt;
+       int error, s, polled;
+       u_int8_t target = link->target;
 
        GDT_DPRINTF(GDT_D_CMD, ("gdt_scsi_cmd "));
 
@@ -607,169 +534,139 @@ gdt_scsi_cmd(struct scsi_xfer *xs)
                return;
        }
 
-       /* Don't double enqueue if we came from gdt_chain. */
-       if (xs != LIST_FIRST(&sc->sc_queue))
-               gdt_enqueue(sc, xs, 0);
+       xs->error = XS_NOERROR;
+       ccb = xs->io;
+       link = xs->sc_link;
+       target = link->target;
+       polled = ISSET(xs->flags, SCSI_POLL);
 
-       while ((xs = gdt_dequeue(sc)) != NULL) {
-               xs->error = XS_NOERROR;
-               ccb = NULL;
-               link = xs->sc_link;
-               target = link->target;
-               polled = ISSET(xs->flags, SCSI_POLL);
- 
-               if (!gdt_polling && !(xs->flags & SCSI_POLL) &&
-                   sc->sc_test_busy(sc)) {
-                       /*
-                        * Put it back in front.  XXX Should we instead
-                        * set xs->error to XS_BUSY?
-                        */
-                       gdt_enqueue(sc, xs, 1);
-                       break;
-               }
+       if (!gdt_polling && !polled && sc->sc_test_busy(sc)) {
+               splx(s);
+               xs->error = XS_BUSY;
+               scsi_done(xs);
+               return;
+       }
 
-               switch (xs->cmd->opcode) {
-               case TEST_UNIT_READY:
-               case REQUEST_SENSE:
-               case INQUIRY:
-               case MODE_SENSE:
-               case START_STOP:
-               case READ_CAPACITY:
-#if 0
-               case VERIFY:
-#endif
-                       gdt_internal_cache_cmd(xs);
-                       scsi_done(xs);
-                       goto ready;
+       switch (xs->cmd->opcode) {
+       case TEST_UNIT_READY:
+       case REQUEST_SENSE:
+       case INQUIRY:
+       case MODE_SENSE:
+       case START_STOP:
+       case READ_CAPACITY:
+               gdt_internal_cache_cmd(xs);
+               scsi_done(xs);
+               break;
 
-               case PREVENT_ALLOW:
-                       GDT_DPRINTF(GDT_D_CMD, ("PREVENT/ALLOW "));
-                       /* XXX Not yet implemented */
-                       xs->error = XS_NOERROR;
-                       scsi_done(xs);
-                       goto ready;
+       case PREVENT_ALLOW:
+               GDT_DPRINTF(GDT_D_CMD, ("PREVENT/ALLOW "));
+               /* XXX Not yet implemented */
+               xs->error = XS_NOERROR;
+               scsi_done(xs);
+               break;
 
-               default:
-                       GDT_DPRINTF(GDT_D_CMD,
-                           ("unknown opc %d ", xs->cmd->opcode));
-                       /* XXX Not yet implemented */
-                       xs->error = XS_DRIVER_STUFFUP;
-                       scsi_done(xs);
-                       goto ready;
+       default:
+               GDT_DPRINTF(GDT_D_CMD,
+                   ("unknown opc %d ", xs->cmd->opcode));
+               /* XXX Not yet implemented */
+               xs->error = XS_DRIVER_STUFFUP;
+               scsi_done(xs);
+               break;
 
-               case READ_COMMAND:
-               case READ_BIG:
-               case WRITE_COMMAND:
-               case WRITE_BIG:
-               case SYNCHRONIZE_CACHE:
-                       /*
-                        * A new command chain, start from the beginning.
-                        */
-                       sc->sc_cmd_off = 0;
+       case READ_COMMAND:
+       case READ_BIG:
+       case WRITE_COMMAND:
+       case WRITE_BIG:
+       case SYNCHRONIZE_CACHE:
+               /*
+                * A new command chain, start from the beginning.
+                */
+               sc->sc_cmd_off = 0;
 
-                       if (xs->cmd->opcode == SYNCHRONIZE_CACHE) {
-                                blockno = blockcnt = 0;
+               if (xs->cmd->opcode == SYNCHRONIZE_CACHE) {
+                        blockno = blockcnt = 0;
+               } else {
+                       /* A read or write operation. */
+                       if (xs->cmdlen == 6) {
+                               rw = (struct scsi_rw *)xs->cmd;
+                               blockno = _3btol(rw->addr) &
+                                   (SRW_TOPADDR << 16 | 0xffff);
+                               blockcnt =
+                                   rw->length ? rw->length : 0x100;
                        } else {
-                               /* A read or write operation. */
-                               if (xs->cmdlen == 6) {
-                                       rw = (struct scsi_rw *)xs->cmd;
-                                       blockno = _3btol(rw->addr) &
-                                           (SRW_TOPADDR << 16 | 0xffff);
-                                       blockcnt =
-                                           rw->length ? rw->length : 0x100;
-                               } else {
-                                       rwb = (struct scsi_rw_big *)xs->cmd;
-                                       blockno = _4btol(rwb->addr);
-                                       blockcnt = _2btol(rwb->length);
-                               }
-                               if (blockno >= sc->sc_hdr[target].hd_size ||
-                                   blockno + blockcnt >
-                                   sc->sc_hdr[target].hd_size) {
-                                       printf(
-                                           "%s: out of bounds %u-%u >= %u\n",
-                                           DEVNAME(sc), blockno,
-                                           blockcnt,
-                                           sc->sc_hdr[target].hd_size);
-                                       /*
-                                        * XXX Should be XS_SENSE but that
-                                        * would require setting up a faked
-                                        * sense too.
-                                        */
-                                       xs->error = XS_DRIVER_STUFFUP;
-                                       scsi_done(xs);
-                                       goto ready;
-                               }
+                               rwb = (struct scsi_rw_big *)xs->cmd;
+                               blockno = _4btol(rwb->addr);
+                               blockcnt = _2btol(rwb->length);
                        }
-
-                       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;
+                       if (blockno >= sc->sc_hdr[target].hd_size ||
+                           blockno + blockcnt >
+                           sc->sc_hdr[target].hd_size) {
+                               printf(
+                                   "%s: out of bounds %u-%u >= %u\n",
+                                   DEVNAME(sc), blockno,
+                                   blockcnt,
+                                   sc->sc_hdr[target].hd_size);
+                               /*
+                                * XXX Should be XS_SENSE but that
+                                * would require setting up a faked
+                                * sense too.
+                                */
+                               xs->error = XS_DRIVER_STUFFUP;
                                scsi_done(xs);
-                               splx(s);
-                               return;
+                               break;
                        }
+               }
 
-                       ccb->gc_blockno = blockno;
-                       ccb->gc_blockcnt = blockcnt;
-                       ccb->gc_xs = xs;
-                       ccb->gc_timeout = xs->timeout;
-                       ccb->gc_service = GDT_CACHESERVICE;
-                       gdt_ccb_set_cmd(ccb, GDT_GCF_SCSI);
-
-                       if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
-                               xfer = ccb->gc_dmamap_xfer;
-                               error = bus_dmamap_load(sc->sc_dmat, xfer,
-                                   xs->data, xs->datalen, NULL,
-                                   (xs->flags & SCSI_NOSLEEP) ?
-                                   BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
-                               if (error) {
-                                       printf("%s: gdt_scsi_cmd: ",
-                                           DEVNAME(sc));
-                                       if (error == EFBIG)
-                                               printf(
-                                                   "more than %d dma segs\n",
-                                                   GDT_MAXOFFSETS);
-                                       else
-                                               printf("error %d "
-                                                   "loading dma map\n",
-                                                   error);
-
-                                       gdt_free_ccb(sc, ccb);
-                                       xs->error = XS_DRIVER_STUFFUP;
-                                       scsi_done(xs);
-                                       goto ready;
-                               }
-                               bus_dmamap_sync(sc->sc_dmat, xfer, 0,
-                                   xfer->dm_mapsize,
-                                   (xs->flags & SCSI_DATA_IN) ?
-                                   BUS_DMASYNC_PREREAD :
-                                   BUS_DMASYNC_PREWRITE);
-                       }
+               ccb = xs->io;
 
-                       gdt_enqueue_ccb(sc, ccb);
-                       /* XXX what if enqueue did not start a transfer? */
-                       if (gdt_polling || (xs->flags & SCSI_POLL)) {
-                               if (!gdt_wait(sc, ccb, ccb->gc_timeout)) {
-                                       printf("%s: command %d timed out\n",
-                                           DEVNAME(sc),
-                                           ccb->gc_cmd_index);
-                                       xs->error = XS_NO_CCB;
-                                       scsi_done(xs);
-                                       splx(s);
-                                       return;
-                               }
+               ccb->gc_blockno = blockno;
+               ccb->gc_blockcnt = blockcnt;
+               ccb->gc_xs = xs;
+               ccb->gc_timeout = xs->timeout;
+               ccb->gc_service = GDT_CACHESERVICE;
+               gdt_ccb_set_cmd(ccb, GDT_GCF_SCSI);
+
+               if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
+                       xfer = ccb->gc_dmamap_xfer;
+                       error = bus_dmamap_load(sc->sc_dmat, xfer,
+                           xs->data, xs->datalen, NULL,
+                           (xs->flags & SCSI_NOSLEEP) ?
+                           BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
+                       if (error) {
+                               printf("%s: gdt_scsi_cmd: ",
+                                   DEVNAME(sc));
+                               if (error == EFBIG)
+                                       printf(
+                                           "more than %d dma segs\n",
+                                           GDT_MAXOFFSETS);
+                               else
+                                       printf("error %d "
+                                           "loading dma map\n",
+                                           error);
+
+                               xs->error = XS_DRIVER_STUFFUP;
+                               scsi_done(xs);
+                               break;
                        }
+                       bus_dmamap_sync(sc->sc_dmat, xfer, 0,
+                           xfer->dm_mapsize,
+                           (xs->flags & SCSI_DATA_IN) ?
+                           BUS_DMASYNC_PREREAD :
+                           BUS_DMASYNC_PREWRITE);
                }
 
-       ready:
-               /*
-                * Don't process the queue if we are polling.
-                */
-               if (polled) {
-                       break;
+               gdt_exec_ccb(ccb);
+
+               /* XXX what if enqueue did not start a transfer? */
+               if (gdt_polling || (xs->flags & SCSI_POLL)) {
+                       if (!gdt_wait(sc, ccb, ccb->gc_timeout)) {
+                               printf("%s: command %d timed out\n",
+                                   DEVNAME(sc),
+                                   ccb->gc_cmd_index);
+                               xs->error = XS_BUSY;
+                               scsi_done(xs);
+                               break;
+                       }
                }
        }
 
@@ -787,12 +684,11 @@ gdt_exec_ccb(struct gdt_ccb *ccb)
        u_int32_t sg_canz;
        bus_dmamap_t xfer;
        int i;
-#if 1 /* XXX */
        static int __level = 0;
 
        if (__level++ > 0)
                panic("level > 0");
-#endif
+
        GDT_DPRINTF(GDT_D_CMD, ("gdt_exec_ccb(%p, %p) ", xs, ccb));
 
        sc->sc_cmd_cnt = 0;
@@ -884,11 +780,9 @@ 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 */
+               scsi_done(xs);
                __level--;
-#endif
                return (0);
        }
 
@@ -897,9 +791,7 @@ gdt_exec_ccb(struct gdt_ccb *ccb)
 
        xs->error = XS_NOERROR;
        xs->resid = 0;
-#if 1 /* XXX */
        __level--;
-#endif
        return (1);
 }
 
@@ -989,43 +881,6 @@ gdt_internal_cache_cmd(struct scsi_xfer 
        xs->error = XS_NOERROR;
 }
 
-/* Start a raw SCSI operation */
-void
-gdt_raw_scsi_cmd(struct scsi_xfer *xs)
-{
-       struct scsi_link *link = xs->sc_link;
-       struct gdt_softc *sc = link->adapter_softc;
-       struct gdt_ccb *ccb;
-       int s;
-
-       GDT_DPRINTF(GDT_D_CMD, ("gdt_raw_scsi_cmd "));
-
-       if (xs->cmdlen > 12 /* XXX create #define */) {
-               GDT_DPRINTF(GDT_D_CMD, ("CDB too big %p ", xs));
-               bzero(&xs->sense, sizeof(xs->sense));
-               xs->sense.error_code = SSD_ERRCODE_VALID | SSD_ERRCODE_CURRENT;
-               xs->sense.flags = SKEY_ILLEGAL_REQUEST;
-               xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */
-               xs->error = XS_SENSE;
-               scsi_done(xs);
-               return;
-       }
-
-       if ((ccb = gdt_get_ccb(sc, xs->flags)) == NULL) {
-               GDT_DPRINTF(GDT_D_CMD, ("no ccb available for %p ", xs));
-               xs->error = XS_DRIVER_STUFFUP;
-               scsi_done(xs);
-               return;
-       }
-
-       xs->error = XS_DRIVER_STUFFUP;
-       s = splbio();
-       scsi_done(xs);
-       gdt_free_ccb(sc, ccb);
-
-       splx(s);
-}
-
 void
 gdt_clear_events(struct gdt_softc *sc)
 {
@@ -1085,7 +940,6 @@ gdt_intr(void *arg)
 {
        struct gdt_softc *sc = arg;
        struct gdt_intr_ctx ctx;
-       int chain = 1;
        int sync_val = 0;
        struct scsi_xfer *xs = NULL;
        int prev_cmd;
@@ -1125,7 +979,6 @@ gdt_intr(void *arg)
        case GDT_SPEZINDEX:
                printf("%s: uninitialized or unknown service (%d %d)\n",
                    DEVNAME(sc), ctx.info, ctx.info2);
-               chain = 0;
                goto finish;
        }
 
@@ -1143,14 +996,11 @@ 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 */
-               chain = 0;
                goto finish;
        case GDT_GCF_INTERNAL:
-               chain = 0;
                goto finish;
        }
 
@@ -1167,12 +1017,9 @@ gdt_intr(void *arg)
                break;
 
        case 2:
-               gdt_enqueue(sc, xs, 0);
+               break;
        }
 
-       if (chain)
-               gdt_chain(sc);
-
        return (1);
 }
 
@@ -1221,16 +1068,16 @@ 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;
        struct gdt_ccb *ccb;
+       int retries, rslt;
 
        GDT_DPRINTF(GDT_D_CMD, ("gdt_internal_cmd(%p, %d, %d, %d, %d, %d) ",
            sc, service, opcode, arg1, arg2, arg3));
 
        bzero(sc->sc_cmd, GDT_CMD_SZ);
 
-       for (retries = GDT_RETRIES; ; ) {
-               ccb = gdt_get_ccb(sc, SCSI_NOSLEEP);
+       for (retries = GDT_RETRIES; retries > 0; retries--) {
+               ccb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP);
                if (ccb == NULL) {
                        printf("%s: no free command index found\n",
                            DEVNAME(sc));
@@ -1282,7 +1129,12 @@ gdt_internal_cmd(struct gdt_softc *sc, u
                sc->sc_copy_cmd(sc, ccb);
                sc->sc_release_event(sc, ccb);
                DELAY(20);
-               if (!gdt_wait(sc, ccb, GDT_POLL_TIMEOUT))
+
+               gdt_exec_ccb(ccb);
+               rslt = gdt_wait(sc, ccb, GDT_POLL_TIMEOUT);
+
+               scsi_io_put(&sc->sc_iopool, ccb);
+               if (rslt == 0)
                        return (0);
                if (sc->sc_status != GDT_S_BSY || --retries == 0)
                        break;
@@ -1291,96 +1143,34 @@ gdt_internal_cmd(struct gdt_softc *sc, u
        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));
-
-       s = splbio();
 
-       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);
-       }
+       GDT_DPRINTF(GDT_D_QUEUE, ("gdt_ccb_alloc(%p, 0x%x) ", sc, flags));
 
-       TAILQ_REMOVE(&sc->sc_free_ccb, ccb, gc_chain);
+       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);
 
- 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;
+       struct gdt_softc *sc = xsc;
+       struct gdt_ccb *ccb = xccb;
 
        GDT_DPRINTF(GDT_D_QUEUE, ("gdt_free_ccb(%p, %p) ", sc, ccb));
 
-       s = splbio();
-
+       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);
-
-       splx(s);
-}
-
-void
-gdt_enqueue_ccb(struct gdt_softc *sc, struct gdt_ccb *ccb)
-{
-       GDT_DPRINTF(GDT_D_QUEUE, ("gdt_enqueue_ccb(%p, %p) ", sc, ccb));
-
-       timeout_set(&ccb->gc_xs->stimeout, gdt_timeout, ccb);
-       TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, gc_chain);
-       gdt_start_ccbs(sc);
-}
-
-void
-gdt_start_ccbs(struct gdt_softc *sc)
-{
-       struct gdt_ccb *ccb;
-       struct scsi_xfer *xs;
-
-       GDT_DPRINTF(GDT_D_QUEUE, ("gdt_start_ccbs(%p) ", sc));
-
-       while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) {
-
-               xs = ccb->gc_xs;
-               if (ccb->gc_flags & GDT_GCF_WATCHDOG)
-                       timeout_del(&xs->stimeout);
-
-               if (gdt_exec_ccb(ccb) == 0) {
-                       ccb->gc_flags |= GDT_GCF_WATCHDOG;
-                       timeout_set(&ccb->gc_xs->stimeout, gdt_watchdog, ccb);
-                       timeout_add_msec(&xs->stimeout, GDT_WATCH_TIMEOUT);
-                       break;
-               }
-               TAILQ_REMOVE(&sc->sc_ccbq, ccb, gc_chain);
-
-               if ((xs->flags & SCSI_POLL) == 0) {
-                       timeout_set(&ccb->gc_xs->stimeout, gdt_timeout, ccb);
-                       timeout_add_msec(&xs->stimeout, ccb->gc_timeout);
-               }
-       }
-}
-
-void
-gdt_chain(struct gdt_softc *sc)
-{
-       GDT_DPRINTF(GDT_D_INTR, ("gdt_chain(%p) ", sc));
-
-       if (LIST_FIRST(&sc->sc_queue))
-               gdt_scsi_cmd(LIST_FIRST(&sc->sc_queue));
+       mtx_leave(&sc->sc_ccb_mtx);
 }
 
 void
@@ -1388,8 +1178,6 @@ gdt_timeout(void *arg)
 {
        struct gdt_ccb *ccb = arg;
        struct scsi_link *link = ccb->gc_xs->sc_link;
-       struct gdt_softc *sc = link->adapter_softc;
-       int s;
 
        sc_print_addr(link);
        printf("timed out\n");
@@ -1397,22 +1185,17 @@ gdt_timeout(void *arg)
        /* XXX Test for multiple timeouts */
 
        ccb->gc_xs->error = XS_TIMEOUT;
-       s = splbio();
-       gdt_enqueue_ccb(sc, ccb);
-       splx(s);
+       scsi_done(ccb->gc_xs);
 }
 
 void
 gdt_watchdog(void *arg)
 {
        struct gdt_ccb *ccb = arg;
-       struct scsi_link *link = ccb->gc_xs->sc_link;
-       struct gdt_softc *sc = link->adapter_softc;
        int s;
 
        s = splbio();
        ccb->gc_flags &= ~GDT_GCF_WATCHDOG;
-       gdt_start_ccbs(sc);
        splx(s);
 }
 
@@ -1514,10 +1297,8 @@ gdt_ioctl(struct device *dev, u_long cmd
 
                ucmd = (gdt_ucmd_t *)addr;
                s = splbio();
-               TAILQ_INSERT_TAIL(&sc->sc_ucmdq, ucmd, links);
                ucmd->complete_flag = FALSE;
                splx(s);
-               gdt_chain(sc);
                if (!ucmd->complete_flag)
                        (void)tsleep((void *)ucmd, PCATCH | PRIBIO, "gdtucw",
                            0);
Index: ic/gdtvar.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/gdtvar.h,v
retrieving revision 1.17
diff -u -p -r1.17 gdtvar.h
--- ic/gdtvar.h 12 Aug 2009 17:51:33 -0000      1.17
+++ ic/gdtvar.h 27 Sep 2010 09:32:51 -0000
@@ -85,7 +85,6 @@ typedef struct gdt_ucmd {
        } u;
        u_int8_t data[GDT_SCRATCH_SZ];
        int     complete_flag;
-       TAILQ_ENTRY(gdt_ucmd) links;
 } gdt_ucmd_t;
 
 #define GDT_IOCTL_DRVERS _IOWR('B', 34, int)   /* get driver version */
@@ -293,10 +292,10 @@ struct gdt_softc {
        u_int16_t sc_ic_all_size;
 
        struct gdt_ccb sc_ccbs[GDT_MAXCMDS];
-       TAILQ_HEAD(, gdt_ccb) sc_free_ccb, sc_ccbq;
-       TAILQ_HEAD(, gdt_ucmd) sc_ucmdq;
-       LIST_HEAD(, scsi_xfer) sc_queue;
-       struct scsi_xfer *sc_queuelast;
+       TAILQ_HEAD(, gdt_ccb) sc_free_ccb;
+
+       struct mutex            sc_ccb_mtx;
+       struct scsi_iopool      sc_iopool;
 
        int     sc_ndevs;

Reply via email to