DragonFly kernel List (threaded) for 2008-01
DragonFly BSD
DragonFly kernel List (threaded) for 2008-01
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: ahc/ahd locking


From: Peter Avalos <pavalos@xxxxxxxxxxxx>
Date: Tue, 1 Jan 2008 21:15:08 -0500
Mail-followup-to: kernel@crater.dragonflybsd.org

Here's my latest patch.  The difference from the last is that I interlocked
the tsleeps and asserted that the serializer is held in the interrupt
handler.

1.  Do the tsleep interlocks look right?

2.  Did I use lwkt_serialize_handler_enable/disable properly?

3.  Generally, does this patch look right?

Thanks,
Peter

http://www.theshell.com/~pavalos/wip/aic7xxx-locking3.patch
diff --git a/sys/dev/disk/aic7xxx/aic7770.c b/sys/dev/disk/aic7xxx/aic7770.c
index fcef375..ad91898 100644
--- a/sys/dev/disk/aic7xxx/aic7770.c
+++ b/sys/dev/disk/aic7xxx/aic7770.c
@@ -254,6 +254,7 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
 	if (error != 0)
 		return (error);
 
+	ahc_lock(ahc);
 	/*
 	 * Link this softc in with all other ahc instances.
 	 */
@@ -264,6 +265,8 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
 	 */
 	ahc_outb(ahc, BCTL, ENABLE);
 
+	ahc_unlock(ahc);
+
 	return (0);
 }
 
diff --git a/sys/dev/disk/aic7xxx/aic79xx.c b/sys/dev/disk/aic7xxx/aic79xx.c
index 834fcf4..47f3565 100644
--- a/sys/dev/disk/aic7xxx/aic79xx.c
+++ b/sys/dev/disk/aic7xxx/aic79xx.c
@@ -5251,6 +5251,7 @@ ahd_alloc(void *platform_arg, char *name)
 		ahd_free(ahd);
 		ahd = NULL;
 	}
+	ahd_lockinit(ahd);
 #ifdef AHD_DEBUG
 	if ((ahd_debug & AHD_SHOW_MEMORY) != 0) {
 		kprintf("%s: scb size = 0x%x, hscb size = 0x%x\n",
@@ -5322,22 +5323,6 @@ ahd_softc_insert(struct ahd_softc *ahd)
 	ahd->init_level++;
 }
 
-/*
- * Verify that the passed in softc pointer is for a
- * controller that is still configured.
- */
-struct ahd_softc *
-ahd_find_softc(struct ahd_softc *ahd)
-{
-	struct ahd_softc *list_ahd;
-
-	TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
-		if (list_ahd == ahd)
-			return (ahd);
-	}
-	return (NULL);
-}
-
 void
 ahd_set_unit(struct ahd_softc *ahd, int unit)
 {
@@ -6179,6 +6164,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
 		next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag);
 		if (next_scb->col_scb != NULL)
 			next_scb->col_scb->col_scb = next_scb;
+		aic_timer_init(&next_scb->io_timer);
 		ahd_free_scb(ahd, next_scb);
 		hscb++;
 		hscb_busaddr += sizeof(*hscb);
@@ -7019,6 +7005,9 @@ ahd_intr_enable(struct ahd_softc *ahd, int enable)
 {
 	u_int hcntrl;
 
+	if (enable)
+		lwkt_serialize_handler_enable(&ahd->platform_data->serializer);
+
 	hcntrl = ahd_inb(ahd, HCNTRL);
 	hcntrl &= ~INTEN;
 	ahd->pause &= ~INTEN;
@@ -7029,6 +7018,8 @@ ahd_intr_enable(struct ahd_softc *ahd, int enable)
 		ahd->unpause |= INTEN;
 	}
 	ahd_outb(ahd, HCNTRL, hcntrl);
+	if (!enable)
+		lwkt_serialize_handler_disable(&ahd->platform_data->serializer);
 }
 
 void
@@ -8024,15 +8015,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
 static void
 ahd_reset_poll(void *arg)
 {
-	struct	ahd_softc *ahd;
+	struct	ahd_softc *ahd = (struct ahd_softc *)arg;
 	u_int	scsiseq1;
 	
-	ahd = ahd_find_softc((struct ahd_softc *)arg);
-	if (ahd == NULL) {
-		kprintf("ahd_reset_poll: Instance %p no longer exists\n", arg);
-		return;
-	}
-	ahd_lock();
+	ahd_lock(ahd);
 	ahd_pause(ahd);
 	ahd_update_modes(ahd);
 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
@@ -8041,7 +8027,7 @@ ahd_reset_poll(void *arg)
 		aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_MS,
 				ahd_reset_poll, ahd);
 		ahd_unpause(ahd);
-		ahd_unlock();
+		ahd_unlock(ahd);
 		return;
 	}
 
@@ -8051,24 +8037,18 @@ ahd_reset_poll(void *arg)
 	ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP));
 	ahd_unpause(ahd);
 	ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
-	ahd_unlock();
 	aic_release_simq(ahd);
+	ahd_unlock(ahd);
 }
 
 /**************************** Statistics Processing ***************************/
 static void
 ahd_stat_timer(void *arg)
 {
-	struct	ahd_softc *ahd;
+	struct	ahd_softc *ahd = (struct ahd_softc *)arg;
 	int	enint_coal;
 	
-	ahd = ahd_find_softc((struct ahd_softc *)arg);
-	if (ahd == NULL) {
-		kprintf("ahd_stat_timer: Instance %p no longer exists\n", arg);
-		return;
-	}
-	ahd_lock();
-
+	ahd_lock(ahd);
 	enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
 	if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold)
 		enint_coal |= ENINT_COALESCE;
@@ -8092,7 +8072,7 @@ ahd_stat_timer(void *arg)
 	ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0;
 	aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS,
 			ahd_stat_timer, ahd);
-	ahd_unlock();
+	ahd_unlock(ahd);
 }
 
 /****************************** Status Processing *****************************/
@@ -9255,8 +9235,6 @@ ahd_recover_commands(struct ahd_softc *ahd)
 	u_int	active_scbptr;
 	u_int	last_phase;
 
-	ahd_lock();
-
 	/*
 	 * Pause the controller and manually flush any
 	 * commands that have just completed but that our
@@ -9282,7 +9260,6 @@ ahd_recover_commands(struct ahd_softc *ahd)
 		kprintf("%s: Timedout SCBs already complete. "
 		       "Interrupts may not be functioning.\n", ahd_name(ahd));
 		ahd_unpause(ahd);
-		ahd_unlock();
 		return;
 	}
 
@@ -9473,7 +9450,6 @@ bus_reset:
 	}
 
 	ahd_unpause(ahd);
-	ahd_unlock();
 }
 
 /*
@@ -9889,13 +9865,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 	 */
 	if ((ahd->flags & AHD_TARGETROLE) == 0
 	 && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
-		u_long	s;
-
 		kprintf("Configuring Target Mode\n");
-		ahd_lock();
 		if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
 			ccb->ccb_h.status = CAM_BUSY;
-			ahd_unlock();
 			return;
 		}
 		ahd->flags |= AHD_TARGETROLE;
@@ -9904,7 +9876,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 		ahd_pause(ahd);
 		ahd_loadseq(ahd);
 		ahd_restart(ahd);
-		ahd_unlock();
 	}
 	cel = &ccb->cel;
 	target = ccb->ccb_h.target_id;
@@ -9963,7 +9934,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 		}
 		SLIST_INIT(&lstate->accept_tios);
 		SLIST_INIT(&lstate->immed_notifies);
-		ahd_lock();
 		ahd_pause(ahd);
 		if (target != CAM_TARGET_WILDCARD) {
 			tstate->enabled_luns[lun] = lstate;
@@ -10022,7 +9992,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 			ahd_outb(ahd, SCSISEQ1, scsiseq1);
 		}
 		ahd_unpause(ahd);
-		ahd_unlock();
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_print_path(ccb->ccb_h.path);
 		kprintf("Lun now enabled for target mode\n");
@@ -10035,8 +10004,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 			return;
 		}
 
-		ahd_lock();
-		
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
 			struct ccb_hdr *ccbh;
@@ -10046,7 +10013,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 			 && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
 				kprintf("CTIO pending\n");
 				ccb->ccb_h.status = CAM_REQ_INVALID;
-				ahd_unlock();
 				return;
 			}
 		}
@@ -10062,7 +10028,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 		}
 
 		if (ccb->ccb_h.status != CAM_REQ_CMP) {
-			ahd_unlock();
 			return;
 		}
 
@@ -10129,7 +10094,6 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
 			}
 		}
 		ahd_unpause(ahd);
-		ahd_unlock();
 	}
 #endif
 }
diff --git a/sys/dev/disk/aic7xxx/aic79xx.h b/sys/dev/disk/aic7xxx/aic79xx.h
index f4e5bf3..847ae9d 100644
--- a/sys/dev/disk/aic7xxx/aic79xx.h
+++ b/sys/dev/disk/aic7xxx/aic79xx.h
@@ -640,6 +640,7 @@ struct scb {
 	u_int			  sg_count;/* How full ahd_dma_seg is */
 #define	AHD_MAX_LQ_CRC_ERRORS 5
 	u_int			  crc_retry_count;
+	aic_timer_t		  io_timer;
 };
 
 TAILQ_HEAD(scb_tailq, scb);
@@ -1395,7 +1396,6 @@ void			 ahd_pause_and_flushwork(struct ahd_softc *ahd);
 int			 ahd_suspend(struct ahd_softc *ahd); 
 int			 ahd_resume(struct ahd_softc *ahd);
 void			 ahd_softc_insert(struct ahd_softc *);
-struct ahd_softc	*ahd_find_softc(struct ahd_softc *ahd);
 void			 ahd_set_unit(struct ahd_softc *, int);
 void			 ahd_set_name(struct ahd_softc *, char *);
 struct scb		*ahd_get_scb(struct ahd_softc *ahd, u_int col_idx);
diff --git a/sys/dev/disk/aic7xxx/aic79xx_osm.c b/sys/dev/disk/aic7xxx/aic79xx_osm.c
index 360dea5..3c38a89 100644
--- a/sys/dev/disk/aic7xxx/aic79xx_osm.c
+++ b/sys/dev/disk/aic7xxx/aic79xx_osm.c
@@ -94,9 +94,9 @@ ahd_map_int(struct ahd_softc *ahd)
 	int error;
 
 	/* Hook up our interrupt handler */
-	error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq,
-			       0, ahd_platform_intr, ahd,
-			       &ahd->platform_data->ih, NULL);
+	error = bus_setup_intr(ahd->dev_softc, ahd->platform_data->irq, 0,
+			       ahd_platform_intr, ahd, &ahd->platform_data->ih,
+			       &ahd->platform_data->serializer);
 	if (error != 0)
 		device_printf(ahd->dev_softc, "bus_setup_intr() failed: %d\n",
 			      error);
@@ -126,7 +126,7 @@ ahd_attach(struct ahd_softc *ahd)
 
 	ahd_controller_info(ahd, ahd_info);
 	kprintf("%s\n", ahd_info);
-	ahd_lock();
+	ahd_lock(ahd);
 
 	/*
 	 * Construct our SIM entry
@@ -163,6 +163,7 @@ ahd_attach(struct ahd_softc *ahd)
 fail:
 	ahd->platform_data->sim = sim;
 	ahd->platform_data->path = path;
+	ahd_unlock(ahd);
 	if (count != 0) {
 		/* We have to wait until after any system dumps... */
 		ahd->platform_data->eh =
@@ -171,8 +172,6 @@ fail:
 		ahd_intr_enable(ahd, TRUE);
 	}
 
-	ahd_unlock();
-
 	return (count);
 }
 
@@ -185,6 +184,7 @@ ahd_platform_intr(void *arg)
 	struct	ahd_softc *ahd;
 
 	ahd = (struct ahd_softc *)arg; 
+	ASSERT_SERIALIZED(&ahd->platform_data->serializer);
 	ahd_intr(ahd);
 }
 
@@ -206,7 +206,7 @@ ahd_done(struct ahd_softc *ahd, struct scb *scb)
 	if ((scb->flags & SCB_TIMEDOUT) != 0)
 		LIST_REMOVE(scb, timedout_links);
 
-	callout_stop(&ccb->ccb_h.timeout_ch);
+	callout_stop(&scb->io_timer);
 
 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 		bus_dmasync_op_t op;
@@ -369,13 +369,11 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
 		}
 		if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
 
-			ahd_lock();
 			SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
 					  sim_links.sle);
 			ccb->ccb_h.status = CAM_REQ_INPROG;
 			if ((ahd->flags & AHD_TQINFIFO_BLOCKED) != 0)
 				ahd_run_tqinfifo(ahd, /*paused*/FALSE);
-			ahd_unlock();
 			break;
 		}
 
@@ -409,7 +407,6 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
 		/*
 		 * get an scb to use.
 		 */
-		ahd_lock();
 		tinfo = ahd_fetch_transinfo(ahd, 'A', our_id,
 					    target_id, &tstate);
 		if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0
@@ -424,12 +421,10 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
 	
 			xpt_freeze_simq(sim, /*count*/1);
 			ahd->flags |= AHD_RESOURCE_SHORTAGE;
-			ahd_unlock();
 			ccb->ccb_h.status = CAM_REQUEUE_REQ;
 			xpt_done(ccb);
 			return;
 		}
-		ahd_unlock();
 		
 		hscb = scb->hscb;
 		
@@ -517,20 +512,16 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
 	}
 	case XPT_SET_TRAN_SETTINGS:
 	{
-		ahd_lock();
 		ahd_set_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
 				      SIM_CHANNEL(ahd, sim), &ccb->cts);
-		ahd_unlock();
 		xpt_done(ccb);
 		break;
 	}
 	case XPT_GET_TRAN_SETTINGS:
 	/* Get default/user set transfer settings for the target */
 	{
-		ahd_lock();
 		ahd_get_tran_settings(ahd, SIM_SCSI_ID(ahd, sim),
 				      SIM_CHANNEL(ahd, sim), &ccb->cts);
-		ahd_unlock();
 		xpt_done(ccb);
 		break;
 	}
@@ -544,10 +535,8 @@ ahd_action(struct cam_sim *sim, union ccb *ccb)
 	{
 		int  found;
 		
-		ahd_lock();
 		found = ahd_reset_channel(ahd, SIM_CHANNEL(ahd, sim),
 					  /*initiate reset*/TRUE);
-		ahd_unlock();
 		if (bootverbose) {
 			xpt_print_path(SIM_PATH(ahd, sim));
 			kprintf("SCSI bus reset delivered. "
@@ -976,13 +965,11 @@ ahd_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
 		 * Revert to async/narrow transfers
 		 * for the next device.
 		 */
-		ahd_lock();
 		ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
 			      AHD_TRANS_GOAL|AHD_TRANS_CUR, /*paused*/FALSE);
 		ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
 				 /*ppr_options*/0, AHD_TRANS_GOAL|AHD_TRANS_CUR,
 				 /*paused*/FALSE);
-		ahd_unlock();
 		break;
 	}
 	default:
@@ -1012,9 +999,7 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 			aic_set_transaction_status(scb, CAM_REQ_CMP_ERR);
 		if (nsegments != 0)
 			bus_dmamap_unload(ahd->buffer_dmat, scb->dmamap);
-		ahd_lock();
 		ahd_free_scb(ahd, scb);
-		ahd_unlock();
 		xpt_done(ccb);
 		return;
 	}
@@ -1052,8 +1037,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 		}
 	}
 
-	ahd_lock();
-
 	/*
 	 * Last time we need to check if this SCB needs to
 	 * be aborted.
@@ -1063,7 +1046,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 			bus_dmamap_unload(ahd->buffer_dmat,
 					  scb->dmamap);
 		ahd_free_scb(ahd, scb);
-		ahd_unlock();
 		xpt_done(ccb);
 		return;
 	}
@@ -1112,8 +1094,6 @@ ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 	} else {
 		ahd_queue_scb(ahd, scb);
 	}
-
-	ahd_unlock();
 }
 
 static void
@@ -1140,6 +1120,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
 
 			if (hscb->cdb_len > MAX_CDB_LEN
 			 && (ccb_h->flags & CAM_CDB_PHYS) == 0) {
+
 				/*
 				 * Should CAM start to support CDB sizes
 				 * greater than 16 bytes, we could use
@@ -1147,9 +1128,7 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
 				 */
 				aic_set_transaction_status(scb,
 							   CAM_REQ_INVALID);
-				ahd_lock();
 				ahd_free_scb(ahd, scb);
-				ahd_unlock();
 				xpt_done((union ccb *)csio);
 				return;
 			}
@@ -1166,11 +1145,10 @@ ahd_setup_data(struct ahd_softc *ahd, struct cam_sim *sim,
 			}
 		} else {
 			if (hscb->cdb_len > MAX_CDB_LEN) {
+
 				aic_set_transaction_status(scb,
 							   CAM_REQ_INVALID);
-				ahd_lock();
 				ahd_free_scb(ahd, scb);
-				ahd_unlock();
 				xpt_done((union ccb *)csio);
 				return;
 			}
@@ -1448,16 +1426,11 @@ ahd_detach(device_t dev)
 
 	device_printf(dev, "detaching device\n");
 	ahd = device_get_softc(dev);
-	ahd = ahd_find_softc(ahd);
-	if (ahd == NULL) {
-		device_printf(dev, "aic7xxx already detached\n");
-		return (ENOENT);
-	}
+	ahd_lock(ahd);
 	TAILQ_REMOVE(&ahd_tailq, ahd, links);
-	ahd_lock();
 	ahd_intr_enable(ahd, FALSE);
 	bus_teardown_intr(dev, ahd->platform_data->irq, ahd->platform_data->ih);
-	ahd_unlock();
+	ahd_unlock(ahd);
 	ahd_free(ahd);
 	return (0);
 }
@@ -1494,6 +1467,7 @@ static int
 ahd_modevent(module_t mod, int type, void *data)
 {
 	/* XXX Deal with busy status on unload. */
+	/* XXX Deal with unknown events */
 	return 0;
 }
   
diff --git a/sys/dev/disk/aic7xxx/aic79xx_osm.h b/sys/dev/disk/aic7xxx/aic79xx_osm.h
index 1e4b4fe..994a616 100644
--- a/sys/dev/disk/aic7xxx/aic79xx_osm.h
+++ b/sys/dev/disk/aic7xxx/aic79xx_osm.h
@@ -116,6 +116,17 @@
 #define AHD_TARGET_MODE 1
 #endif
 
+/***************************** Core Includes **********************************/
+#ifdef AHD_REG_PRETTY_PRINT
+#define AIC_DEBUG_REGISTERS 1
+#else
+#define AIC_DEBUG_REGISTERS 0
+#endif
+#define	AIC_CORE_INCLUDE "aic79xx.h"
+#define	AIC_LIB_PREFIX ahd
+#define	AIC_CONST_PREFIX AHD
+#include "aic_osm_lib.h"
+
 /************************** Softc/SCB Platform Data ***************************/
 struct ahd_platform_data {
 	/*
@@ -132,22 +143,12 @@ struct ahd_platform_data {
 	void			*ih;
 	eventhandler_tag	 eh;
 	struct thread		*recovery_thread;
+	struct lwkt_serialize	 serializer;
 };
 
 struct scb_platform_data {
 };
 
-/***************************** Core Includes **********************************/
-#ifdef AHD_REG_PRETTY_PRINT
-#define AIC_DEBUG_REGISTERS 1
-#else
-#define AIC_DEBUG_REGISTERS 0
-#endif
-#define	AIC_CORE_INCLUDE "aic79xx.h"
-#define	AIC_LIB_PREFIX ahd
-#define	AIC_CONST_PREFIX AHD
-#include "aic_osm_lib.h"
-
 /*************************** Device Access ************************************/
 #define ahd_inb(ahd, port)					\
 	bus_space_read_1((ahd)->tags[(port) >> 8],		\
@@ -187,19 +188,26 @@ ahd_flush_device_writes(struct ahd_softc *ahd)
 
 /**************************** Locking Primitives ******************************/
 /* Lock protecting internal data structures */
-static __inline void ahd_lock(void);
-static __inline void ahd_unlock(void);
+static __inline void ahd_lockinit(struct ahd_softc *);
+static __inline void ahd_lock(struct ahd_softc *);
+static __inline void ahd_unlock(struct ahd_softc *);
+
+static __inline void
+ahd_lockinit(struct ahd_softc *ahd)
+{
+	lwkt_serialize_init(&ahd->platform_data->serializer);
+}
 
 static __inline void
-ahd_lock(void)
+ahd_lock(struct ahd_softc *ahd)
 {
-	crit_enter();
+	lwkt_serialize_enter(&ahd->platform_data->serializer);
 }
 
 static __inline void
-ahd_unlock(void)
+ahd_unlock(struct ahd_softc *ahd)
 {
-	crit_exit();
+	lwkt_serialize_exit(&ahd->platform_data->serializer);
 }
 
 /********************************** PCI ***************************************/
diff --git a/sys/dev/disk/aic7xxx/aic79xx_pci.c b/sys/dev/disk/aic7xxx/aic79xx_pci.c
index 07e27cf..ee67102 100644
--- a/sys/dev/disk/aic7xxx/aic79xx_pci.c
+++ b/sys/dev/disk/aic7xxx/aic79xx_pci.c
@@ -416,10 +416,12 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
 	if (error != 0)
 		return (error);
 
+	ahd_lock(ahd);
 	/*
 	 * Link this softc in with all other ahd instances.
 	 */
 	ahd_softc_insert(ahd);
+	ahd_unlock(ahd);
 	return (0);
 }
 
diff --git a/sys/dev/disk/aic7xxx/aic7xxx.c b/sys/dev/disk/aic7xxx/aic7xxx.c
index add0b68..febc516 100644
--- a/sys/dev/disk/aic7xxx/aic7xxx.c
+++ b/sys/dev/disk/aic7xxx/aic7xxx.c
@@ -3928,6 +3928,7 @@ ahc_alloc(void *platform_arg, char *name)
 		ahc_free(ahc);
 		ahc = NULL;
 	}
+	ahc_lockinit(ahc);
 	return (ahc);
 }
 
@@ -4006,22 +4007,6 @@ ahc_softc_insert(struct ahc_softc *ahc)
 	ahc->init_level++;
 }
 
-/*
- * Verify that the passed in softc pointer is for a
- * controller that is still configured.
- */
-struct ahc_softc *
-ahc_find_softc(struct ahc_softc *ahc)
-{
-	struct ahc_softc *list_ahc;
-
-	TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
-		if (list_ahc == ahc)
-			return (ahc);
-	}
-	return (NULL);
-}
-
 void
 ahc_set_unit(struct ahc_softc *ahc, int unit)
 {
@@ -4574,6 +4559,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
 #endif
 		next_scb->hscb = &scb_data->hscbs[scb_data->numscbs];
 		next_scb->hscb->tag = ahc->scb_data->numscbs;
+		aic_timer_init(&next_scb->io_timer);
 		SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs,
 				  next_scb, links.sle);
 		segs += AHC_NSEG;
@@ -5147,6 +5133,9 @@ ahc_intr_enable(struct ahc_softc *ahc, int enable)
 {
 	u_int hcntrl;
 
+	if (enable)
+		lwkt_serialize_handler_enable(&ahc->platform_data->serializer);
+
 	hcntrl = ahc_inb(ahc, HCNTRL);
 	hcntrl &= ~INTEN;
 	ahc->pause &= ~INTEN;
@@ -5157,6 +5146,8 @@ ahc_intr_enable(struct ahc_softc *ahc, int enable)
 		ahc->unpause |= INTEN;
 	}
 	ahc_outb(ahc, HCNTRL, hcntrl);
+	if (!enable)
+		lwkt_serialize_handler_disable(&ahc->platform_data->serializer);
 }
 
 /*
@@ -6988,8 +6979,6 @@ ahc_recover_commands(struct ahc_softc *ahc)
 	int	restart_needed;
 	u_int	last_phase;
 
-	ahc_lock();
-
 	/*
 	 * Pause the controller and manually flush any
 	 * commands that have just completed but that our
@@ -7009,7 +6998,6 @@ ahc_recover_commands(struct ahc_softc *ahc)
 		kprintf("%s: Timedout SCBs already complete. "
 		       "Interrupts may not be functioning.\n", ahc_name(ahc));
 		ahc_unpause(ahc);
-		ahc_unlock();
 		return;
 	}
 
@@ -7262,7 +7250,6 @@ bus_reset:
 		ahc_restart(ahc);
 	else
 		ahc_unpause(ahc);
-	ahc_unlock();
 }
 
 /************************* Target Mode ****************************************/
@@ -7399,10 +7386,8 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 		ahc_flag saved_flags;
 
 		kprintf("Configuring Target Mode\n");
-		ahc_lock();
 		if (LIST_FIRST(&ahc->pending_scbs) != NULL) {
 			ccb->ccb_h.status = CAM_BUSY;
-			ahc_unlock();
 			return;
 		}
 		saved_flags = ahc->flags;
@@ -7423,12 +7408,10 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 			ahc->flags = saved_flags;
 			(void)ahc_loadseq(ahc);
 			ahc_restart(ahc);
-			ahc_unlock();
 			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
 			return;
 		}
 		ahc_restart(ahc);
-		ahc_unlock();
 	}
 	cel = &ccb->cel;
 	target = ccb->ccb_h.target_id;
@@ -7487,7 +7470,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 		}
 		SLIST_INIT(&lstate->accept_tios);
 		SLIST_INIT(&lstate->immed_notifies);
-		ahc_lock();
 		ahc_pause(ahc);
 		if (target != CAM_TARGET_WILDCARD) {
 			tstate->enabled_luns[lun] = lstate;
@@ -7553,7 +7535,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 			ahc_outb(ahc, SCSISEQ, scsiseq);
 		}
 		ahc_unpause(ahc);
-		ahc_unlock();
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_print_path(ccb->ccb_h.path);
 		kprintf("Lun now enabled for target mode\n");
@@ -7566,8 +7547,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 			return;
 		}
 
-		ahc_lock();
-		
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
 			struct ccb_hdr *ccbh;
@@ -7577,7 +7556,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 			 && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
 				kprintf("CTIO pending\n");
 				ccb->ccb_h.status = CAM_REQ_INVALID;
-				ahc_unlock();
 				return;
 			}
 		}
@@ -7593,7 +7571,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 		}
 
 		if (ccb->ccb_h.status != CAM_REQ_CMP) {
-			ahc_unlock();
 			return;
 		}
 
@@ -7668,7 +7645,6 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
 			}
 		}
 		ahc_unpause(ahc);
-		ahc_unlock();
 	}
 }
 
diff --git a/sys/dev/disk/aic7xxx/aic7xxx.h b/sys/dev/disk/aic7xxx/aic7xxx.h
index 77cce33..65a1cb0 100644
--- a/sys/dev/disk/aic7xxx/aic7xxx.h
+++ b/sys/dev/disk/aic7xxx/aic7xxx.h
@@ -598,6 +598,7 @@ struct scb {
 	struct ahc_dma_seg 	 *sg_list;
 	bus_addr_t		  sg_list_phys;
 	u_int			  sg_count;/* How full ahc_dma_seg is */
+	aic_timer_t		  io_timer;
 };
 
 struct scb_data {
@@ -1225,7 +1226,6 @@ void			 ahc_pause_and_flushwork(struct ahc_softc *ahc);
 int			 ahc_suspend(struct ahc_softc *ahc); 
 int			 ahc_resume(struct ahc_softc *ahc);
 void			 ahc_softc_insert(struct ahc_softc *);
-struct ahc_softc	*ahc_find_softc(struct ahc_softc *ahc);
 void			 ahc_set_unit(struct ahc_softc *, int);
 void			 ahc_set_name(struct ahc_softc *, char *);
 int			 ahc_alloc_scbs(struct ahc_softc *ahc);
diff --git a/sys/dev/disk/aic7xxx/aic7xxx_osm.c b/sys/dev/disk/aic7xxx/aic7xxx_osm.c
index 8181836..0b66a6d 100644
--- a/sys/dev/disk/aic7xxx/aic7xxx_osm.c
+++ b/sys/dev/disk/aic7xxx/aic7xxx_osm.c
@@ -106,9 +106,9 @@ ahc_map_int(struct ahc_softc *ahc)
 	ahc->platform_data->irq_res_type = SYS_RES_IRQ;
 
 	/* Hook up our interrupt handler */
-	error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq,
-			       0, ahc_platform_intr, ahc,
-			       &ahc->platform_data->ih, NULL);
+	error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq, 0,
+			       ahc_platform_intr, ahc, &ahc->platform_data->ih,
+			       &ahc->platform_data->serializer);
 
 	if (error != 0)
 		device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n",
@@ -167,7 +167,7 @@ ahc_attach(struct ahc_softc *ahc)
 
 	ahc_controller_info(ahc, ahc_info);
 	kprintf("%s\n", ahc_info);
-	ahc_lock();
+	ahc_lock(ahc);
 
 	/*
 	 * Attach secondary channel first if the user has
@@ -267,6 +267,7 @@ fail:
 		ahc->platform_data->sim_b = sim2;
 		ahc->platform_data->path_b = path2;
 	}
+	ahc_unlock(ahc);
 
 	if (count != 0) {
 		/* We have to wait until after any system dumps... */
@@ -276,7 +277,6 @@ fail:
 		ahc_intr_enable(ahc, TRUE);
 	}
 
-	ahc_unlock();
 	return (count);
 }
 
@@ -289,6 +289,7 @@ ahc_platform_intr(void *arg)
 	struct	ahc_softc *ahc;
 
 	ahc = (struct ahc_softc *)arg; 
+	ASSERT_SERIALIZED(&ahc->platform_data->serializer);
 	ahc_intr(ahc);
 }
 
@@ -320,7 +321,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
 		ahc_run_untagged_queue(ahc, untagged_q);
 	}
 
-	callout_stop(&ccb->ccb_h.timeout_ch);
+	callout_stop(&scb->io_timer);
 
 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
 		bus_dmasync_op_t op;
@@ -384,8 +385,8 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
 			 * so reinstate the timeouts for all other pending
 			 * commands.
 			 */
-			 LIST_FOREACH(list_scb, &ahc->pending_scbs,
-				      pending_links) {
+			LIST_FOREACH(list_scb, &ahc->pending_scbs,
+				     pending_links) {
 
 				aic_scb_timer_reset(list_scb,
 						    aic_get_timeout(scb));
@@ -462,13 +463,11 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
 		}
 		if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
 
-			ahc_lock();
 			SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
 					  sim_links.sle);
 			ccb->ccb_h.status = CAM_REQ_INPROG;
 			if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0)
 				ahc_run_tqinfifo(ahc, /*paused*/FALSE);
-			ahc_unlock();
 			break;
 		}
 
@@ -498,17 +497,14 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
 		/*
 		 * get an scb to use.
 		 */
-		ahc_lock();
 		if ((scb = ahc_get_scb(ahc)) == NULL) {
 	
 			xpt_freeze_simq(sim, /*count*/1);
 			ahc->flags |= AHC_RESOURCE_SHORTAGE;
-			ahc_unlock();
 			ccb->ccb_h.status = CAM_REQUEUE_REQ;
 			xpt_done(ccb);
 			return;
 		}
-		ahc_unlock();
 		
 		hscb = scb->hscb;
 		
@@ -639,8 +635,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
 			break;
 		}
 		
-		ahc_lock();
-
 		if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
 			if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
 				*discenable |= devinfo.target_mask;
@@ -716,7 +710,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
 					 /*paused*/FALSE);
 		}
-		ahc_unlock();
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 #else
@@ -752,8 +745,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
 			break;
 		}
 		
-		ahc_lock();
-
 		if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) {
 			if ((cts->flags & CCB_TRANS_DISC_ENB) != 0)
 				*discenable |= devinfo.target_mask;
@@ -834,7 +825,6 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
 					 ppr_options, update_type,
 					 /*paused*/FALSE);
 		}
-		ahc_unlock();
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 #endif
@@ -844,10 +834,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
 	/* Get default/user set transfer settings for the target */
 	{
 
-		ahc_lock();
 		ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim),
 				      SIM_CHANNEL(ahc, sim), &ccb->cts);
-		ahc_unlock();
 		xpt_done(ccb);
 		break;
 	}
@@ -866,10 +854,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
 	{
 		int  found;
 		
-		ahc_lock();
 		found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim),
 					  /*initiate reset*/TRUE);
-		ahc_unlock();
 		if (bootverbose) {
 			xpt_print_path(SIM_PATH(ahc, sim));
 			kprintf("SCSI bus reset delivered. "
@@ -1077,14 +1063,12 @@ ahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
 		 * Revert to async/narrow transfers
 		 * for the next device.
 		 */
-		ahc_lock();
 		ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
 			      AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE);
 		ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL,
 				 /*period*/0, /*offset*/0, /*ppr_options*/0,
 				 AHC_TRANS_GOAL|AHC_TRANS_CUR,
 				 /*paused*/FALSE);
-		ahc_unlock();
 		break;
 	}
 	default:
@@ -1114,9 +1098,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 			aic_set_transaction_status(scb, CAM_REQ_CMP_ERR);
 		if (nsegments != 0)
 			bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
-		ahc_lock();
 		ahc_free_scb(ahc, scb);
-		ahc_unlock();
 		xpt_done(ccb);
 		return;
 	}
@@ -1189,9 +1171,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 					    CAM_REQ_TOO_BIG);
 					bus_dmamap_unload(ahc->buffer_dmat,
 							  scb->dmamap);
-					ahc_lock();
 					ahc_free_scb(ahc, scb);
-					ahc_unlock();
 					xpt_done(ccb);
 					return;
 				}
@@ -1214,8 +1194,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 	
 	scb->sg_count = nsegments;
 
-	ahc_lock();
-
 	/*
 	 * Last time we need to check if this SCB needs to
 	 * be aborted.
@@ -1224,7 +1202,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 		if (nsegments != 0)
 			bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
 		ahc_free_scb(ahc, scb);
-		ahc_unlock();
 		xpt_done(ccb);
 		return;
 	}
@@ -1275,7 +1252,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 		TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
 		scb->flags |= SCB_UNTAGGEDQ;
 		if (TAILQ_FIRST(untagged_q) != scb) {
-			ahc_unlock();
 			return;
 		}
 	}
@@ -1297,8 +1273,6 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
 	} else {
 		ahc_queue_scb(ahc, scb);
 	}
-
-	ahc_unlock();
 }
 
 static void
@@ -1330,9 +1304,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim,
 			 || (ccb_h->flags & CAM_CDB_PHYS) != 0) {
 				aic_set_transaction_status(scb,
 							   CAM_REQ_INVALID);
-				ahc_lock();
 				ahc_free_scb(ahc, scb);
-				ahc_unlock();
 				xpt_done((union ccb *)csio);
 				return;
 			}
@@ -1628,16 +1600,11 @@ ahc_detach(device_t dev)
 
 	device_printf(dev, "detaching device\n");
 	ahc = device_get_softc(dev);
-	ahc = ahc_find_softc(ahc);
-	if (ahc == NULL) {
-		device_printf(dev, "aic7xxx already detached\n");
-		return (ENOENT);
-	}
+	ahc_lock(ahc);
 	TAILQ_REMOVE(&ahc_tailq, ahc, links);
-	ahc_lock();
 	ahc_intr_enable(ahc, FALSE);
 	bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih);
-	ahc_unlock();
+	ahc_unlock(ahc);
 	ahc_free(ahc);
 	return (0);
 }
@@ -1674,6 +1641,7 @@ static int
 ahc_modevent(module_t mod, int type, void *data)
 {
 	/* XXX Deal with busy status on unload. */
+	/* XXX Deal with unknown events */
 	return 0;
 }
   
diff --git a/sys/dev/disk/aic7xxx/aic7xxx_osm.h b/sys/dev/disk/aic7xxx/aic7xxx_osm.h
index 193bef0..a73fc7a 100644
--- a/sys/dev/disk/aic7xxx/aic7xxx_osm.h
+++ b/sys/dev/disk/aic7xxx/aic7xxx_osm.h
@@ -126,6 +126,17 @@ extern devclass_t ahc_devclass;
 /* This driver supports target mode */
 #define AHC_TARGET_MODE 1
 
+/***************************** Core Includes **********************************/
+#ifdef AHC_REG_PRETTY_PRINT
+#define AIC_DEBUG_REGISTERS 1
+#else
+#define AIC_DEBUG_REGISTERS 0
+#endif
+#define	AIC_CORE_INCLUDE "aic7xxx.h"
+#define	AIC_LIB_PREFIX ahc
+#define	AIC_CONST_PREFIX AHC
+#include "aic_osm_lib.h"
+
 /************************** Softc/SCB Platform Data ***************************/
 struct ahc_platform_data {
 	/*
@@ -144,22 +155,12 @@ struct ahc_platform_data {
 	void			*ih;
 	eventhandler_tag	 eh;
 	struct thread		*recovery_thread;
+	struct lwkt_serialize	 serializer;
 };
 
 struct scb_platform_data {
 };
 
-/***************************** Core Includes **********************************/
-#ifdef AHC_REG_PRETTY_PRINT
-#define AIC_DEBUG_REGISTERS 1
-#else
-#define AIC_DEBUG_REGISTERS 0
-#endif
-#define	AIC_CORE_INCLUDE "aic7xxx.h"
-#define	AIC_LIB_PREFIX ahc
-#define	AIC_CONST_PREFIX AHC
-#include "aic_osm_lib.h"
-
 /*************************** Device Access ************************************/
 #define ahc_inb(ahc, port)				\
 	bus_space_read_1((ahc)->tag, (ahc)->bsh, port)
@@ -184,19 +185,26 @@ ahc_flush_device_writes(struct ahc_softc *ahc)
 
 /**************************** Locking Primitives ******************************/
 /* Lock protecting internal data structures */
-static __inline void ahc_lock(void);
-static __inline void ahc_unlock(void);
+static __inline void ahc_lockinit(struct ahc_softc *);
+static __inline void ahc_lock(struct ahc_softc *);
+static __inline void ahc_unlock(struct ahc_softc *);
+
+static __inline void
+ahc_lockinit(struct ahc_softc *ahc)
+{
+	lwkt_serialize_init(&ahc->platform_data->serializer);
+}
 
 static __inline void
-ahc_lock(void)
+ahc_lock(struct ahc_softc *ahc)
 {
-	crit_enter_id("ahc");
+	lwkt_serialize_enter(&ahc->platform_data->serializer);
 }
 
 static __inline void
-ahc_unlock(void)
+ahc_unlock(struct ahc_softc *ahc)
 {
-	crit_exit_id("ahc");
+	lwkt_serialize_exit(&ahc->platform_data->serializer);
 }
 
 /************************* Initialization/Teardown ****************************/
diff --git a/sys/dev/disk/aic7xxx/aic7xxx_pci.c b/sys/dev/disk/aic7xxx/aic7xxx_pci.c
index c4caf62..2129843 100644
--- a/sys/dev/disk/aic7xxx/aic7xxx_pci.c
+++ b/sys/dev/disk/aic7xxx/aic7xxx_pci.c
@@ -1045,10 +1045,12 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
 	if (error != 0)
 		return (error);
 
+	ahc_lock(ahc);
 	/*
 	 * Link this softc in with all other ahc instances.
 	 */
 	ahc_softc_insert(ahc);
+	ahc_unlock(ahc);
 	return (0);
 }
 
diff --git a/sys/dev/disk/aic7xxx/aic_osm_lib.c b/sys/dev/disk/aic7xxx/aic_osm_lib.c
index ff2568d..35ff4ae 100644
--- a/sys/dev/disk/aic7xxx/aic_osm_lib.c
+++ b/sys/dev/disk/aic7xxx/aic_osm_lib.c
@@ -57,7 +57,7 @@ aic_set_recoveryscb(struct aic_softc *aic, struct scb *scb)
 			union ccb *ccb;
 
 			ccb = list_scb->io_ctx;
-			callout_stop(&ccb->ccb_h.timeout_ch);
+			callout_stop(&scb->io_timer);
 		}
 	}
 }
@@ -68,9 +68,9 @@ aic_platform_timeout(void *arg)
 	struct	scb *scb;
 	
 	scb = (struct scb *)arg; 
-	aic_lock();
+	aic_lock(scb->aic_softc);
 	aic_timeout(scb);
-	aic_unlock();
+	aic_unlock(scb->aic_softc);
 }
 
 int
@@ -92,9 +92,7 @@ void
 aic_terminate_recovery_thread(struct aic_softc *aic)
 {
 
-	aic_lock();
 	if (aic->platform_data->recovery_thread == NULL) {
-		aic_unlock();
 		return;
 	}
 	aic->flags |= AIC_SHUTDOWN_RECOVERY;
@@ -103,8 +101,12 @@ aic_terminate_recovery_thread(struct aic_softc *aic)
 	 * Sleep on a slightly different location 
 	 * for this interlock just for added safety.
 	 */
+	crit_enter();
+	aic_lock(aic);
+	tsleep_interlock(aic->platform_data);
+	aic_unlock(aic);
 	tsleep(aic->platform_data, 0, "thtrm", 0);
-	aic_unlock();
+	crit_exit();
 }
 
 static void
@@ -112,29 +114,27 @@ aic_recovery_thread(void *arg)
 {
 	struct aic_softc *aic;
 
-#if __FreeBSD_version >= 500000
-	mtx_lock(&Giant);
-#endif
 	aic = (struct aic_softc *)arg;
-	aic_lock();
+	aic_lock(aic);
 	for (;;) {
 		
 		if (LIST_EMPTY(&aic->timedout_scbs) != 0
-		 && (aic->flags & AIC_SHUTDOWN_RECOVERY) == 0)
+		 && (aic->flags & AIC_SHUTDOWN_RECOVERY) == 0) {
+			crit_enter();
+			tsleep_interlock(aic);
+			aic_unlock(aic);
 			tsleep(aic, 0, "idle", 0);
+			crit_exit();
+			aic_lock(aic);
+		}
 
 		if ((aic->flags & AIC_SHUTDOWN_RECOVERY) != 0)
 			break;
 
-		aic_unlock();
 		aic_recover_commands(aic);
-		aic_lock();
 	}
 	aic->platform_data->recovery_thread = NULL;
 	wakeup(aic->platform_data);
-	aic_unlock();
-#if __FreeBSD_version >= 500000
-	mtx_unlock(&Giant);
-#endif
+	aic_unlock(aic);
 	kthread_exit();
 }
diff --git a/sys/dev/disk/aic7xxx/aic_osm_lib.h b/sys/dev/disk/aic7xxx/aic_osm_lib.h
index e402ba1..ce4e153 100644
--- a/sys/dev/disk/aic7xxx/aic_osm_lib.h
+++ b/sys/dev/disk/aic7xxx/aic_osm_lib.h
@@ -39,6 +39,8 @@
 /******************************** OS Includes *********************************/
 #if __FreeBSD_version >= 500000
 #include <sys/mutex.h>
+#else
+#include <sys/serialize.h>
 #endif
 
 /*************************** Library Symbol Mapping ***************************/
@@ -223,8 +225,7 @@ aic_scb_timer_reset(struct scb *scb, u_int msec)
 	time = msec;
 	time *= hz;
 	time /= 1000;
-	callout_reset(&scb->io_ctx->ccb_h.timeout_ch, time,
-		aic_platform_timeout, scb);
+	callout_reset(&scb->io_timer, time, aic_platform_timeout, scb);
 }
 
 static __inline void
@@ -233,13 +234,7 @@ aic_scb_timer_start(struct scb *scb)
 	
 	if (AIC_SCB_DATA(scb->aic_softc)->recovery_scbs == 0
 	 && scb->io_ctx->ccb_h.timeout != CAM_TIME_INFINITY) {
-		uint64_t time;
-
-		time = scb->io_ctx->ccb_h.timeout;
-		time *= hz;
-		time /= 1000;
-		callout_reset(&scb->io_ctx->ccb_h.timeout_ch, time,
-		    aic_platform_timeout, scb);
+		aic_scb_timer_reset(scb, scb->io_ctx->ccb_h.timeout);
 	}
 }
 

Attachment: pgp00001.pgp
Description: PGP signature



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]