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;