Re: scsi iopoolification of many 'obscure' drivers

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Kenneth R Westerback
Date: Saturday, October 2, 2010 - 2:28 pm

On Fri, Sep 24, 2010 at 03:55:50AM -0400, Kenneth R Westerback wrote:

Sigh. And now with the forgotten luna88k bit.

.... 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/adw.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/adw.c,v
retrieving revision 1.47
diff -u -p -r1.47 adw.c
--- sys/dev/ic/adw.c	7 Aug 2010 03:50:01 -0000	1.47
+++ sys/dev/ic/adw.c	23 Sep 2010 13:56:21 -0000
@@ -59,10 +59,10 @@
 int adw_alloc_controls(ADW_SOFTC *);
 int adw_alloc_carriers(ADW_SOFTC *);
 int adw_create_ccbs(ADW_SOFTC *, ADW_CCB *, int);
-void adw_free_ccb(ADW_SOFTC *, ADW_CCB *);
+void adw_ccb_free(void *, void *);
 void adw_reset_ccb(ADW_CCB *);
 int adw_init_ccb(ADW_SOFTC *, ADW_CCB *);
-ADW_CCB *adw_get_ccb(ADW_SOFTC *, int);
+void *adw_ccb_alloc(void *);
 int adw_queue_ccb(ADW_SOFTC *, ADW_CCB *, int);
 
 void adw_scsi_cmd(struct scsi_xfer *);
@@ -230,25 +230,17 @@ adw_create_ccbs(sc, ccbstore, count)
  * A ccb is put onto the free list.
  */
 void
-adw_free_ccb(sc, ccb)
-	ADW_SOFTC      *sc;
-	ADW_CCB        *ccb;
+adw_ccb_free(xsc, xccb)
+	void *xsc, *xccb;
 {
-	int             s;
-
-	s = splbio();
+	ADW_SOFTC *sc = xsc;
+	ADW_CCB *ccb = xccb;
 
 	adw_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);
 }
 
 
@@ -300,36 +292,21 @@ adw_init_ccb(sc, ccb)
  *
  * If there are none, see if we can allocate a new one
  */
-ADW_CCB *
-adw_get_ccb(sc, flags)
-	ADW_SOFTC      *sc;
-	int             flags;
-{
-	ADW_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, "adwccb", 0);
+void *
+adw_ccb_alloc(xsc)
+	void *xsc;
+{
+	ADW_SOFTC *sc = xsc;
+	ADW_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);
 }
 
@@ -455,6 +432,8 @@ adw_attach(sc)
 	TAILQ_INIT(&sc->sc_waiting_ccb);
 	TAILQ_INIT(&sc->sc_pending_ccb);
 
+	mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
+	scsi_iopool_init(&sc->sc_iopool, sc, adw_ccb_alloc, adw_ccb_free);
 
 	/*
          * Allocate the Control Blocks.
@@ -554,6 +533,7 @@ adw_attach(sc)
 	sc->sc_link.adapter = &sc->sc_adapter;
 	sc->sc_link.openings = 4;
 	sc->sc_link.adapter_buswidth = ADW_MAX_TID+1;
+	sc->sc_link.pool = &sc->sc_iopool;
 
 	bzero(&saa, sizeof(saa));
 	saa.saa_sc_link = &sc->sc_link;
@@ -597,13 +577,7 @@ adw_scsi_cmd(xs)
 	flags = xs->flags;
 	if (nowait)
 		flags |= SCSI_NOSLEEP;
-	if ((ccb = adw_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;
@@ -714,7 +688,6 @@ adw_build_req(xs, ccb, flags)
 			}
 
 			xs->error = XS_DRIVER_STUFFUP;
-			adw_free_ccb(sc, ccb);
 			return (0);
 		}
 		bus_dmamap_sync(dmat, ccb->dmamap_xfer,
@@ -1046,7 +1019,6 @@ adw_isr_callback(sc, scsiq)
 	if ((ccb->flags & CCB_ALLOC) == 0) {
 		panic("%s: unallocated ccb found on pending list!",
 		    sc->sc_dev.dv_xname);
-		adw_free_ccb(sc, ccb);
 		return;
 	}
 
@@ -1205,8 +1177,6 @@ NO_ERROR:
 		xs->error = XS_DRIVER_STUFFUP;
 		break;
 	}
-
-	adw_free_ccb(sc, ccb);
 
 	scsi_done(xs);
 }
Index: sys/dev/ic/adwlib.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/adwlib.h,v
retrieving revision 1.12
diff -u -p -r1.12 adwlib.h
--- sys/dev/ic/adwlib.h	26 Nov 2008 16:39:31 -0000	1.12
+++ sys/dev/ic/adwlib.h	23 Sep 2010 08:22:47 -0000
@@ -746,6 +746,8 @@ typedef struct adw_softc {
 	TAILQ_HEAD(adw_pending_ccb, adw_ccb)	sc_pending_ccb;
 	struct scsi_link	sc_link;     /* prototype for devs */
 	struct scsi_adapter	sc_adapter;
+	struct mutex		sc_ccb_mtx;
+	struct scsi_iopool	sc_iopool;
 
 	int			sc_freeze_dev[ADW_MAX_TID+1];
 
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/iha.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/iha.c,v
retrieving revision 1.39
diff -u -p -r1.39 iha.c
--- sys/dev/ic/iha.c	28 Jun 2010 18:31:02 -0000	1.39
+++ sys/dev/ic/iha.c	23 Sep 2010 13:54:21 -0000
@@ -99,8 +99,8 @@ void iha_scsi(struct iha_softc *, bus_sp
 int  iha_wait(struct iha_softc *, bus_space_tag_t, bus_space_handle_t,
 		      u_int8_t);
 void iha_mark_busy_scb(struct iha_scb *);
-void iha_append_free_scb(struct iha_softc *, struct iha_scb *);
-struct iha_scb *iha_pop_free_scb(struct iha_softc *);
+void *iha_scb_alloc(void *);
+void iha_scb_free(void *, void *);
 void iha_append_done_scb(struct iha_softc *, struct iha_scb *,
 				 u_int8_t);
 struct iha_scb *iha_pop_done_scb(struct iha_softc *);
@@ -267,12 +267,7 @@ iha_scsi_cmd(xs)
 		return;
 	}
 
-	pScb = iha_pop_free_scb(sc);
-	if (pScb == NULL) {
-		xs->error = XS_NO_CCB;
-		scsi_done(xs);
-		return;
-	}
+	pScb = xs->io;
 
 	pScb->SCB_Target = sc_link->target;
 	pScb->SCB_Lun	 = sc_link->lun;
@@ -306,8 +301,6 @@ iha_scsi_cmd(xs)
 				printf("error %d loading buffer dma map\n",
 				    error);
 
-			iha_append_free_scb(sc, pScb); 
-
 			xs->error = XS_DRIVER_STUFFUP;
 			scsi_done(xs);
 			return;
@@ -361,6 +354,13 @@ iha_init_tulip(sc)
 
 	pScsi = &iha_nvram.NVM_Scsi[0];
 
+	TAILQ_INIT(&sc->HCS_FreeScb);
+	TAILQ_INIT(&sc->HCS_PendScb);
+	TAILQ_INIT(&sc->HCS_DoneScb);
+
+	mtx_init(&sc->sc_scb_mtx, IPL_BIO);
+	scsi_iopool_init(&sc->sc_iopool, sc, iha_scb_alloc, iha_scb_free);
+
 	/*
 	 * fill in the prototype scsi_link.
 	 */
@@ -369,6 +369,7 @@ iha_init_tulip(sc)
 	sc->sc_link.openings	     = 4; /* # xs's allowed per device */
 	sc->sc_link.adapter_target   = pScsi->NVM_SCSI_Id;
 	sc->sc_link.adapter_buswidth = pScsi->NVM_SCSI_Targets;
+	sc->sc_link.pool             = &sc->sc_iopool;
 
 	/*
 	 * fill in the rest of the iha_softc fields
@@ -377,10 +378,6 @@ iha_init_tulip(sc)
 	sc->HCS_JSStatus0 = 0;
 	sc->HCS_ActScb	  = NULL;
 
-	TAILQ_INIT(&sc->HCS_FreeScb);
-	TAILQ_INIT(&sc->HCS_PendScb);
-	TAILQ_INIT(&sc->HCS_DoneScb);
-
 	error = iha_alloc_scbs(sc);
 	if (error != 0)
 		return (error);
@@ -491,45 +488,42 @@ iha_reset_dma(iot, ioh)
 }
 
 /*
- * iha_pop_free_scb - return the first free SCB, or NULL if there are none.
+ * iha_scb_alloc - return the first free SCB, or NULL if there are none.
  */
-struct iha_scb *
-iha_pop_free_scb(sc)
-	struct iha_softc *sc;
+void *
+iha_scb_alloc(xsc)
+	void *xsc;
 {
+	struct iha_softc *sc;
 	struct iha_scb *pScb;
-	int s;
-
-	s = splbio();
 
+	mtx_enter(&sc->sc_scb_mtx);
 	pScb = TAILQ_FIRST(&sc->HCS_FreeScb);
-
 	if (pScb != NULL) {
 		pScb->SCB_Status = STATUS_RENT;
 		TAILQ_REMOVE(&sc->HCS_FreeScb, pScb, SCB_ScbList);
 	}
-
-	splx(s);
+	mtx_leave(&sc->sc_scb_mtx);
 
 	return (pScb);
 }
 
 /*
- * iha_append_free_scb - append the supplied SCB to the tail of the
- *                       HCS_FreeScb queue after clearing and resetting
- *			 everything possible.
+ * iha_scb_free - append the supplied SCB to the tail of the
+ *                HCS_FreeScb queue after clearing and resetting
+ *		  everything possible.
  */
 void
-iha_append_free_scb(sc, pScb)
-	struct iha_softc *sc;
-	struct iha_scb *pScb;
+iha_scb_free(void *xsc, void *xscb)
 {
+	struct iha_softc *sc = xsc;
+	struct iha_scb *pScb = xscb;
 	int s;
 
 	s = splbio();
-
 	if (pScb == sc->HCS_ActScb)
 		sc->HCS_ActScb = NULL;
+	splx(s);
 
 	pScb->SCB_Status = STATUS_QUEUED;
 	pScb->SCB_HaStat = HOST_OK;
@@ -555,9 +549,9 @@ iha_append_free_scb(sc, pScb)
 	 * SCB_TagId is set at initialization and never changes
 	 */
 
+	mtx_enter(&sc->sc_scb_mtx);
 	TAILQ_INSERT_TAIL(&sc->HCS_FreeScb, pScb, SCB_ScbList);
-
-	splx(s);
+	mtx_leave(&sc->sc_scb_mtx);
 }
 
 void
@@ -2541,11 +2535,8 @@ iha_done_scb(sc, pScb)
 			xs->error = XS_DRIVER_STUFFUP;
 			break;
 		}
-
 		scsi_done(xs);
 	}
-	
-	iha_append_free_scb(sc, pScb);
 }
 
 void
Index: sys/dev/ic/iha.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/iha.h,v
retrieving revision 1.17
diff -u -p -r1.17 iha.h
--- sys/dev/ic/iha.h	23 Mar 2010 01:57:19 -0000	1.17
+++ sys/dev/ic/iha.h	23 Sep 2010 07:00:18 -0000
@@ -167,6 +167,9 @@ struct iha_softc {
 	TAILQ_HEAD(, iha_scb) HCS_FreeScb, HCS_PendScb, HCS_DoneScb;
 
 	struct tcs HCS_Tcs[IHA_MAX_TARGETS];
+
+	struct mutex		sc_scb_mtx;	/* scb queue protection */
+	struct scsi_iopool	sc_iopool;
 };
 
 /*
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	23 Sep 2010 14:01:24 -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,39 @@ 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);
 	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;
 
+	mtx_enter(&scbus->sc_ccb_mtx);
 	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;
 	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 +371,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 +456,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);
 }
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
scsi iopoolification of many 'obscure' drivers, Kenneth R Westerback, (Fri Sep 24, 12:55 am)
Re: scsi iopoolification of many 'obscure' drivers, Kenneth R Westerback, (Sat Oct 2, 1:54 pm)
Re: scsi iopoolification of many 'obscure' drivers, Kenneth R Westerback, (Sat Oct 2, 2:28 pm)
Re: scsi iopoolification of many 'obscure' drivers, Kenneth R Westerback, (Sat Oct 2, 7:00 pm)
Re: scsi iopoolification of many 'obscure' drivers, Kenneth R Westerback, (Sun Oct 3, 7:07 pm)