On Sat, Oct 02, 2010 at 05:28:10PM -0400, Kenneth R Westerback wrote: > On Fri, Sep 24, 2010 at 03:55:50AM -0400, Kenneth R Westerback wrote: > > Here is a pass over the less well-known drivers that appeared to be simple > > to move to the scsi future - iopools: > > > > Index: arch/hp300/dev/mb89352.c > > Index: arch/hp300/dev/mb89352var.h > > Index: arch/luna88k/dev/mb89352.c > > Index: arch/luna88k/dev/mb89352var.h > > Index: arch/macppc/dev/mesh.c > > Index: dev/eisa/aha1742.c > > Index: dev/ic/adv.c > > Index: dev/ic/advlib.h > > Index: dev/ic/adw.c > > Index: dev/ic/adwlib.h > > Index: dev/ic/aic6360.c > > Index: dev/ic/aic6360var.h > > Index: dev/ic/bha.c > > Index: dev/ic/bhavar.h > > Index: dev/ic/iha.c > > Index: dev/ic/iha.h > > Index: dev/ic/oosiop.c > > Index: dev/ic/oosiopvar.h > > Index: dev/ic/uha.c > > Index: dev/ic/uhavar.h > > Index: dev/isa/aha.c > > Index: dev/isa/seagate.c > > Index: dev/isa/wds.c > > Index: dev/sdmmc/sdmmc_scsi.c > > > > Unless someone speaks up quickly claiming to have any of these in > > use I will commit and deal with reported problems. The ones in > > i386 GENERIC at least compile. > > > > .... Ken > > Sigh. And now with the forgotten luna88k bit. > > .... Ken
Sans committed bits. Tweak to sdmmc. sdmmc(4) testing especially sought as some issues with performance changes and boot delays have been reported. .... Ken Index: sys/arch/hp300/dev/mb89352.c =================================================================== RCS file: /cvs/src/sys/arch/hp300/dev/mb89352.c,v retrieving revision 1.25 diff -u -p -r1.25 mb89352.c --- sys/arch/hp300/dev/mb89352.c 28 Jun 2010 18:31:01 -0000 1.25 +++ sys/arch/hp300/dev/mb89352.c 30 Sep 2010 00:16:06 -0000 @@ -143,8 +143,8 @@ void spc_setsync(struct spc_softc *, str void spc_select (struct spc_softc *, struct spc_acb *); void spc_timeout (void *); void spc_scsi_reset (struct spc_softc *); -void spc_free_acb (struct spc_softc *, struct spc_acb *, int); -struct spc_acb* spc_get_acb(struct spc_softc *, int); +void spc_acb_free (void *, void *); +void *spc_acb_alloc(void *); int spc_reselect (struct spc_softc *, int); void spc_sense (struct spc_softc *, struct spc_acb *); void spc_msgin (struct spc_softc *); @@ -276,6 +276,9 @@ spc_init(struct spc_softc *sc) TAILQ_INIT(&sc->ready_list); TAILQ_INIT(&sc->nexus_list); TAILQ_INIT(&sc->free_list); + mtx_init(&sc->sc_acb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, spc_acb_alloc, + spc_acb_free); sc->sc_nexus = NULL; acb = sc->sc_acb; bzero(acb, sizeof(sc->sc_acb)); @@ -322,44 +325,36 @@ spc_init(struct spc_softc *sc) } void -spc_free_acb(struct spc_softc *sc, struct spc_acb *acb, int flags) +spc_acb_free(void *xsc, void *xacb) { - int s; + struct spc_softc *sc = xsc; + struct spc_acb *acb = xacb; - SPC_TRACE(("spc_free_acb ")); - s = splbio(); + SPC_TRACE(("spc_acb_free ")); acb->flags = 0; - TAILQ_INSERT_HEAD(&sc->free_list, acb, chain); - - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(acb, chain) == NULL) - wakeup(&sc->free_list); - splx(s); + mtx_enter(&sc->sc_acb_mtx); + TAILQ_INSERT_HEAD(&sc->free_list, acb, chain); + mtx_leave(&sc->sc_acb_mtx); } -struct spc_acb * -spc_get_acb(struct spc_softc *sc, int flags) +void * +spc_acb_alloc(void *xsc) { + struct spc_softc *sc = xsc; struct spc_acb *acb; - int s; - SPC_TRACE(("spc_get_acb ")); - s = splbio(); + SPC_TRACE(("spc_acb_alloc ")); - while ((acb = TAILQ_FIRST(&sc->free_list)) == NULL && - (flags & SCSI_NOSLEEP) == 0) - tsleep(&sc->free_list, PRIBIO, "spcacb", 0); + mtx_enter(&sc->sc_acb_mtx); + acb = TAILQ_FIRST(&sc->free_list); if (acb) { TAILQ_REMOVE(&sc->free_list, acb, chain); acb->flags |= ACB_ALLOC; } + mtx_leave(&sc->sc_acb_mtx); - splx(s); return acb; } @@ -402,11 +397,7 @@ spc_scsi_cmd(struct scsi_xfer *xs) sc_link->target)); flags = xs->flags; - if ((acb = spc_get_acb(sc, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - return; - } + acb = xs->io; /* Initialize acb */ acb->xs = xs; @@ -768,7 +759,6 @@ spc_done(struct spc_softc *sc, struct sp } else spc_dequeue(sc, acb); - spc_free_acb(sc, acb, xs->flags); ti->cmds++; scsi_done(xs); } Index: sys/arch/hp300/dev/mb89352var.h =================================================================== RCS file: /cvs/src/sys/arch/hp300/dev/mb89352var.h,v retrieving revision 1.6 diff -u -p -r1.6 mb89352var.h --- sys/arch/hp300/dev/mb89352var.h 4 Apr 2010 17:40:14 -0000 1.6 +++ sys/arch/hp300/dev/mb89352var.h 24 Sep 2010 03:15:58 -0000 @@ -122,6 +122,8 @@ struct spc_softc { struct spc_acb *sc_nexus; /* current command */ struct spc_acb sc_acb[8]; struct spc_tinfo sc_tinfo[8]; + struct mutex sc_acb_mtx; + struct scsi_iopool sc_iopool; /* Data about the current nexus (updated for every cmd switch) */ u_char *sc_dp; /* Current data pointer */ Index: sys/arch/luna88k/dev/mb89352.c =================================================================== RCS file: /cvs/src/sys/arch/luna88k/dev/mb89352.c,v retrieving revision 1.15 diff -u -p -r1.15 mb89352.c --- sys/arch/luna88k/dev/mb89352.c 28 Jun 2010 18:31:01 -0000 1.15 +++ sys/arch/luna88k/dev/mb89352.c 2 Oct 2010 21:19:49 -0000 @@ -157,8 +157,8 @@ void spc_select (struct spc_softc *, str void spc_timeout (void *); void spc_scsi_reset (struct spc_softc *); void spc_reset (struct spc_softc *); -void spc_free_acb (struct spc_softc *, struct spc_acb *, int); -struct spc_acb* spc_get_acb(struct spc_softc *, int); +void spc_acb_free (void *, void *); +void *spc_acb_alloc (void *); int spc_reselect (struct spc_softc *, int); void spc_sense (struct spc_softc *, struct spc_acb *); void spc_msgin (struct spc_softc *); @@ -215,6 +215,7 @@ spc_attach(sc, adapter) sc->sc_link.adapter_target = sc->sc_initiator; sc->sc_link.adapter = adapter; sc->sc_link.openings = 2; + sc->sc_link.pool = &sc->sc_iopool; bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_link; @@ -297,6 +298,8 @@ spc_init(sc) TAILQ_INIT(&sc->ready_list); TAILQ_INIT(&sc->nexus_list); TAILQ_INIT(&sc->free_list); + mtx_init(&sc->sc_acb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, spc_acb_alloc, spc_acb_free); sc->sc_nexus = NULL; acb = sc->sc_acb; bzero(acb, sizeof(sc->sc_acb)); @@ -346,49 +349,37 @@ spc_init(sc) } void -spc_free_acb(sc, acb, flags) - struct spc_softc *sc; - struct spc_acb *acb; - int flags; +spc_acb_free(xsc, xacb) + void *xsc, *xacb; { - int s; + struct spc_softc *sc = xsc; + struct spc_acb *acb = xacb; - SPC_TRACE(("spc_free_acb ")); - s = splbio(); + SPC_TRACE(("spc_acb_free ")); acb->flags = 0; + mtx_enter(&sc->sc_acb_mtx); TAILQ_INSERT_HEAD(&sc->free_list, acb, chain); - - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(acb, chain) == NULL) - wakeup(&sc->free_list); - - splx(s); + mtx_leave(&sc->sc_acb_mtx); } -struct spc_acb * -spc_get_acb(sc, flags) - struct spc_softc *sc; - int flags; +void * +spc_acb_alloc(xsc) + void *xsc; { + struct spc_softc *sc = xsc; struct spc_acb *acb; - int s; - SPC_TRACE(("spc_get_acb ")); - s = splbio(); + SPC_TRACE(("spc_acb_alloc ")); - while ((acb = TAILQ_FIRST(&sc->free_list)) == NULL && - (flags & SCSI_NOSLEEP) == 0) - tsleep(&sc->free_list, PRIBIO, "spcacb", 0); + mtx_enter(&sc->sc_acb_mtx); + acb = TAILQ_FIRST(&sc->free_list); if (acb) { TAILQ_REMOVE(&sc->free_list, acb, chain); acb->flags |= ACB_ALLOC; } + mtx_leave(&sc->sc_acb_mtx); - splx(s); return acb; } @@ -432,11 +423,7 @@ spc_scsi_cmd(xs) sc_link->target)); flags = xs->flags; - if ((acb = spc_get_acb(sc, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - return; - } + acb = xs->io; /* Initialize acb */ acb->xs = xs; @@ -818,7 +805,6 @@ spc_done(sc, acb) } else spc_dequeue(sc, acb); - spc_free_acb(sc, acb, xs->flags); ti->cmds++; scsi_done(xs); } Index: sys/arch/luna88k/dev/mb89352var.h =================================================================== RCS file: /cvs/src/sys/arch/luna88k/dev/mb89352var.h,v retrieving revision 1.2 diff -u -p -r1.2 mb89352var.h --- sys/arch/luna88k/dev/mb89352var.h 23 Mar 2010 01:57:19 -0000 1.2 +++ sys/arch/luna88k/dev/mb89352var.h 24 Sep 2010 03:14:26 -0000 @@ -123,6 +123,8 @@ struct spc_softc { struct spc_acb *sc_nexus; /* current command */ struct spc_acb sc_acb[8]; struct spc_tinfo sc_tinfo[8]; + struct mutex sc_acb_mtx; + struct scsi_iopool sc_iopool; /* Data about the current nexus (updated for every cmd switch) */ u_char *sc_dp; /* Current data pointer */ Index: sys/arch/macppc/dev/mesh.c =================================================================== RCS file: /cvs/src/sys/arch/macppc/dev/mesh.c,v retrieving revision 1.28 diff -u -p -r1.28 mesh.c --- sys/arch/macppc/dev/mesh.c 1 Jul 2010 03:20:38 -0000 1.28 +++ sys/arch/macppc/dev/mesh.c 30 Sep 2010 00:17:49 -0000 @@ -205,6 +205,9 @@ struct mesh_softc { struct mesh_scb sc_scb[16]; struct timeout sc_tmo; + + struct mutex sc_scb_mtx; + struct scsi_iopool sc_iopool; }; /* mesh_msgout() values */ @@ -233,7 +236,8 @@ void mesh_reset(struct mesh_softc *); int mesh_stp(struct mesh_softc *, int); void mesh_setsync(struct mesh_softc *, struct mesh_tinfo *); struct mesh_scb *mesh_get_scb(struct mesh_softc *); -void mesh_free_scb(struct mesh_softc *, struct mesh_scb *); +void *mesh_scb_alloc(void *); +void mesh_scb_free(void *, void *); void mesh_scsi_cmd(struct scsi_xfer *); void mesh_sched(struct mesh_softc *); int mesh_poll(struct scsi_xfer *); @@ -329,6 +333,8 @@ mesh_attach(struct device *parent, struc TAILQ_INIT(&sc->free_scb); TAILQ_INIT(&sc->ready_scb); + mtx_init(&sc->sc_scb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, mesh_scb_alloc, mesh_scb_free); for (i = 0; i < sizeof(sc->sc_scb)/sizeof(sc->sc_scb[0]); i++) TAILQ_INSERT_TAIL(&sc->free_scb, &sc->sc_scb[i], chain); @@ -350,6 +356,7 @@ mesh_attach(struct device *parent, struc sc->sc_link.adapter_target = sc->sc_id; sc->sc_link.adapter = &mesh_switch; sc->sc_link.openings = 2; + sc->sc_link.pool = &sc->sc_iopool; bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_link; @@ -1005,22 +1012,30 @@ mesh_setsync(struct mesh_softc *sc, stru mesh_set_reg(sc, MESH_SYNC_PARAM, (offset << 4) | v); } -struct mesh_scb * -mesh_get_scb(struct mesh_softc *sc) +void * +mesh_scb_alloc(void *xsc) { + struct mesh_softc *sc = xsc; struct mesh_scb *scb; + mtx_enter(&sc->sc_scb_mtx); scb = TAILQ_FIRST(&sc->free_scb); if (scb) TAILQ_REMOVE(&sc->free_scb, scb, chain); + mtx_leave(&sc->sc_scb_mtx); return scb; } void -mesh_free_scb(struct mesh_softc *sc, struct mesh_scb *scb) +mesh_scb_free(void *xsc, void *xscb) { + struct mesh_softc *sc = xsc; + struct mesh_scb *scb = xscb; + + mtx_enter(&sc->sc_scb_mtx); TAILQ_INSERT_TAIL(&sc->free_scb, scb, chain); + mtx_leave(&sc->sc_scb_mtx); } void @@ -1033,15 +1048,8 @@ mesh_scsi_cmd(struct scsi_xfer *xs) int s; flags = xs->flags; - s = splbio(); - scb = mesh_get_scb(sc); - if (scb == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - splx(s); - return; - } - splx(s); + scb = xs->io; + DPRINTF("cmdlen: %d\n", xs->cmdlen); scb->xs = xs; scb->flags = 0; @@ -1139,7 +1147,6 @@ mesh_done(struct mesh_softc *sc, struct mesh_sched(sc); scsi_done(xs); - mesh_free_scb(sc, scb); } void Index: sys/dev/eisa/aha1742.c =================================================================== RCS file: /cvs/src/sys/dev/eisa/aha1742.c,v retrieving revision 1.42 diff -u -p -r1.42 aha1742.c --- sys/dev/eisa/aha1742.c 7 Aug 2010 03:50:01 -0000 1.42 +++ sys/dev/eisa/aha1742.c 24 Sep 2010 08:08:30 -0000 @@ -266,12 +266,14 @@ struct ahb_softc { int sc_irq; void *sc_ih; - struct ahb_ecb *immed_ecb; /* an outstanding immediete command */ + struct ahb_ecb *immed_ecb; /* an outstanding immediate command */ struct ahb_ecb *ecbhash[ECB_HASH_SIZE]; TAILQ_HEAD(, ahb_ecb) free_ecb; int numecbs; int ahb_scsi_dev; /* our scsi id */ struct scsi_link sc_link; + struct mutex sc_ecb_mtx; + struct scsi_iopool sc_iopool; }; void ahb_send_mbox(struct ahb_softc *, int, struct ahb_ecb *); @@ -279,8 +281,8 @@ int ahb_poll(struct ahb_softc *, struct void ahb_send_immed(struct ahb_softc *, int, u_long); int ahbintr(void *); void ahb_done(struct ahb_softc *, struct ahb_ecb *); -void ahb_free_ecb(struct ahb_softc *, struct ahb_ecb *, int); -struct ahb_ecb *ahb_get_ecb(struct ahb_softc *, int); +void ahb_ecb_free(void *, void *); +void *ahb_ecb_alloc(void *); struct ahb_ecb *ahb_ecb_phys_kv(struct ahb_softc *, physaddr); int ahb_find(bus_space_tag_t, bus_space_handle_t, struct ahb_softc *); void ahb_init(struct ahb_softc *); @@ -484,6 +486,8 @@ ahbattach(parent, self, aux) ahb_init(sc); TAILQ_INIT(&sc->free_ecb); + mtx_init(&sc->sc_ecb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, ahb_ecb_alloc, ahb_ecb_free); /* * fill in the prototype scsi_link. @@ -492,6 +496,7 @@ ahbattach(parent, self, aux) sc->sc_link.adapter_target = sc->ahb_scsi_dev; sc->sc_link.adapter = &ahb_switch; sc->sc_link.openings = 2; + sc->sc_link.pool = &sc->sc_iopool; if (!strcmp(ea->ea_idstring, "ADP0000")) model = EISA_PRODUCT_ADP0000; @@ -586,7 +591,7 @@ ahbintr(arg) ecb->flags |= ECB_IMMED_FAIL; case AHB_IMMED_OK: ecb = sc->immed_ecb; - sc->immed_ecb = 0; + sc->immed_ecb = NULL; break; default: @@ -674,35 +679,24 @@ ahb_done(sc, ecb) xs->resid = 0; } done: - ahb_free_ecb(sc, ecb, xs->flags); scsi_done(xs); } /* - * A ecb (and hence a mbx-out is put onto the - * free list. + * A ecb (and hence a mbx-out) is put onto the free list. */ void -ahb_free_ecb(sc, ecb, flags) - struct ahb_softc *sc; - struct ahb_ecb *ecb; - int flags; +ahb_ecb_free(xsc, xecb) + void *xsc, *xecb; { - int s; - - s = splbio(); + struct ahb_softc *sc = xsc; + struct ahb_ecb *ecb = xecb; ecb->flags = ECB_FREE; - TAILQ_INSERT_HEAD(&sc->free_ecb, ecb, chain); - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(ecb, chain) == NULL) - wakeup(&sc->free_ecb); - - splx(s); + mtx_enter(&sc->sc_ecb_mtx); + TAILQ_INSERT_HEAD(&sc->free_ecb, ecb, chain); + mtx_leave(&sc->sc_ecb_mtx); } static inline void ahb_init_ecb(struct ahb_softc *, struct ahb_ecb *); @@ -737,53 +731,23 @@ ahb_reset_ecb(sc, ecb) /* * Get a free ecb - * - * If there are none, see if we can allocate a new one. If so, put it in the - * hash table too otherwise either return an error or sleep. */ -struct ahb_ecb * -ahb_get_ecb(sc, flags) - struct ahb_softc *sc; - int flags; +void * +ahb_ecb_alloc(xsc) + void *xsc; { + struct ahb_softc *sc = xsc; struct ahb_ecb *ecb; - int s; - - s = splbio(); - /* - * If we can and have to, sleep waiting for one to come free - * but only if we can't allocate a new one. - */ - for (;;) { - ecb = TAILQ_FIRST(&sc->free_ecb); - if (ecb) { - TAILQ_REMOVE(&sc->free_ecb, ecb, chain); - break; - } - if (sc->numecbs < AHB_ECB_MAX) { - ecb = (struct ahb_ecb *) malloc(sizeof(struct ahb_ecb), - M_TEMP, M_NOWAIT); - if (ecb) { - ahb_init_ecb(sc, ecb); - sc->numecbs++; - } else { - printf("%s: can't malloc ecb\n", - sc->sc_dev.dv_xname); - goto out; - } - break; - } - if ((flags & SCSI_NOSLEEP) != 0) - goto out; - tsleep(&sc->free_ecb, PRIBIO, "ahbecb", 0); + mtx_enter(&sc->sc_ecb_mtx); + ecb = TAILQ_FIRST(&sc->free_ecb); + if (ecb) { + TAILQ_REMOVE(&sc->free_ecb, ecb, chain); + ahb_reset_ecb(sc, ecb); + ecb->flags = ECB_ACTIVE; } + mtx_leave(&sc->sc_ecb_mtx); - ahb_reset_ecb(sc, ecb); - ecb->flags = ECB_ACTIVE; - -out: - splx(s); return ecb; } @@ -941,11 +905,7 @@ ahb_scsi_cmd(xs) * then we can't allow it to sleep */ flags = xs->flags; - if ((ecb = ahb_get_ecb(sc, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - return; - } + ecb = xs->io; ecb->xs = xs; timeout_set(&ecb->xs->stimeout, ahb_timeout, ecb); @@ -958,7 +918,7 @@ ahb_scsi_cmd(xs) if (flags & SCSI_RESET) { ecb->flags |= ECB_IMMED; if (sc->immed_ecb) { - xs->error = XS_NO_CCB; + xs->error = XS_BUSY; scsi_done(xs); return; } @@ -1062,7 +1022,6 @@ ahb_scsi_cmd(xs) printf("%s: ahb_scsi_cmd, more than %d dma segs\n", sc->sc_dev.dv_xname, AHB_NSEG); xs->error = XS_DRIVER_STUFFUP; - ahb_free_ecb(sc, ecb, flags); scsi_done(xs); return; } Index: sys/dev/ic/adv.c =================================================================== RCS file: /cvs/src/sys/dev/ic/adv.c,v retrieving revision 1.33 diff -u -p -r1.33 adv.c --- sys/dev/ic/adv.c 7 Aug 2010 03:50:01 -0000 1.33 +++ sys/dev/ic/adv.c 23 Sep 2010 13:53:16 -0000 @@ -58,10 +58,10 @@ static int adv_alloc_ccbs(ASC_SOFTC *); static int adv_create_ccbs(ASC_SOFTC *, ADV_CCB *, int); -static void adv_free_ccb(ASC_SOFTC *, ADV_CCB *); +void adv_ccb_free(void *, void *); static void adv_reset_ccb(ADV_CCB *); static int adv_init_ccb(ASC_SOFTC *, ADV_CCB *); -static ADV_CCB *adv_get_ccb(ASC_SOFTC *, int); +void *adv_ccb_alloc(void *); static void adv_queue_ccb(ASC_SOFTC *, ADV_CCB *); static void adv_start_ccbs(ASC_SOFTC *); @@ -178,26 +178,18 @@ adv_create_ccbs(sc, ccbstore, count) /* * A ccb is put onto the free list. */ -static void -adv_free_ccb(sc, ccb) - ASC_SOFTC *sc; - ADV_CCB *ccb; +void +adv_ccb_free(xsc, xccb) + void *xsc, *xccb; { - int s; - - s = splbio(); + ASC_SOFTC *sc = xsc; + ADV_CCB *ccb = xccb; adv_reset_ccb(ccb); - TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); - - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(ccb, chain) == NULL) - wakeup(&sc->sc_free_ccb); - splx(s); + mtx_enter(&sc->sc_ccb_mtx); + TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); + mtx_leave(&sc->sc_ccb_mtx); } @@ -236,43 +228,25 @@ adv_init_ccb(sc, ccb) /* * Get a free ccb - * - * If there are none, see if we can allocate a new one */ -static ADV_CCB * -adv_get_ccb(sc, flags) - ASC_SOFTC *sc; - int flags; -{ - ADV_CCB *ccb = 0; - int s; - - s = splbio(); - - /* - * If we can and have to, sleep waiting for one to come free - * but only if we can't allocate a new one. - */ - for (;;) { - ccb = TAILQ_FIRST(&sc->sc_free_ccb); - if (ccb) { - TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); - break; - } - if ((flags & SCSI_NOSLEEP) != 0) - goto out; - - tsleep(&sc->sc_free_ccb, PRIBIO, "advccb", 0); +void * +adv_ccb_alloc(xsc) + void *xsc; +{ + ASC_SOFTC *sc = xsc; + ADV_CCB *ccb; + + mtx_enter(&sc->sc_ccb_mtx); + ccb = TAILQ_FIRST(&sc->sc_free_ccb); + if (ccb) { + TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); + ccb->flags |= CCB_ALLOC; } + mtx_leave(&sc->sc_ccb_mtx); - ccb->flags |= CCB_ALLOC; - -out: - splx(s); return (ccb); } - /* * Queue a CCB to be sent to the controller, and send it if possible. */ @@ -506,6 +480,11 @@ adv_attach(sc) sc->sc_dev.dv_xname); } + TAILQ_INIT(&sc->sc_free_ccb); + TAILQ_INIT(&sc->sc_waiting_ccb); + + mtx_init(&sc->sc_ccb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, adv_ccb_alloc, adv_ccb_free); /* * fill in the prototype scsi_link. @@ -514,13 +493,9 @@ adv_attach(sc) sc->sc_link.adapter_target = sc->chip_scsi_id; sc->sc_link.adapter = &adv_switch; sc->sc_link.openings = 4; + sc->sc_link.pool = &sc->sc_iopool; sc->sc_link.adapter_buswidth = 7; - - TAILQ_INIT(&sc->sc_free_ccb); - TAILQ_INIT(&sc->sc_waiting_ccb); - - /* * Allocate the Control Blocks. */ @@ -579,13 +554,7 @@ adv_scsi_cmd(xs) */ flags = xs->flags; - if ((ccb = adv_get_ccb(sc, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - splx(s); - return; - } - splx(s); /* done playing with the queue */ + ccb = xs->io; ccb->xs = xs; ccb->timeout = xs->timeout; @@ -643,7 +612,6 @@ adv_scsi_cmd(xs) } xs->error = XS_DRIVER_STUFFUP; - adv_free_ccb(sc, ccb); scsi_done(xs); return; } @@ -914,7 +882,5 @@ adv_narrow_isr_callback(sc, qdonep) break; } - - adv_free_ccb(sc, ccb); scsi_done(xs); } Index: sys/dev/ic/advlib.h =================================================================== RCS file: /cvs/src/sys/dev/ic/advlib.h,v retrieving revision 1.10 diff -u -p -r1.10 advlib.h --- sys/dev/ic/advlib.h 26 Nov 2008 16:39:31 -0000 1.10 +++ sys/dev/ic/advlib.h 23 Sep 2010 08:07:28 -0000 @@ -835,6 +835,8 @@ typedef struct asc_softc struct adv_control *sc_control; /* control structures */ TAILQ_HEAD(, adv_ccb) sc_free_ccb, sc_waiting_ccb; struct scsi_link sc_link; /* prototype for devs */ + struct mutex sc_ccb_mtx; + struct scsi_iopool sc_iopool; u_int8_t *overrun_buf; Index: sys/dev/ic/aic6360.c =================================================================== RCS file: /cvs/src/sys/dev/ic/aic6360.c,v retrieving revision 1.25 diff -u -p -r1.25 aic6360.c --- sys/dev/ic/aic6360.c 28 Jun 2010 18:31:02 -0000 1.25 +++ sys/dev/ic/aic6360.c 23 Sep 2010 13:50:05 -0000 @@ -166,8 +166,8 @@ void aic_timeout(void *); void aic_sched(struct aic_softc *); void aic_scsi_reset(struct aic_softc *); void aic_reset(struct aic_softc *); -void aic_free_acb(struct aic_softc *, struct aic_acb *, int); -struct aic_acb* aic_get_acb(struct aic_softc *, int); +void aic_acb_free(void *, void *); +void *aic_acb_alloc(void *); int aic_reselect(struct aic_softc *, int); void aic_sense(struct aic_softc *, struct aic_acb *); void aic_msgin(struct aic_softc *); @@ -280,6 +280,7 @@ aicattach(struct aic_softc *sc) sc->sc_link.adapter_target = sc->sc_initiator; sc->sc_link.adapter = &aic_switch; sc->sc_link.openings = 2; + sc->sc_link.pool = &sc->sc_iopool; bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_link; @@ -381,6 +382,9 @@ aic_init(struct aic_softc *sc) TAILQ_INIT(&sc->ready_list); TAILQ_INIT(&sc->nexus_list); TAILQ_INIT(&sc->free_list); + mtx_init(&sc->sc_acb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, aic_acb_alloc, + aic_acb_free); sc->sc_nexus = NULL; acb = sc->sc_acb; bzero(acb, sizeof(sc->sc_acb)); @@ -429,45 +433,34 @@ aic_init(struct aic_softc *sc) } void -aic_free_acb(struct aic_softc *sc, struct aic_acb *acb, int flags) +aic_acb_free(void *xsc, void *xacb) { - int s; - - s = splbio(); + struct aic_softc *sc = xsc; + struct aic_acb *acb = xacb; + mtx_enter(&sc->sc_acb_mtx); acb->flags = 0; TAILQ_INSERT_HEAD(&sc->free_list, acb, chain); - - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(acb, chain) == NULL) - wakeup(&sc->free_list); - - splx(s); + mtx_leave(&sc->sc_acb_mtx); } -struct aic_acb * -aic_get_acb(struct aic_softc *sc, int flags) +void * +aic_acb_alloc(void *xsc) { + struct aic_softc *sc = xsc; struct aic_acb *acb; - int s; - - s = splbio(); - while ((acb = TAILQ_FIRST(&sc->free_list)) == NULL && - (flags & SCSI_NOSLEEP) == 0) - tsleep(&sc->free_list, PRIBIO, "aicacb", 0); + mtx_enter(&sc->sc_acb_mtx); + acb = TAILQ_FIRST(&sc->free_list); if (acb) { TAILQ_REMOVE(&sc->free_list, acb, chain); acb->flags |= ACB_ALLOC; } + mtx_leave(&sc->sc_acb_mtx); - splx(s); return acb; } - + /* * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS */ @@ -507,11 +500,7 @@ aic_scsi_cmd(struct scsi_xfer *xs) sc_link->target)); flags = xs->flags; - if ((acb = aic_get_acb(sc, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - return; - } + acb = xs->io; /* Initialize acb */ acb->xs = xs; @@ -856,7 +845,6 @@ aic_done(struct aic_softc *sc, struct ai } else aic_dequeue(sc, acb); - aic_free_acb(sc, acb, xs->flags); ti->cmds++; scsi_done(xs); } Index: sys/dev/ic/aic6360var.h =================================================================== RCS file: /cvs/src/sys/dev/ic/aic6360var.h,v retrieving revision 1.6 diff -u -p -r1.6 aic6360var.h --- sys/dev/ic/aic6360var.h 3 Jun 2006 01:51:54 -0000 1.6 +++ sys/dev/ic/aic6360var.h 23 Sep 2010 12:31:43 -0000 @@ -131,6 +131,9 @@ struct aic_softc { struct aic_acb sc_acb[8]; struct aic_tinfo sc_tinfo[8]; + struct mutex sc_acb_mtx; + struct scsi_iopool sc_iopool; + /* Data about the current nexus (updated for every cmd switch) */ u_char *sc_dp; /* Current data pointer */ size_t sc_dleft; /* Data bytes left to transfer */ Index: sys/dev/ic/bha.c =================================================================== RCS file: /cvs/src/sys/dev/ic/bha.c,v retrieving revision 1.26 diff -u -p -r1.26 bha.c --- sys/dev/ic/bha.c 7 Aug 2010 03:50:01 -0000 1.26 +++ sys/dev/ic/bha.c 23 Sep 2010 13:51:04 -0000 @@ -82,9 +82,9 @@ int bha_debug = 1; integrate void bha_finish_ccbs(struct bha_softc *); integrate void bha_reset_ccb(struct bha_softc *, struct bha_ccb *); -void bha_free_ccb(struct bha_softc *, struct bha_ccb *); +void bha_ccb_free(void *, void *); integrate int bha_init_ccb(struct bha_softc *, struct bha_ccb *); -struct bha_ccb *bha_get_ccb(struct bha_softc *, int); +void *bha_ccb_alloc(void *); struct bha_ccb *bha_ccb_phys_kv(struct bha_softc *, u_long); void bha_queue_ccb(struct bha_softc *, struct bha_ccb *); void bha_collect_mbo(struct bha_softc *); @@ -252,6 +252,12 @@ bha_attach(sc, bpd) struct scsibus_attach_args saa; int s; + TAILQ_INIT(&sc->sc_free_ccb); + TAILQ_INIT(&sc->sc_waiting_ccb); + + mtx_init(&sc->sc_ccb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, bha_ccb_alloc, bha_ccb_free); + /* * Fill in the adapter. */ @@ -265,9 +271,7 @@ bha_attach(sc, bpd) sc->sc_link.adapter_target = bpd->sc_scsi_dev; sc->sc_link.adapter = &sc->sc_adapter; sc->sc_link.openings = 4; - - TAILQ_INIT(&sc->sc_free_ccb); - TAILQ_INIT(&sc->sc_waiting_ccb); + sc->sc_link.pool = &sc->sc_iopool; s = splbio(); bha_inquire_setup_information(sc); @@ -459,25 +463,17 @@ bha_reset_ccb(sc, ccb) * A ccb is put onto the free list. */ void -bha_free_ccb(sc, ccb) - struct bha_softc *sc; - struct bha_ccb *ccb; +bha_ccb_free(xsc, xccb) + void *xsc, *xccb; { - int s; - - s = splbio(); + struct bha_softc *sc = xsc; + struct bha_ccb *ccb; bha_reset_ccb(sc, ccb); - TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(ccb, chain) == NULL) - wakeup(&sc->sc_free_ccb); - - splx(s); + mtx_enter(&sc->sc_ccb_mtx); + TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); + mtx_leave(&sc->sc_ccb_mtx); } integrate int @@ -541,39 +537,22 @@ bha_create_ccbs(sc, ccbstore, count) /* * Get a free ccb - * - * If there are none, see if we can allocate a new one. If so, put it in - * the hash table too otherwise either return an error or sleep. */ -struct bha_ccb * -bha_get_ccb(sc, flags) - struct bha_softc *sc; - int flags; +void * +bha_ccb_alloc(xsc) + void *xsc; { + struct bha_softc *sc = xsc; struct bha_ccb *ccb; - int s; - s = splbio(); - - /* - * If we can and have to, sleep waiting for one to come free - * but only if we can't allocate a new one. - */ - for (;;) { - ccb = TAILQ_FIRST(&sc->sc_free_ccb); - if (ccb) { - TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); - break; - } - if ((flags & SCSI_NOSLEEP) != 0) - goto out; - tsleep(&sc->sc_free_ccb, PRIBIO, "bhaccb", 0); + mtx_enter(&sc->sc_ccb_mtx); + ccb = TAILQ_FIRST(&sc->sc_free_ccb); + if (ccb) { + TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); + ccb->flags |= CCB_ALLOC; } + mtx_leave(&sc->sc_ccb_mtx); - ccb->flags |= CCB_ALLOC; - -out: - splx(s); return (ccb); } @@ -781,7 +760,6 @@ bha_done(sc, ccb) } else xs->resid = 0; } - bha_free_ccb(sc, ccb); scsi_done(xs); } @@ -1278,14 +1256,7 @@ bha_scsi_cmd(xs) * then we can't allow it to sleep */ flags = xs->flags; - if ((ccb = bha_get_ccb(sc, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - splx(s); - return; - } - - splx(s); /* done playing with the queue */ + ccb = xs->io; ccb->xs = xs; ccb->timeout = xs->timeout; @@ -1395,7 +1366,6 @@ bha_scsi_cmd(xs) bad: xs->error = XS_DRIVER_STUFFUP; - bha_free_ccb(sc, ccb); scsi_done(xs); } Index: sys/dev/ic/bhavar.h =================================================================== RCS file: /cvs/src/sys/dev/ic/bhavar.h,v retrieving revision 1.4 diff -u -p -r1.4 bhavar.h --- sys/dev/ic/bhavar.h 26 Nov 2008 16:38:00 -0000 1.4 +++ sys/dev/ic/bhavar.h 23 Sep 2010 10:54:54 -0000 @@ -84,6 +84,9 @@ struct bha_softc { struct scsi_link sc_link; /* prototype for devs */ struct scsi_adapter sc_adapter; + struct mutex sc_ccb_mtx; + struct scsi_iopool sc_iopool; + char sc_model[7]; char sc_firmware[6]; }; Index: sys/dev/ic/oosiop.c =================================================================== RCS file: /cvs/src/sys/dev/ic/oosiop.c,v retrieving revision 1.17 diff -u -p -r1.17 oosiop.c --- sys/dev/ic/oosiop.c 28 Jun 2010 18:31:02 -0000 1.17 +++ sys/dev/ic/oosiop.c 30 Sep 2010 00:18:31 -0000 @@ -90,6 +90,9 @@ void oosiop_setup(struct oosiop_softc *, void oosiop_poll(struct oosiop_softc *, struct oosiop_cb *); void oosiop_processintr(struct oosiop_softc *, u_int8_t); +void *oosiop_cb_alloc(void *); +void oosiop_cb_free(void *, void *); + /* Trap interrupt code for unexpected data I/O */ #define DATAIN_TRAP 0xdead0001 #define DATAOUT_TRAP 0xdead0002 @@ -135,6 +138,32 @@ struct scsi_adapter oosiop_adapter = { NULL }; +void * +oosiop_cb_alloc(void *xsc) +{ + struct oosiop_softc *sc = xsc; + struct oosiop_cb *cb; + + mtx_enter(&sc->sc_cb_mtx); + cb = TAILQ_FIRST(&sc->sc_free_cb); + if (cb) + TAILQ_REMOVE(&sc->sc_free_cb, cb, chain); + mtx_leave(&sc->sc_cb_mtx); + + return (cb); +} + +void +oosiop_cb_free(void *xsc, void *xcb) +{ + struct oosiop_softc *sc = xsc; + struct oosiop_cb *cb = xcb; + + mtx_enter(&sc->sc_cb_mtx); + TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain); + mtx_leave(&sc->sc_cb_mtx); +} + void oosiop_attach(struct oosiop_softc *sc) { @@ -715,8 +744,8 @@ oosiop_scsicmd(struct scsi_xfer *xs) sc = (struct oosiop_softc *)xs->sc_link->adapter_softc; s = splbio(); - cb = TAILQ_FIRST(&sc->sc_free_cb); - TAILQ_REMOVE(&sc->sc_free_cb, cb, chain); + + cb = xs->io; cb->xs = xs; cb->xsflags = xs->flags; @@ -735,10 +764,9 @@ oosiop_scsicmd(struct scsi_xfer *xs) if (err) { printf("%s: unable to load cmd DMA map: %d", sc->sc_dev.dv_xname, err); + splx(s); xs->error = XS_DRIVER_STUFFUP; scsi_done(xs); - TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain); - splx(s); return; } bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen, @@ -757,11 +785,10 @@ oosiop_scsicmd(struct scsi_xfer *xs) if (err) { printf("%s: unable to load data DMA map: %d", sc->sc_dev.dv_xname, err); - xs->error = XS_DRIVER_STUFFUP; bus_dmamap_unload(sc->sc_dmat, cb->cmddma); - scsi_done(xs); - TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain); splx(s); + xs->error = XS_DRIVER_STUFFUP; + scsi_done(xs); return; } bus_dmamap_sync(sc->sc_dmat, cb->datadma, @@ -937,7 +964,6 @@ oosiop_done(struct oosiop_softc *sc, str FREE: xs->resid = 0; scsi_done(xs); - TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain); if (cb == sc->sc_curcb) sc->sc_curcb = NULL; Index: sys/dev/ic/oosiopvar.h =================================================================== RCS file: /cvs/src/sys/dev/ic/oosiopvar.h,v retrieving revision 1.4 diff -u -p -r1.4 oosiopvar.h --- sys/dev/ic/oosiopvar.h 20 Apr 2010 20:21:56 -0000 1.4 +++ sys/dev/ic/oosiopvar.h 23 Sep 2010 08:51:16 -0000 @@ -139,6 +139,9 @@ struct oosiop_softc { TAILQ_HEAD(oosiop_cb_queue, oosiop_cb) sc_free_cb, sc_cbq; + struct mutex sc_cb_mtx; + struct scsi_iopool sc_iopool; + struct oosiop_cb *sc_curcb; /* current command */ struct oosiop_cb *sc_lastcb; /* last activated command */ Index: sys/dev/ic/uha.c =================================================================== RCS file: /cvs/src/sys/dev/ic/uha.c,v retrieving revision 1.21 diff -u -p -r1.21 uha.c --- sys/dev/ic/uha.c 7 Aug 2010 03:50:01 -0000 1.21 +++ sys/dev/ic/uha.c 23 Sep 2010 13:50:10 -0000 @@ -83,9 +83,9 @@ #define KVTOPHYS(x) vtophys((vaddr_t)x) integrate void uha_reset_mscp(struct uha_softc *, struct uha_mscp *); -void uha_free_mscp(struct uha_softc *, struct uha_mscp *); +void uha_mscp_free(void *, void *); integrate void uha_init_mscp(struct uha_softc *, struct uha_mscp *); -struct uha_mscp *uha_get_mscp(struct uha_softc *, int); +void *uha_mscp_alloc(void *); void uhaminphys(struct buf *, struct scsi_link *); void uha_scsi_cmd(struct scsi_xfer *); @@ -129,6 +129,9 @@ uha_attach(sc) (sc->init)(sc); SLIST_INIT(&sc->sc_free_mscp); + mtx_init(&sc->sc_mscp_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, uha_mscp_alloc, uha_mscp_free); + /* * fill in the prototype scsi_link. */ @@ -136,6 +139,7 @@ uha_attach(sc) sc->sc_link.adapter_target = sc->sc_scsi_dev; sc->sc_link.adapter = &uha_switch; sc->sc_link.openings = 2; + sc->sc_link.pool = &sc->sc_iopool; bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_link; @@ -159,25 +163,17 @@ uha_reset_mscp(sc, mscp) * A mscp (and hence a mbx-out) is put onto the free list. */ void -uha_free_mscp(sc, mscp) - struct uha_softc *sc; - struct uha_mscp *mscp; +uha_mscp_free(xsc, xmscp) + void *xsc, *xmscp; { - int s; - - s = splbio(); + struct uha_softc *sc = xmscp; + struct uha_mscp *mscp; uha_reset_mscp(sc, mscp); - SLIST_INSERT_HEAD(&sc->sc_free_mscp, mscp, chain); - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (SLIST_NEXT(mscp, chain) == NULL) - wakeup(&sc->sc_free_mscp); - - splx(s); + mtx_enter(&sc->sc_mscp_mtx); + SLIST_INSERT_HEAD(&sc->sc_free_mscp, mscp, chain); + mtx_leave(&sc->sc_mscp_mtx); } integrate void @@ -201,51 +197,22 @@ uha_init_mscp(sc, mscp) /* * Get a free mscp - * - * If there are none, see if we can allocate a new one. If so, put it in the - * hash table too otherwise either return an error or sleep. */ -struct uha_mscp * -uha_get_mscp(sc, flags) - struct uha_softc *sc; - int flags; +void * +uha_mscp_alloc(xsc) + void *xsc; { + struct uha_softc *sc = xsc; struct uha_mscp *mscp; - int s; - s = splbio(); - - /* - * If we can and have to, sleep waiting for one to come free - * but only if we can't allocate a new one - */ - for (;;) { - mscp = SLIST_FIRST(&sc->sc_free_mscp); - if (mscp) { - SLIST_REMOVE_HEAD(&sc->sc_free_mscp, chain); - break; - } - if (sc->sc_nummscps < UHA_MSCP_MAX) { - mscp = (struct uha_mscp *) malloc(sizeof(struct uha_mscp), - M_TEMP, M_NOWAIT); - if (!mscp) { - printf("%s: can't malloc mscp\n", - sc->sc_dev.dv_xname); - goto out; - } - uha_init_mscp(sc, mscp); - sc->sc_nummscps++; - break; - } - if ((flags & SCSI_NOSLEEP) != 0) - goto out; - tsleep(&sc->sc_free_mscp, PRIBIO, "uhamsc", 0); + mtx_enter(&sc->sc_mscp_mtx); + mscp = SLIST_FIRST(&sc->sc_free_mscp); + if (mscp) { + SLIST_REMOVE_HEAD(&sc->sc_free_mscp, chain); + mscp->flags |= MSCP_ALLOC; } + mtx_leave(&sc->sc_mscp_mtx); - mscp->flags |= MSCP_ALLOC; - -out: - splx(s); return (mscp); } @@ -319,7 +286,7 @@ uha_done(sc, mscp) } else xs->resid = 0; } - uha_free_mscp(sc, mscp); + scsi_done(xs); } @@ -355,11 +322,8 @@ uha_scsi_cmd(xs) * then we can't allow it to sleep */ flags = xs->flags; - if ((mscp = uha_get_mscp(sc, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - return; - } + mscp = xs->io; + mscp->xs = xs; mscp->timeout = xs->timeout; timeout_set(&xs->stimeout, uha_timeout, xs); @@ -485,7 +449,6 @@ uha_scsi_cmd(xs) bad: xs->error = XS_DRIVER_STUFFUP; scsi_done(xs); - uha_free_mscp(sc, mscp); return; } Index: sys/dev/ic/uhavar.h =================================================================== RCS file: /cvs/src/sys/dev/ic/uhavar.h,v retrieving revision 1.3 diff -u -p -r1.3 uhavar.h --- sys/dev/ic/uhavar.h 30 Jun 2010 19:06:16 -0000 1.3 +++ sys/dev/ic/uhavar.h 23 Sep 2010 11:08:45 -0000 @@ -50,6 +50,10 @@ struct uha_softc { struct uha_mscp *sc_mscphash[MSCP_HASH_SIZE]; SLIST_HEAD(, uha_mscp) sc_free_mscp; + + struct mutex sc_mscp_mtx; + struct scsi_iopool sc_iopool; + int sc_nummscps; int sc_scsi_dev; /* our scsi id */ struct scsi_link sc_link; Index: sys/dev/isa/aha.c =================================================================== RCS file: /cvs/src/sys/dev/isa/aha.c,v retrieving revision 1.73 diff -u -p -r1.73 aha.c --- sys/dev/isa/aha.c 7 Aug 2010 03:50:01 -0000 1.73 +++ sys/dev/isa/aha.c 24 Sep 2010 09:51:33 -0000 @@ -128,6 +128,9 @@ struct aha_softc { int sc_numccbs, sc_mbofull; int sc_scsi_dev; /* our scsi id */ struct scsi_link sc_link; + + struct mutex sc_ccb_mtx; + struct scsi_iopool sc_iopool; }; #ifdef AHADEBUG @@ -138,9 +141,9 @@ int aha_cmd(int, struct aha_softc *, int void aha_finish_ccbs(struct aha_softc *); int ahaintr(void *); void aha_reset_ccb(struct aha_softc *, struct aha_ccb *); -void aha_free_ccb(struct aha_softc *, struct aha_ccb *); +void aha_ccb_free(void *, void *); int aha_init_ccb(struct aha_softc *, struct aha_ccb *, int); -struct aha_ccb *aha_get_ccb(struct aha_softc *, int); +void *aha_ccb_alloc(void *); struct aha_ccb *aha_ccb_phys_kv(struct aha_softc *, u_long); void aha_queue_ccb(struct aha_softc *, struct aha_ccb *); void aha_collect_mbo(struct aha_softc *); @@ -384,6 +387,8 @@ ahaattach(parent, self, aux) aha_init(sc); TAILQ_INIT(&sc->sc_free_ccb); TAILQ_INIT(&sc->sc_waiting_ccb); + mtx_init(&sc->sc_ccb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, aha_ccb_alloc, aha_ccb_free); /* * fill in the prototype scsi_link. @@ -392,6 +397,7 @@ ahaattach(parent, self, aux) sc->sc_link.adapter_target = sc->sc_scsi_dev; sc->sc_link.adapter = &aha_switch; sc->sc_link.openings = 2; + sc->sc_link.pool = &sc->sc_iopool; bzero(&saa, sizeof(saa)); saa.saa_sc_link = &sc->sc_link; @@ -556,10 +562,11 @@ aha_reset_ccb(sc, ccb) * A ccb is put onto the free list. */ void -aha_free_ccb(sc, ccb) - struct aha_softc *sc; - struct aha_ccb *ccb; +aha_ccb_free(xsc, xccb) + void *xsc, *xccb; { + struct aha_softc *sc = xsc; + struct aha_ccb *ccb = xccb; int s, hashnum; struct aha_ccb **hashccb; @@ -583,14 +590,10 @@ aha_free_ccb(sc, ccb) } aha_reset_ccb(sc, ccb); - TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(ccb, chain) == NULL) - wakeup(&sc->sc_free_ccb); + mtx_enter(&sc->sc_ccb_mtx); + TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); + mtx_leave(&sc->sc_ccb_mtx); splx(s); } @@ -634,58 +637,35 @@ aha_init_ccb(sc, ccb, flags) * If there are none, see if we can allocate a new one. If so, put it in * the hash table too otherwise either return an error or sleep. */ -struct aha_ccb * -aha_get_ccb(sc, flags) - struct aha_softc *sc; - int flags; +void * +aha_ccb_alloc(xsc) + void *xsc; { + struct aha_softc *sc = xsc; struct aha_ccb *ccb; int hashnum, s; s = splbio(); - /* - * If we can and have to, sleep waiting for one to come free - * but only if we can't allocate a new one. - */ - for (;;) { - ccb = TAILQ_FIRST(&sc->sc_free_ccb); - if (ccb) { - TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); - break; - } - if (sc->sc_numccbs < AHA_CCB_MAX) { - ccb = malloc(sizeof *ccb, M_DEVBUF, - (flags & SCSI_NOSLEEP) ? M_NOWAIT : M_WAITOK); - if (ccb == NULL) { - printf("%s: can't malloc ccb\n", - sc->sc_dev.dv_xname); - goto out; - } - if (aha_init_ccb(sc, ccb, flags) == 0) { - sc->sc_numccbs++; - break; - } - free(ccb, M_DEVBUF); - ccb = NULL; + mtx_enter(&sc->sc_ccb_mtx); + ccb = TAILQ_FIRST(&sc->sc_free_ccb); + if (ccb) { + TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); + ccb->flags |= CCB_ALLOC; + if (bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmam, ccb, CCB_PHYS_SIZE, + NULL, BUS_DMA_NOWAIT) != 0) { + mtx_leave(&sc->sc_ccb_mtx); + aha_ccb_free(sc, ccb); + splx(s); + return (NULL); + } else { + hashnum = CCB_HASH(ccb->ccb_dmam->dm_segs[0].ds_addr); + ccb->nexthash = sc->sc_ccbhash[hashnum]; + sc->sc_ccbhash[hashnum] = ccb; } - if (flags & SCSI_NOSLEEP) - goto out; - tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0); } + mtx_leave(&sc->sc_ccb_mtx); - ccb->flags |= CCB_ALLOC; - - if (bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmam, ccb, CCB_PHYS_SIZE, - NULL, BUS_DMA_NOWAIT) != 0) { - aha_free_ccb(sc, ccb); - ccb = NULL; - } else { - hashnum = CCB_HASH(ccb->ccb_dmam->dm_segs[0].ds_addr); - ccb->nexthash = sc->sc_ccbhash[hashnum]; - sc->sc_ccbhash[hashnum] = ccb; - } -out: splx(s); return (ccb); } @@ -886,7 +866,6 @@ aha_done(sc, ccb) ccb->dmam->dm_mapsize, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->sc_dmat, ccb->dmam); } - aha_free_ccb(sc, ccb); scsi_done(xs); } @@ -1246,11 +1225,7 @@ aha_scsi_cmd(xs) * then we can't allow it to sleep */ flags = xs->flags; - if ((ccb = aha_get_ccb(sc, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - return; - } + ccb = xs->io; ccb->xs = xs; ccb->timeout = xs->timeout; @@ -1277,8 +1252,7 @@ aha_scsi_cmd(xs) */ if (bus_dmamap_load(sc->sc_dmat, ccb->dmam, xs->data, xs->datalen, NULL, BUS_DMA_NOWAIT) != 0) { - aha_free_ccb(sc, ccb); - xs->error = XS_NO_CCB; + xs->error = XS_BUSY; scsi_done(xs); return; } @@ -1338,7 +1312,6 @@ aha_scsi_cmd(xs) BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc->sc_dmat, ccb->dmam); } - aha_free_ccb(sc, ccb); scsi_done(xs); splx(s); return; Index: sys/dev/isa/seagate.c =================================================================== RCS file: /cvs/src/sys/dev/isa/seagate.c,v retrieving revision 1.36 diff -u -p -r1.36 seagate.c --- sys/dev/isa/seagate.c 28 Jun 2010 18:31:02 -0000 1.36 +++ sys/dev/isa/seagate.c 23 Sep 2010 23:57:56 -0000 @@ -202,6 +202,9 @@ struct sea_softc { int numscbs; /* number of scsi control blocks */ struct sea_scb scb[SCB_TABLE_SIZE]; + struct mutex sc_scb_mtx; + struct scsi_iopool sc_iopool; + int our_id; /* our scsi id */ u_char our_id_mask; volatile u_char busy[8]; /* index=target, bit=lun, Keep track of @@ -271,7 +274,7 @@ static const char *bases[] = { #define nbases (sizeof(bases) / sizeof(bases[0])) #endif -struct sea_scb *sea_get_scb(struct sea_softc *, int); +void *sea_scb_alloc(void *); int seaintr(void *); void sea_scsi_cmd(struct scsi_xfer *); int sea_poll(struct sea_softc *, struct scsi_xfer *, int); @@ -283,7 +286,7 @@ static void sea_main(void); static void sea_information_transfer(struct sea_softc *); void sea_timeout(void *); void sea_done(struct sea_softc *, struct sea_scb *); -void sea_free_scb(struct sea_softc *, struct sea_scb *, int); +void sea_scb_free(void *, void *); void sea_init(struct sea_softc *); void sea_send_scb(struct sea_softc *sea, struct sea_scb *scb); void sea_reselect(struct sea_softc *sea); @@ -427,6 +430,7 @@ seaattach(struct device *parent, struct sea->sc_link.adapter_target = sea->our_id; sea->sc_link.adapter = &sea_switch; sea->sc_link.openings = 1; + sea->sc_link.pool = &sea->sc_iopool; printf("\n"); @@ -508,6 +512,9 @@ sea_init(struct sea_softc *sea) TAILQ_INIT(&sea->ready_list); TAILQ_INIT(&sea->nexus_list); TAILQ_INIT(&sea->free_list); + mtx_init(&sea->sc_scb_mtx, IPL_BIO); + scsi_iopool_init(&sea->sc_iopool, sea, sea_scb_alloc, sea_scb_free); + for (i = 0; i < 8; i++) sea->busy[i] = 0x00; @@ -534,11 +541,7 @@ sea_scsi_cmd(struct scsi_xfer *xs) SC_DEBUG(sc_link, SDEV_DB2, ("sea_scsi_cmd\n")); flags = xs->flags; - if ((scb = sea_get_scb(sea, flags)) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - return; - } + scb = xs->io; scb->flags = SCB_ACTIVE; scb->xs = xs; timeout_set(&scb->xs->stimeout, sea_timeout, scb); @@ -590,42 +593,21 @@ sea_scsi_cmd(struct scsi_xfer *xs) } /* - * Get a free scb. If there are none, see if we can allocate a new one. If so, - * put it in the hash table too; otherwise return an error or sleep. + * Get a free scb. */ -struct sea_scb * -sea_get_scb(struct sea_softc *sea, int flags) +void * +sea_scb_alloc(void *xsea) { - int s; + struct sea_softc *sea = xsea; struct sea_scb *scb; - s = splbio(); - - /* - * If we can and have to, sleep waiting for one to come free - * but only if we can't allocate a new one. - */ - for (;;) { - scb = TAILQ_FIRST(&sea->free_list); - if (scb) { - TAILQ_REMOVE(&sea->free_list, scb, chain); - break; - } - if (sea->numscbs < SEA_SCB_MAX) { - scb = malloc(sizeof(*scb), M_TEMP, M_NOWAIT | M_ZERO); - if (scb) { - sea->numscbs++; - } else - printf("%s: can't malloc scb\n", - sea->sc_dev.dv_xname); - break; - } - if ((flags & SCSI_NOSLEEP) != 0) - break; - tsleep(&sea->free_list, PRIBIO, "seascb", 0); + mtx_enter(&sea->sc_scb_mtx); + scb = TAILQ_FIRST(&sea->free_list); + if (scb) { + TAILQ_REMOVE(&sea->free_list, scb, chain); } + mtx_leave(&sea->sc_scb_mtx); - splx(s); return scb; } @@ -749,23 +731,16 @@ loop: } void -sea_free_scb(struct sea_softc *sea, struct sea_scb *scb, int flags) +sea_scb_free(void *xsea, void *xscb) { - int s; - - s = splbio(); + struct sea_softc *sea = xsea; + struct sea_scb *scb = xscb; scb->flags = SCB_FREE; - TAILQ_INSERT_HEAD(&sea->free_list, scb, chain); - - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(scb, chain) == NULL) - wakeup((caddr_t)&sea->free_list); - splx(s); + mtx_enter(&sea->sc_scb_mtx); + TAILQ_INSERT_HEAD(&sea->free_list, scb, chain); + mtx_leave(&sea->sc_scb_mtx); } void @@ -1152,7 +1127,6 @@ sea_done(struct sea_softc *sea, struct s if (scb->flags & SCB_ERROR) xs->error = XS_DRIVER_STUFFUP; } - sea_free_scb(sea, scb, xs->flags); scsi_done(xs); } Index: sys/dev/isa/wds.c =================================================================== RCS file: /cvs/src/sys/dev/isa/wds.c,v retrieving revision 1.37 diff -u -p -r1.37 wds.c --- sys/dev/isa/wds.c 2 Jul 2010 02:29:45 -0000 1.37 +++ sys/dev/isa/wds.c 23 Sep 2010 23:35:52 -0000 @@ -120,6 +120,9 @@ struct wds_softc { int sc_numscbs, sc_mbofull; int sc_scsi_dev; struct scsi_link sc_link; /* prototype for subdevs */ + + struct mutex sc_scb_mtx; + struct scsi_iopool sc_iopool; }; /* Define the bounce buffer length... */ @@ -146,10 +149,10 @@ int wds_cmd(struct wds_softc *, u_ch integrate void wds_finish_scbs(struct wds_softc *); int wdsintr(void *); integrate void wds_reset_scb(struct wds_softc *, struct wds_scb *); -void wds_free_scb(struct wds_softc *, struct wds_scb *); +void wds_scb_free(void *, void *); void wds_free_buf(struct wds_softc *, struct wds_buf *); integrate void wds_init_scb(struct wds_softc *, struct wds_scb *); -struct wds_scb *wds_get_scb(struct wds_softc *, int, int); +void *wds_scb_alloc(void *); struct wds_buf *wds_get_buf(struct wds_softc *, int); struct wds_scb *wds_scb_phys_kv(struct wds_softc *, u_long); void wds_queue_scb(struct wds_softc *, struct wds_scb *); @@ -293,6 +296,9 @@ wdsattach(parent, self, aux) TAILQ_INIT(&sc->sc_free_scb); TAILQ_INIT(&sc->sc_waiting_scb); + mtx_init(&sc->sc_scb_mtx, IPL_BIO); + scsi_iopool_init(&sc->sc_iopool, sc, wds_scb_alloc, wds_scb_free); + wds_inquire_setup_information(sc); /* @@ -308,6 +314,7 @@ wdsattach(parent, self, aux) /* I don't think the -ASE can handle openings > 1. */ /* It gives Vendor Error 26 whenever I try it. */ sc->sc_link.openings = 1; + sc->sc_link.pool = &sc->sc_iopool; sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE, IPL_BIO, wdsintr, sc, sc->sc_dev.dv_xname); @@ -435,35 +442,21 @@ wds_reset_scb(sc, scb) * Free the command structure, the outgoing mailbox and the data buffer. */ void -wds_free_scb(sc, scb) - struct wds_softc *sc; - struct wds_scb *scb; +wds_scb_free(xsc, xscb) + void *xsc, *xscb; { - int s; + struct wds_softc *sc = xsc; + struct wds_scb *scb = xscb; - if (scb->buf != 0) { + if (scb->buf) { wds_free_buf(sc, scb->buf); - scb->buf = 0; + scb->buf = NULL; } - s = splbio(); - -#ifdef notyet - if (scb->scb_phys[0].addr) - isadma_unmap((caddr_t)scb, SCB_PHYS_SIZE, 1, scb->scb_phys); -#endif - wds_reset_scb(sc, scb); + mtx_enter(&sc->sc_scb_mtx); TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain); - - /* - * If there were none, wake anybody waiting for one to come free, - * starting with queued entries. - */ - if (TAILQ_NEXT(scb, chain) == NULL) - wakeup(&sc->sc_free_scb); - - splx(s); + mtx_leave(&sc->sc_scb_mtx); } void @@ -509,84 +502,22 @@ wds_init_scb(sc, scb) /* * Get a free scb - * - * If there are none, see if we can allocate a new one. If so, put it in - * the hash table too otherwise either return an error or sleep. */ -struct wds_scb * -wds_get_scb(sc, flags, needbuffer) - struct wds_softc *sc; - int flags; - int needbuffer; +void * +wds_scb_alloc(xsc) + void *xsc; { + struct wds_softc *sc = xsc; struct wds_scb *scb; - int s; -#ifdef notyet - int mflags, hashnum; -#endif - - s = splbio(); - -#ifdef notyet - if (flags & SCSI_NOSLEEP) - mflags = ISADMA_MAP_BOUNCE; - else - mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK; -#endif - /* - * If we can and have to, sleep waiting for one to come free - * but only if we can't allocate a new one. - */ - for (;;) { - scb = TAILQ_FIRST(&sc->sc_free_scb); - if (scb) { - TAILQ_REMOVE(&sc->sc_free_scb, scb, chain); - break; - } - if (sc->sc_numscbs < WDS_SCB_MAX) { - scb = (struct wds_scb *) malloc(sizeof(struct wds_scb), - M_TEMP, M_NOWAIT); - if (!scb) { - printf("%s: can't malloc scb\n", - sc->sc_dev.dv_xname); - goto out; - } - wds_init_scb(sc, scb); - sc->sc_numscbs++; - break; - } - if ((flags & SCSI_NOSLEEP) != 0) - goto out; - tsleep(&sc->sc_free_scb, PRIBIO, "wdsscb", 0); + mtx_enter(&sc->sc_scb_mtx); + scb = TAILQ_FIRST(&sc->sc_free_scb); + if (scb) { + TAILQ_REMOVE(&sc->sc_free_scb, scb, chain); + scb->flags |= SCB_ALLOC; } + mtx_leave(&sc->sc_scb_mtx); - scb->flags |= SCB_ALLOC; - -#ifdef notyet - if (isadma_map((caddr_t)scb, SCB_PHYS_SIZE, scb->scb_phys, - mflags | ISADMA_MAP_CONTIG) == 1) { - hashnum = SCB_HASH(scb->scb_phys[0].addr); - scb->nexthash = sc->sc_scbhash[hashnum]; - sc->sc_scbhash[hashnum] = ccb; - } else { - scb->scb_phys[0].addr = 0; - wds_free_scb(sc, scb); - scb = 0; - } -#else - if (needbuffer) { - scb->buf = wds_get_buf(sc, flags); - if (scb->buf == 0) { - wds_free_scb(sc, scb); - scb = 0; - } - } -#endif - - -out: - splx(s); return (scb); } @@ -834,7 +765,6 @@ wds_done(sc, scb, stat) scb->data_nseg, scb->data_phys); } #endif - wds_free_scb(sc, scb); scsi_done(xs); } @@ -978,7 +908,8 @@ wds_inquire_setup_information(sc) u_char *j; int s; - if ((scb = wds_get_scb(sc, SCSI_NOSLEEP, 0)) == NULL) { + scb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP); + if (scb == NULL) { printf("%s: no request slot available in getvers()!\n", sc->sc_dev.dv_xname); return; @@ -1013,7 +944,7 @@ wds_inquire_setup_information(sc) out: printf("\n"); - wds_free_scb(sc, scb); + scsi_io_put(&sc->sc_iopool, scb); } void @@ -1060,11 +991,7 @@ wds_scsi_cmd(xs) else mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK; #endif - if ((scb = wds_get_scb(sc, flags, NEEDBUFFER(sc))) == NULL) { - xs->error = XS_NO_CCB; - scsi_done(xs); - return; - } + scb = xs->io; scb->xs = xs; scb->timeout = xs->timeout; @@ -1227,7 +1154,6 @@ wds_scsi_cmd(xs) isadma_unmap(xs->data, xs->datalen, scb->data_nseg, scb->data_phys); } - wds_free_scb(sc, scb); scsi_done(xs); splx(s); return; @@ -1247,7 +1173,6 @@ wds_scsi_cmd(xs) bad: xs->error = XS_DRIVER_STUFFUP; - wds_free_scb(sc, scb); } /* Index: sys/dev/sdmmc/sdmmc_scsi.c =================================================================== RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_scsi.c,v retrieving revision 1.25 diff -u -p -r1.25 sdmmc_scsi.c --- sys/dev/sdmmc/sdmmc_scsi.c 24 Aug 2010 14:52:23 -0000 1.25 +++ sys/dev/sdmmc/sdmmc_scsi.c 4 Oct 2010 01:44:31 -0000 @@ -70,12 +70,14 @@ struct sdmmc_scsi_softc { struct sdmmc_ccb *sc_ccbs; /* allocated ccbs */ struct sdmmc_ccb_list sc_ccb_freeq; /* free ccbs */ struct sdmmc_ccb_list sc_ccb_runq; /* queued ccbs */ + struct mutex sc_ccb_mtx; + struct scsi_iopool sc_iopool; }; int sdmmc_alloc_ccbs(struct sdmmc_scsi_softc *, int); void sdmmc_free_ccbs(struct sdmmc_scsi_softc *); -struct sdmmc_ccb *sdmmc_get_ccb(struct sdmmc_scsi_softc *, int); -void sdmmc_put_ccb(struct sdmmc_ccb *); +void *sdmmc_ccb_alloc(void *); +void sdmmc_ccb_free(void *, void *); void sdmmc_scsi_cmd(struct scsi_xfer *); void sdmmc_start_xs(struct sdmmc_softc *, struct sdmmc_ccb *); @@ -133,6 +135,7 @@ sdmmc_scsi_attach(struct sdmmc_softc *sc scbus->sc_link.luns = 1; scbus->sc_link.openings = 1; scbus->sc_link.adapter = &scbus->sc_adapter; + scbus->sc_link.pool = &scbus->sc_iopool; bzero(&saa, sizeof(saa)); saa.scsi_link = &scbus->sc_link; @@ -200,6 +203,9 @@ sdmmc_alloc_ccbs(struct sdmmc_scsi_softc TAILQ_INIT(&scbus->sc_ccb_freeq); TAILQ_INIT(&scbus->sc_ccb_runq); + mtx_init(&scbus->sc_ccb_mtx, IPL_BIO); + scsi_iopool_init(&scbus->sc_iopool, scbus, sdmmc_ccb_alloc, + sdmmc_ccb_free); for (i = 0; i < nccbs; i++) { ccb = &scbus->sc_ccbs[i]; @@ -222,40 +228,42 @@ sdmmc_free_ccbs(struct sdmmc_scsi_softc } } -struct sdmmc_ccb * -sdmmc_get_ccb(struct sdmmc_scsi_softc *scbus, int flags) +void * +sdmmc_ccb_alloc(void *xscbus) { + struct sdmmc_scsi_softc *scbus = xscbus; struct sdmmc_ccb *ccb; - int s; - s = splbio(); - while ((ccb = TAILQ_FIRST(&scbus->sc_ccb_freeq)) == NULL && - !ISSET(flags, SCSI_NOSLEEP)) - tsleep(&scbus->sc_ccb_freeq, PRIBIO, "getccb", 0); + mtx_enter(&scbus->sc_ccb_mtx); + ccb = TAILQ_FIRST(&scbus->sc_ccb_freeq); if (ccb != NULL) { TAILQ_REMOVE(&scbus->sc_ccb_freeq, ccb, ccb_link); ccb->ccb_state = SDMMC_CCB_READY; } - splx(s); + mtx_leave(&scbus->sc_ccb_mtx); + return ccb; } void -sdmmc_put_ccb(struct sdmmc_ccb *ccb) +sdmmc_ccb_free(void *xscbus, void *xccb) { - struct sdmmc_scsi_softc *scbus = ccb->ccb_scbus; + struct sdmmc_scsi_softc *scbus = xscbus; + struct sdmmc_ccb *ccb = xccb; int s; s = splbio(); if (ccb->ccb_state == SDMMC_CCB_QUEUED) TAILQ_REMOVE(&scbus->sc_ccb_runq, ccb, ccb_link); + splx(s); + ccb->ccb_state = SDMMC_CCB_FREE; ccb->ccb_flags = 0; ccb->ccb_xs = NULL; + + mtx_enter(&scbus->sc_ccb_mtx); TAILQ_INSERT_TAIL(&scbus->sc_ccb_freeq, ccb, ccb_link); - if (TAILQ_NEXT(ccb, ccb_link) == NULL) - wakeup(&scbus->sc_ccb_freeq); - splx(s); + mtx_leave(&scbus->sc_ccb_mtx); } /* @@ -366,16 +374,9 @@ sdmmc_scsi_cmd(struct scsi_xfer *xs) return; } - ccb = sdmmc_get_ccb(sc->sc_scsibus, xs->flags); - if (ccb == NULL) { - printf("%s: out of ccbs\n", DEVNAME(sc)); - xs->error = XS_DRIVER_STUFFUP; - scsi_done(xs); - return; - } + ccb = xs->io; ccb->ccb_xs = xs; - ccb->ccb_blockcnt = blockcnt; ccb->ccb_blockno = blockno; @@ -458,7 +459,6 @@ sdmmc_done_xs(struct sdmmc_ccb *ccb) if (ISSET(ccb->ccb_flags, SDMMC_CCB_F_ERR)) xs->error = XS_DRIVER_STUFFUP; - sdmmc_put_ccb(ccb); scsi_done(xs); }