PERFORCE change 118630 for review

Matt Jacob mjacob at FreeBSD.org
Mon Apr 23 02:52:04 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=118630

Change 118630 by mjacob at mjexp on 2007/04/23 02:51:22

	First blush at MPSAFE isp.

Affected files ...

.. //depot/projects/mjexp/sys/dev/isp/isp_freebsd.c#20 edit
.. //depot/projects/mjexp/sys/dev/isp/isp_freebsd.h#13 edit
.. //depot/projects/mjexp/sys/dev/isp/isp_pci.c#23 edit
.. //depot/projects/mjexp/sys/dev/isp/isp_sbus.c#12 edit

Differences ...

==== //depot/projects/mjexp/sys/dev/isp/isp_freebsd.c#20 (text+ko) ====

@@ -99,7 +99,9 @@
 #else
 static struct cdevsw isp_cdevsw = {
 	.d_version =	D_VERSION,
+#if	__FreeBSD_version < 700037
 	.d_flags =	D_NEEDGIANT,
+#endif
 	.d_ioctl =	ispioctl,
 	.d_name =	"isp",
 };
@@ -172,39 +174,6 @@
 	xpt_action((union ccb *)&csa);
 	isp->isp_sim = sim;
 	isp->isp_path = path;
-	/*
-	 * Create a kernel thread for fibre channel instances. We
-	 * don't have dual channel FC cards.
-	 */
-	if (IS_FC(isp)) {
-#if __FreeBSD_version >= 500000  
-		if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
-		    RFHIGHPID, 0, "%s: fc_thrd",
-		    device_get_nameunit(isp->isp_dev)))
-#else
-		if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
-		    "%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
-#endif
-		{
-			xpt_bus_deregister(cam_sim_path(sim));
-			cam_sim_free(sim, TRUE);
-			config_intrhook_disestablish(&isp->isp_osinfo.ehook);
-			isp_prt(isp, ISP_LOGERR, "could not create kthread");
-			return;
-		}
-		/*
-		 * We start by being "loop down" if we have an initiator role
-		 */
-		if (isp->isp_role & ISP_ROLE_INITIATOR) {
-			isp_freeze_loopdown(isp, "isp_attach");
-			isp->isp_osinfo.ldt =
-			    timeout(isp_ldt, isp, isp_quickboot_time * hz);
-			isp->isp_osinfo.ldt_running = 1;
-			isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
-			   "Starting Initial Loop Down Timer");
-		}
-	}
-
 
 	/*
 	 * If we have a second channel, construct SIM entry for that.
@@ -266,7 +235,46 @@
 		}
 		tmp->isp_osinfo.next = isp;
 	}
+	ISP_UNLOCK(isp);
 	isp_sysctl_update(isp);
+	ISP_LOCK(isp);
+
+	/*
+	 * Create a kernel thread for fibre channel instances.
+	 */
+	if (IS_FC(isp)) {
+		isp_callout_init(&isp->isp_osinfo.ldt);
+		isp_callout_init(&isp->isp_osinfo.gdt);
+		ISP_UNLOCK(isp);
+#if __FreeBSD_version >= 500000  
+		if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
+		    RFHIGHPID, 0, "%s: fc_thrd",
+		    device_get_nameunit(isp->isp_dev)))
+#else
+		if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
+		    "%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
+#endif
+		{
+			ISP_LOCK(isp);
+			xpt_bus_deregister(cam_sim_path(sim));
+			cam_sim_free(sim, TRUE);
+			config_intrhook_disestablish(&isp->isp_osinfo.ehook);
+			isp_prt(isp, ISP_LOGERR, "could not create kthread");
+			return;
+		}
+		ISP_LOCK(isp);
+		/*
+		 * We start by being "loop down" if we have an initiator role
+		 */
+		if (isp->isp_role & ISP_ROLE_INITIATOR) {
+			isp_freeze_loopdown(isp, "isp_attach");
+			isp->isp_osinfo.ldt_running = 1;
+			callout_reset(&isp->isp_osinfo.ldt,
+			    isp_quickboot_time * hz, isp_ldt, isp);
+			isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+			   "Starting Initial Loop Down Timer");
+		}
+	}
 }
 
 static void
@@ -677,9 +685,11 @@
 isp_intr_enable(void *arg)
 {
 	ispsoftc_t *isp = arg;
+	ISP_LOCK(isp);
 	if (isp->isp_role != ISP_ROLE_NONE) {
 		ISP_ENABLE_INTS(isp);
 	}
+	ISP_UNLOCK(isp);
 	/* Release our hook so that the boot can continue. */
 	config_intrhook_disestablish(&isp->isp_osinfo.ehook);
 }
@@ -2078,10 +2088,12 @@
 {
 	ispsoftc_t *isp;
 	XS_T *xs = arg;
-	for (isp = isplist; isp != NULL; isp = isp->isp_osinfo.next) {
-		if (isp_watchdog_work(isp, xs)) {
-			break;
-		}
+	int r;
+
+	for (r = 0, isp = isplist; r && isp; isp = isp->isp_osinfo.next) {
+		ISP_LOCK(isp);
+		r = isp_watchdog_work(isp, xs);
+		ISP_UNLOCK(isp);
 	}
 	if (isp == NULL) {
 		printf("isp_watchdog: nobody had %p active\n", arg);
@@ -2145,6 +2157,7 @@
 	fcportdb_t *lp;
 	int dbidx, tgt, more_to_do = 0;
 
+	ISP_LOCK(isp);
 	isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
 	for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
 		lp = &FCPARAM(isp)->portdb[dbidx];
@@ -2172,12 +2185,14 @@
 		isp_make_gone(isp, tgt);
 	}
 	if (more_to_do) {
-		isp->isp_osinfo.gdt = timeout(isp_gdt, isp, hz);
+		isp->isp_osinfo.gdt_running = 1;
+		callout_reset(&isp->isp_osinfo.gdt, hz, isp_gdt, isp);
 	} else {
 		isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
 		    "stopping Gone Device Timer");
 		isp->isp_osinfo.gdt_running = 0;
 	}
+	ISP_UNLOCK(isp);
 }
 
 /*
@@ -2196,6 +2211,8 @@
 	fcportdb_t *lp;
 	int dbidx, tgt;
 
+	ISP_LOCK(isp);
+
 	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
 
 	/*
@@ -2240,7 +2257,8 @@
 	 * to notice that fact (or make it false).
 	 */
 	isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
-	wakeup(&isp->isp_osinfo.kproc);
+	wakeup(ISP_KT_WCHAN(isp));
+	ISP_UNLOCK(isp);
 }
 
 static void
@@ -2250,8 +2268,10 @@
 	int slp = 0;
 #if __FreeBSD_version < 500000  
         int s = splcam();
+#elif __FreeBSD_version < 700037
+	mtx_lock(&Giant);
 #else
-	mtx_lock(&Giant);
+	mtx_lock(&isp->isp_osinfo.lock);
 #endif
 	/*
 	 * The first loop is for our usage where we have yet to have
@@ -2330,7 +2350,12 @@
 		}
 		isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
 		    "isp_kthread: sleep time %d", slp);
-		tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf", slp * hz);
+#if __FreeBSD_version < 700037
+		tsleep(ISP_KT_WCHAN(isp), PRIBIO, "ispf", slp * hz);
+#else
+		msleep(ISP_KT_WCHAN(isp), &isp->isp_osinfo.lock,
+		    PRIBIO, "ispf", slp * hz);
+#endif
 		/*
 		 * If slp is zero, we're waking up for the first time after
 		 * things have been okay. In this case, we set a deferral state
@@ -2342,29 +2367,35 @@
 			isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
 			    "isp_kthread: sleep hysteresis tick time %d",
 			    isp->isp_osinfo.hysteresis * hz);
+#if __FreeBSD_version < 700037
 			(void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
 			    (isp->isp_osinfo.hysteresis * hz));
+#else
+			(void) msleep(&isp_fabric_hysteresis,
+			    &isp->isp_osinfo.lock, PRIBIO, "ispT",
+			    (isp->isp_osinfo.hysteresis * hz));
+#endif
 		}
 	}
 #if __FreeBSD_version < 500000  
 	splx(s);
+#elif __FreeBSD_version < 700037
+	mtx_unlock(&Giant);
 #else
-	mtx_unlock(&Giant);
+	mtx_unlock(&isp->isp_osinfo.lock);
 #endif
 }
 
 static void
 isp_action(struct cam_sim *sim, union ccb *ccb)
 {
-	int bus, tgt, error, lim;
+	int bus, tgt, ts, error, lim;
 	ispsoftc_t *isp;
 	struct ccb_trans_settings *cts;
 
 	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
 	
 	isp = (ispsoftc_t *)cam_sim_softc(sim);
-	ccb->ccb_h.sim_priv.entries[0].field = 0;
-	ccb->ccb_h.sim_priv.entries[1].ptr = isp;
 	if (isp->isp_state != ISP_RUNSTATE &&
 	    ccb->ccb_h.func_code == XPT_SCSI_IO) {
 		isp_init(isp);
@@ -2380,7 +2411,7 @@
 		isp->isp_state = ISP_RUNSTATE;
 	}
 	isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
-
+	ISP_PCMD(ccb) = NULL;
 
 	switch (ccb->ccb_h.func_code) {
 	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
@@ -2407,30 +2438,34 @@
 			break;
 		}
 #endif
-		((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK;
+		ccb->csio.scsi_status = SCSI_STATUS_OK;
+		if (isp_get_pcmd(isp, ccb)) {
+			isp_prt(isp, ISP_LOGWARN, "out of PCMDs");
+			cam_freeze_devq(ccb->ccb_h.path);
+			cam_release_devq(ccb->ccb_h.path,
+			    RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
+			xpt_done(ccb);
+			break;
+		}
 		error = isp_start((XS_T *) ccb);
 		switch (error) {
 		case CMD_QUEUED:
 			XS_CMD_S_CLEAR(ccb);
 			ccb->ccb_h.status |= CAM_SIM_QUEUED;
-			if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
-				int ms = ccb->ccb_h.timeout;
-				if (ms == CAM_TIME_DEFAULT) {
-					ms = 60*1000;
-				}
-				ccb->ccb_h.timeout_ch =
-				    timeout(isp_watchdog, ccb, isp_mstohz(ms));
-			} else {
-				callout_handle_init(&ccb->ccb_h.timeout_ch);
+			if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
+				break;
+			}
+			ts = ccb->ccb_h.timeout;
+			if (ts == CAM_TIME_DEFAULT) {
+				ts = 60*1000;
 			}
+			ts = isp_mstohz(ts);
+			callout_reset(&PISP_PCMD(ccb)->wdog, ts,
+			    isp_watchdog, ccb);
 			break;
 		case CMD_RQLATER:
+			isp_free_pcmd(isp, ccb);
 			/*
-			 * This can only happen for Fibre Channel
-			 */
-			KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
-
-			/*
 			 * Handle initial and subsequent loop down cases
 			 */
 			if (FCPARAM(isp)->loop_seen_once == 0) {
@@ -2461,15 +2496,15 @@
 			xpt_done(ccb);
 			break;
 		case CMD_EAGAIN:
-			cam_freeze_devq(ccb->ccb_h.path);
-			cam_release_devq(ccb->ccb_h.path,
-			    RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
+			isp_free_pcmd(isp, ccb);
+			XS_SETERR(ccb, CAM_REQUEUE_REQ);
 			xpt_done(ccb);
 			break;
 		case CMD_COMPLETE:
 			isp_done((struct ccb_scsiio *) ccb);
 			break;
 		default:
+			isp_free_pcmd(isp, ccb);
 			isp_prt(isp, ISP_LOGERR,
 			    "What's this? 0x%x at %d in file %s",
 			    error, __LINE__, __FILE__);
@@ -2916,6 +2951,9 @@
 		if (error)
 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
 		else {
+			if (bootverbose) {
+				xpt_print(ccb->ccb_h.path, "reset bus\n");
+			}
 			if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
 				xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
 			else if (isp->isp_path != NULL)
@@ -3045,6 +3083,7 @@
 			    "finished command on borrowed time");
 		}
 		XS_CMD_S_CLEAR(sccb);
+		isp_free_pcmd(isp, (union ccb *) sccb);
 		xpt_done((union ccb *) sccb);
 	}
 }
@@ -3177,9 +3216,9 @@
 			isp_freeze_loopdown(isp, msg);
 		}
 		if (isp->isp_osinfo.ldt_running == 0) {
-			isp->isp_osinfo.ldt = timeout(isp_ldt, isp,
-			    isp->isp_osinfo.loop_down_limit * hz);
 			isp->isp_osinfo.ldt_running = 1;
+			callout_reset(&isp->isp_osinfo.ldt,
+			    isp->isp_osinfo.loop_down_limit * hz, isp_ldt, isp);
 			isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
 			   "starting Loop Down Timer");
 		}
@@ -3323,8 +3362,9 @@
 			if (isp->isp_osinfo.gdt_running == 0) {
 				isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
 				    "starting Gone Device Timer");
-				isp->isp_osinfo.gdt = timeout(isp_gdt, isp, hz);
 				isp->isp_osinfo.gdt_running = 1;
+				callout_reset(&isp->isp_osinfo.gdt, hz,
+				    isp_gdt, isp);
 			}
 			tgt = lp->ini_map_idx - 1;
 			isp_prt(isp, ISP_LOGCONFIG, prom2,
@@ -3361,12 +3401,11 @@
 			isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
 			   "Stopping Loop Down Timer");
 			isp->isp_osinfo.ldt_running = 0;
-			untimeout(isp_ldt, isp, isp->isp_osinfo.ldt);
-			callout_handle_init(&isp->isp_osinfo.ldt);
+			callout_stop(&isp->isp_osinfo.ldt);
 		}
 		isp_prt(isp, ISP_LOGINFO, msg);
 		isp_freeze_loopdown(isp, msg);
-		wakeup(&isp->isp_osinfo.kproc);
+		wakeup(ISP_KT_WCHAN(isp));
 		break;
 	}
 #ifdef	ISP_TARGET_MODE
@@ -3517,8 +3556,13 @@
 		isp->isp_osinfo.mbox_sleep_ok = 0;
 		isp->isp_osinfo.mbox_sleeping = 1;
 		for (olim = 0; olim < max; olim++) {
+#if __FreeBSD_version < 700037
 			tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep",
 			    isp_mstohz(ms));
+#else
+			msleep(&isp->isp_mbxworkp, &isp->isp_osinfo.lock,
+			    PRIBIO, "ispmbx_sleep", isp_mstohz(ms));
+#endif
 			if (isp->isp_osinfo.mboxcmd_done) {
 				break;
 			}
@@ -3587,3 +3631,20 @@
 	}
 	return (hz);
 }
+
+void
+isp_platform_intr(void *arg)
+{
+	ispsoftc_t *isp = arg;
+	uint32_t isr;
+	uint16_t sema, mbox;
+
+	ISP_LOCK(isp);
+	isp->isp_intcnt++;
+	if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
+		isp->isp_intbogus++;
+	} else {
+		isp_intr(isp, isr, sema, mbox);
+	}
+	ISP_UNLOCK(isp);
+}

==== //depot/projects/mjexp/sys/dev/isp/isp_freebsd.h#13 (text+ko) ====

@@ -87,8 +87,10 @@
 
 #if __FreeBSD_version < 500000  
 #define	ISP_IFLAGS	INTR_TYPE_CAM
+#elif __FreeBSD_version < 700037
+#define	ISP_IFLAGS	INTR_TYPE_CAM | INTR_ENTROPY
 #else
-#define	ISP_IFLAGS	INTR_TYPE_CAM | INTR_ENTROPY
+#define	ISP_IFLAGS	INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE
 #endif
 
 #if __FreeBSD_version < 700000
@@ -132,10 +134,23 @@
 		((lun) & (LUN_HASH_SIZE - 1)))
 #endif
 
+/*
+ * Per command info.
+ */
+struct isp_pcmd {
+	struct isp_pcmd *	next;
+	bus_dmamap_t 		dmap;	/* dma map for this command */
+	struct ispsoftc *	isp;	/* containing isp */
+	struct callout		wdog;	/* watchdog timer */
+};
+#define	ISP_PCMD(ccb)		(ccb)->ccb_h.spriv_ptr1
+#define	PISP_PCMD(ccb)		((struct isp_pcmd *)ISP_PCMD(ccb))
+
 struct isposinfo {
 	struct ispsoftc *	next;
 	bus_space_tag_t		bus_tag;
 	bus_space_handle_t	bus_handle;
+	bus_dma_tag_t		dmat;
 	uint64_t		default_port_wwn;
 	uint64_t		default_node_wwn;
 	uint32_t		default_id;
@@ -159,11 +174,14 @@
 		mbox_sleep_ok	: 1,
 		mboxcmd_done	: 1,
 		mboxbsy		: 1;
-	struct callout_handle 	ldt;	/* loop down timer */
-	struct callout_handle	gdt;	/* gone device timer */
-#if __FreeBSD_version >= 500000  
+	struct callout		ldt;	/* loop down timer */
+	struct callout		gdt;	/* gone device timer */
+#if __FreeBSD_version < 500000  
+	uint32_t		splcount;
+	uint32_t		splsaved;
+#else
+	struct mtx		lock;
 	const struct firmware *	fw;
-	struct mtx		lock;
 	union {
 		struct {
 			char wwnn[17];
@@ -176,6 +194,12 @@
 	bus_dmamap_t		cdmap;
 #define	isp_cdmat		isp_osinfo.cdmat
 #define	isp_cdmap		isp_osinfo.cdmap
+	/*
+	 * Per command information.
+	 */
+	struct isp_pcmd *	pcmd_pool;
+	struct isp_pcmd *	pcmd_free;
+
 #ifdef	ISP_TARGET_MODE
 #define	TM_WILDCARD_ENABLED	0x02
 #define	TM_TMODE_ENABLED	0x01
@@ -187,6 +211,7 @@
 	atio_private_data_t	atpdp[ATPDPSIZE];
 #endif
 };
+#define	ISP_KT_WCHAN(isp)	(&(isp)->isp_osinfo.kproc)
 
 #define	isp_lock	isp_osinfo.lock
 #define	isp_bus_tag	isp_osinfo.bus_tag
@@ -195,6 +220,25 @@
 /*
  * Locking macros...
  */
+#if __FreeBSD_version < 500000
+#define	ISP_LOCK(isp)						\
+	if (isp->isp_osinfo.splcount++ == 0) {			\
+		 isp->isp_osinfo.splsaved = splcam();		\
+	}
+#define	ISP_UNLOCK(isp)						\
+	if (isp->isp_osinfo.splcount > 1) {			\
+		isp->isp_osinfo.splcount--;			\
+	} else {						\
+		isp->isp_osinfo.splcount = 0;			\
+		splx(isp->isp_osinfo.splsaved);			\
+	}
+#elif	__FreeBSD_version < 700037
+#define	ISP_LOCK(isp)	do {} while (0)
+#define	ISP_UNLOCK(isp)	do {} while (0)
+#else
+#define	ISP_LOCK(isp)	mtx_lock(&isp->isp_osinfo.lock)
+#define	ISP_UNLOCK(isp)	mtx_unlock(&isp->isp_osinfo.lock)
+#endif
 
 /*
  * Required Macros/Defines
@@ -264,7 +308,7 @@
 
 #define	XS_T			struct ccb_scsiio
 #define	XS_DMA_ADDR_T		bus_addr_t
-#define	XS_ISP(ccb)		((ispsoftc_t *) (ccb)->ccb_h.spriv_ptr1)
+#define	XS_ISP(ccb)		cam_sim_softc(xpt_path_sim((ccb)->ccb_h.path))
 #define	XS_CHANNEL(ccb)		cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))
 #define	XS_TGT(ccb)		(ccb)->ccb_h.target_id
 #define	XS_LUN(ccb)		(ccb)->ccb_h.target_lun
@@ -465,6 +509,7 @@
 void isp_mbox_notify_done(ispsoftc_t *);
 void isp_mbox_release(ispsoftc_t *);
 int isp_mstohz(int);
+void isp_platform_intr(void *);
 
 /*
  * Platform Version specific defines
@@ -478,11 +523,16 @@
 #define	isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z)	\
 	bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
 	busdma_lock_mutex, &Giant, z)
+#elif __FreeBSD_version < 700037
+#define	BUS_DMA_ROOTARG(x)	bus_get_dma_tag(x)
+#define	isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z)	\
+	bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
+	busdma_lock_mutex, &Giant, z)
 #else
 #define	BUS_DMA_ROOTARG(x)	bus_get_dma_tag(x)
 #define	isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z)	\
 	bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
-	busdma_lock_mutex, &Giant, z)
+	busdma_lock_mutex, &isp->isp_osinfo.lock, z)
 #endif
 
 #if __FreeBSD_version < 700031
@@ -494,11 +544,14 @@
 
 #if __FreeBSD_version < 500000
 #define	isp_sim_alloc	cam_sim_alloc
+#define	isp_callout_init(x)	callout_init(x)
 #elif	__FreeBSD_version < 700037
+#define	isp_callout_init(x)	callout_init(x, 0)
 #define	isp_sim_alloc	cam_sim_alloc
 #else
+#define	isp_callout_init(x)	callout_init(x, 1)
 #define	isp_sim_alloc(a, b, c, d, e, f, g, h)	\
-	cam_sim_alloc(a, b, c, d, e, &Giant, f, g, h)
+	cam_sim_alloc(a, b, c, d, e, &(d)->isp_osinfo.lock, f, g, h)
 #endif
 
 /* Should be BUS_SPACE_MAXSIZE, but MAXPHYS is larger than BUS_SPACE_MAXSIZE */
@@ -507,6 +560,28 @@
 /*
  * Platform specific inline functions
  */
+static inline int isp_get_pcmd(ispsoftc_t *, union ccb *);
+static inline void isp_free_pcmd(ispsoftc_t *, union ccb *);
+
+static inline int
+isp_get_pcmd(ispsoftc_t *isp, union ccb *ccb)
+{
+	ISP_PCMD(ccb) = isp->isp_osinfo.pcmd_free;
+	if (ISP_PCMD(ccb) == NULL) {
+		return (-1);
+	}
+	isp->isp_osinfo.pcmd_free = ((struct isp_pcmd *)ISP_PCMD(ccb))->next;
+	return (0);
+}
+
+static inline void
+isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
+{
+	((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
+	isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
+	ISP_PCMD(ccb) = NULL;
+}
+
 
 /*
  * ISP General Library functions
@@ -514,10 +589,4 @@
 
 #include <dev/isp/isp_library.h>
 
-/*
- * XXX: Temp
- */
-#if	ISP_DEFAULT_ROLES == ISP_ROLE_BOTH
-#error	"Dual Role Temporarily Unsupported"
-#endif
 #endif	/* _ISP_FREEBSD_H */

==== //depot/projects/mjexp/sys/dev/isp/isp_pci.c#23 (text+ko) ====

@@ -338,7 +338,6 @@
 	void *				ih;
 	int16_t				pci_poff[_NREG_BLKS];
 	bus_dma_tag_t			dmat;
-	bus_dmamap_t			*dmaps;
 #if __FreeBSD_version > 700025
 	int				msicount;
 #endif
@@ -352,7 +351,6 @@
 	DEVMETHOD(device_detach,	isp_pci_detach),
 	{ 0, 0 }
 };
-static void isp_pci_intr(void *);
 
 static driver_t isp_pci_driver = {
 	"isp", isp_pci_methods, sizeof (struct isp_pcisoftc)
@@ -704,9 +702,6 @@
 		}
 	}
 
-	callout_handle_init(&isp->isp_osinfo.ldt);
-	callout_handle_init(&isp->isp_osinfo.gdt);
-
 	if (IS_SCSI(isp)) {
 		return;
 	}
@@ -1180,7 +1175,7 @@
 	locksetup++;
 #endif
 
-	if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_pci_intr, isp,
+	if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp,
 	    &pcs->ih)) {
 		device_printf(dev, "could not setup interrupt\n");
 		goto bad;
@@ -1203,53 +1198,47 @@
 	/*
 	 * Make sure we're in reset state.
 	 */
+	ISP_LOCK(isp);
 	isp_reset(isp);
 	if (isp->isp_state != ISP_RESETSTATE) {
+		ISP_UNLOCK(isp);
 		goto bad;
 	}
 	isp_init(isp);
 	if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_INITSTATE) {
 		isp_uninit(isp);
+		ISP_UNLOCK(isp);
 		goto bad;
 	}
 	isp_attach(isp);
 	if (isp->isp_role != ISP_ROLE_NONE && isp->isp_state != ISP_RUNSTATE) {
 		isp_uninit(isp);
+		ISP_UNLOCK(isp);
 		goto bad;
 	}
-	/*
-	 * XXXX: Here is where we might unload the f/w module
-	 * XXXX: (or decrease the reference count to it).
-	 */
-
+	ISP_UNLOCK(isp);
 	return (0);
 
 bad:
-
 	if (pcs && pcs->ih) {
 		(void) bus_teardown_intr(dev, irq, pcs->ih);
 	}
-
 #if __FreeBSD_version >= 500000  
 	if (locksetup && isp) {
 		mtx_destroy(&isp->isp_osinfo.lock);
 	}
 #endif
-
 	if (irq) {
 		(void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq);
 	}
-
 #if __FreeBSD_version > 700025
 	if (pcs && pcs->msicount) {
 		pci_release_msi(dev);
 	}
 #endif
-
 	if (regs) {
 		(void) bus_release_resource(dev, rtp, rgd, regs);
 	}
-
 	if (pcs) {
 		if (pcs->pci_isp.isp_param) {
 #ifdef	ISP_FW_CRASH_DUMP
@@ -1260,11 +1249,6 @@
 			free(pcs->pci_isp.isp_param, M_DEVBUF);
 		}
 	}
-
-	/*
-	 * XXXX: Here is where we might unload the f/w module
-	 * XXXX: (or decrease the reference count to it).
-	 */
 	return (ENXIO);
 }
 
@@ -1283,22 +1267,6 @@
 	return (0);
 }
 
-static void
-isp_pci_intr(void *arg)
-{
-	ispsoftc_t *isp = arg;
-	uint32_t isr;
-	uint16_t sema, mbox;
-
-	isp->isp_intcnt++;
-	if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
-		isp->isp_intbogus++;
-	} else {
-		isp_intr(isp, isr, sema, mbox);
-	}
-}
-
-
 #define	IspVirt2Off(a, x)	\
 	(((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \
 	_BLK_REG_SHFT] + ((x) & 0xfff))
@@ -1331,8 +1299,7 @@
 }
 
 static int
-isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp,
-    uint16_t *semap, uint16_t *mbp)
+isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp)
 {
 	uint16_t isr, sema;
 
@@ -1739,9 +1706,11 @@
 	if (isp->isp_rquest) {
 		return (0);
 	}
+	ISP_UNLOCK(isp);
 
 	if (isp->isp_maxcmds == 0) {
 		isp_prt(isp, ISP_LOGERR, "maxcmds not set");
+		ISP_LOCK(isp);
 		return (1);
 	}
 
@@ -1754,11 +1723,22 @@
 		slim = (1 << 24);
 	}
 
+	len = isp->isp_maxcmds * sizeof (struct isp_pcmd);
+	isp->isp_osinfo.pcmd_pool =
+		(struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+	if (isp->isp_osinfo.pcmd_pool == NULL) {
+		isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds");
+		ISP_LOCK(isp);
+		return (1);
+	}
+
 	/*
 	 * XXX: We don't really support 64 bit target mode for parallel scsi yet
 	 */
 #ifdef	ISP_TARGET_MODE
 	if (IS_SCSI(isp) && sizeof (bus_addr_t) > 4) {
+		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
+		ISP_LOCK(isp);
 		isp_prt(isp, ISP_LOGERR, "we cannot do DAC for SPI cards yet");
 		return (1);
 	}
@@ -1766,7 +1746,9 @@
 
 	if (isp_dma_tag_create(BUS_DMA_ROOTARG(pcs->pci_dev), 1, slim, llim,
 	    hlim, NULL, NULL, BUS_SPACE_MAXSIZE, ISP_NSEGS, slim, 0,
-	    &pcs->dmat)) {
+	    &isp->isp_osinfo.dmat)) {
+		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
+		ISP_LOCK(isp);
 		isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
 		return (1);
 	}
@@ -1775,6 +1757,8 @@
 	len = sizeof (XS_T **) * isp->isp_maxcmds;
 	isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
 	if (isp->isp_xflist == NULL) {
+		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
+		ISP_LOCK(isp);
 		isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
 		return (1);
 	}
@@ -1782,20 +1766,13 @@
 	len = sizeof (void **) * isp->isp_maxcmds;
 	isp->isp_tgtlist = (void **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
 	if (isp->isp_tgtlist == NULL) {
+		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
+		free(isp->isp_xflist, M_DEVBUF);
+		ISP_LOCK(isp);
 		isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array");
 		return (1);
 	}
 #endif
-	len = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
-	pcs->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF,  M_WAITOK);
-	if (pcs->dmaps == NULL) {
-		isp_prt(isp, ISP_LOGERR, "can't alloc dma map storage");
-		free(isp->isp_xflist, M_DEVBUF);
-#ifdef	ISP_TARGET_MODE
-		free(isp->isp_tgtlist, M_DEVBUF);
-#endif
-		return (1);
-	}
 
 	/*
 	 * Allocate and map the request, result queues, plus FC scratch area.
@@ -1810,16 +1787,17 @@
 	/*
 	 * Create a tag for the control spaces- force it to within 32 bits.
 	 */
-	if (isp_dma_tag_create(pcs->dmat, QENTRY_LEN, slim,
+	if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim,
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
 	    NULL, NULL, len, ns, slim, 0, &isp->isp_cdmat)) {
 		isp_prt(isp, ISP_LOGERR,
 		    "cannot create a dma tag for control spaces");
-		free(pcs->dmaps, M_DEVBUF);
+		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
 		free(isp->isp_xflist, M_DEVBUF);
 #ifdef	ISP_TARGET_MODE
 		free(isp->isp_tgtlist, M_DEVBUF);
 #endif
+		ISP_LOCK(isp);
 		return (1);
 	}
 
@@ -1828,25 +1806,35 @@
 		isp_prt(isp, ISP_LOGERR,
 		    "cannot allocate %d bytes of CCB memory", len);
 		bus_dma_tag_destroy(isp->isp_cdmat);
+		free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
 		free(isp->isp_xflist, M_DEVBUF);
 #ifdef	ISP_TARGET_MODE
 		free(isp->isp_tgtlist, M_DEVBUF);
 #endif
-		free(pcs->dmaps, M_DEVBUF);
+		ISP_LOCK(isp);
 		return (1);
 	}
 
 	for (i = 0; i < isp->isp_maxcmds; i++) {
-		error = bus_dmamap_create(pcs->dmat, 0, &pcs->dmaps[i]);
+		struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i];
+		error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap);
 		if (error) {
 			isp_prt(isp, ISP_LOGERR,
 			    "error %d creating per-cmd DMA maps", error);
 			while (--i >= 0) {
-				bus_dmamap_destroy(pcs->dmat, pcs->dmaps[i]);
+				bus_dmamap_destroy(isp->isp_osinfo.dmat,
+				    isp->isp_osinfo.pcmd_pool[i].dmap);
 			}
 			goto bad;
 		}
+		isp_callout_init(&pcmd->wdog);
+		if (i == isp->isp_maxcmds-1) {
+			pcmd->next = NULL;
+		} else {
+			pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1];
+		}
 	}
+	isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0];
 
 	im.isp = isp;
 	im.error = 0;
@@ -1864,6 +1852,7 @@
 		base += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
 		FCPARAM(isp)->isp_scratch = base;
 	}
+	ISP_LOCK(isp);
 	return (0);
 
 bad:
@@ -1873,8 +1862,9 @@
 #ifdef	ISP_TARGET_MODE
 	free(isp->isp_tgtlist, M_DEVBUF);
 #endif
-	free(pcs->dmaps, M_DEVBUF);
+	free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
 	isp->isp_rquest = NULL;
+	ISP_LOCK(isp);
 	return (1);
 }
 
@@ -1917,7 +1907,6 @@
 	mush_t *mp;
 	struct ccb_scsiio *csio;
 	ispsoftc_t *isp;
-	struct isp_pcisoftc *pcs;
 	bus_dmamap_t *dp;
 	ct_entry_t *cto, *qe;
 	uint8_t scsi_status;
@@ -1998,12 +1987,12 @@
 	cto->ct_resid = 0;
 	cto->ct_scsi_status = 0;
 
-	pcs = (struct isp_pcisoftc *)isp;
-	dp = &pcs->dmaps[isp_handle_index(handle & ISP_HANDLE_MASK)];
+	dp = &ISP_PCMD(csio)->dmap;
 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
-		bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
+		bus_dmamap_sync(isp->isp_osinfo.dmat, *dp, BUS_DMASYNC_PREREAD);
 	} else {
-		bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
+		bus_dmamap_sync(isp->isp_osinfo.dmat,
+		    *dp, BUS_DMASYNC_PREWRITE);
 	}
 
 	nxti = *mp->nxtip;
@@ -2369,7 +2358,6 @@
 	mush_t *mp;
 	ispsoftc_t *isp;
 	struct ccb_scsiio *csio;
-	struct isp_pcisoftc *pcs;
 	bus_dmamap_t *dp;
 	bus_dma_segment_t *eseg;
 	ispreqt7_t *rq;
@@ -2391,14 +2379,14 @@
 	csio = mp->cmd_token;
 	isp = mp->isp;
 	rq = mp->rq;
-	pcs = (struct isp_pcisoftc *)mp->isp;
-	dp = &pcs->dmaps[isp_handle_index(rq->req_handle & ISP_HANDLE_MASK)];
+	dp = &PISP_PCMD(csio)->dmap;
 	nxti = *mp->nxtip;
 
 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
-		bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
+		bus_dmamap_sync(isp->isp_osinfo.dmat, *dp, BUS_DMASYNC_PREREAD);
 	} else {
-		bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
+		bus_dmamap_sync(isp->isp_osinfo.dmat,
+		    *dp, BUS_DMASYNC_PREWRITE);
 	}
 	datalen = XS_XFRLEN(csio);
 
@@ -2476,7 +2464,6 @@
 	mush_t *mp;
 	ispsoftc_t *isp;
 	struct ccb_scsiio *csio;
-	struct isp_pcisoftc *pcs;
 	bus_dmamap_t *dp;
 	bus_dma_segment_t *eseg;
 	ispreq64_t *rq;
@@ -2497,14 +2484,14 @@
 	csio = mp->cmd_token;
 	isp = mp->isp;
 	rq = mp->rq;
-	pcs = (struct isp_pcisoftc *)mp->isp;
-	dp = &pcs->dmaps[isp_handle_index(rq->req_handle & ISP_HANDLE_MASK)];
+	dp = &PISP_PCMD(csio)->dmap;
 	nxti = *mp->nxtip;
 
 	if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
-		bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
+		bus_dmamap_sync(isp->isp_osinfo.dmat, *dp, BUS_DMASYNC_PREREAD);
 	} else {
-		bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
+		bus_dmamap_sync(isp->isp_osinfo.dmat,
+		    *dp, BUS_DMASYNC_PREWRITE);
 	}
 	datalen = XS_XFRLEN(csio);
 
@@ -2610,7 +2597,6 @@
 	mush_t *mp;
 	ispsoftc_t *isp;
 	struct ccb_scsiio *csio;
-	struct isp_pcisoftc *pcs;
 	bus_dmamap_t *dp;
 	bus_dma_segment_t *eseg;

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list