Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Nov 2006 05:14:43 GMT
From:      Matt Jacob <mjacob@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 109591 for review
Message-ID:  <200611090514.kA95Eha3084751@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=109591

Change 109591 by mjacob@newisp on 2006/11/09 05:14:05

	Add a loop down timer that will then cause devices to get
	marked lost if it expires. This is a tunable value that
	can be set.

Affected files ...

.. //depot/projects/newisp/dev/isp/isp_freebsd.c#21 edit
.. //depot/projects/newisp/dev/isp/isp_freebsd.h#13 edit
.. //depot/projects/newisp/dev/isp/isp_pci.c#17 edit
.. //depot/projects/newisp/dev/isp/ispvar.h#12 edit

Differences ...

==== //depot/projects/newisp/dev/isp/isp_freebsd.c#21 (text+ko) ====

@@ -50,12 +50,16 @@
 int isp_loop_down_limit = 300;	/* default loop down limit */
 int isp_quickboot_time = 5;	/* don't wait more than N secs for loop up */
 int isp_lost_device_time = 30;	/* grace time before reporting device lost */
+static const char *roles[4] = {
+    "(none)", "Target", "Initiator", "Target/Initiator"
+};
 
 static d_ioctl_t ispioctl;
 static void isp_intr_enable(void *);
 static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
 static void isp_poll(struct cam_sim *);
 static timeout_t isp_watchdog;
+static timeout_t isp_ldt;
 static void isp_kthread(void *);
 static void isp_action(struct cam_sim *, union ccb *);
 
@@ -633,12 +637,9 @@
 	struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev);
 
 	if (IS_SCSI(isp)) {
-		isp->isp_osinfo.sysctl_info.spi.iid = DEFAULT_IID(isp);
-		SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "iid",
-		    CTLFLAG_RD, &isp->isp_osinfo.sysctl_info.spi.iid, 0,
-		    "Initiator ID");
 		return;
 	}
+
 	snprintf(isp->isp_osinfo.sysctl_info.fc.wwnn,
 	    sizeof (isp->isp_osinfo.sysctl_info.fc.wwnn), "0x%08x%08x",
 	    (uint32_t) (ISP_NODEWWN(isp) >> 32), (uint32_t) ISP_NODEWWN(isp));
@@ -650,9 +651,21 @@
 	SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 	       "wwnn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwnn, 0,
 	       "World Wide Node Name");
+
 	SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 	       "wwpn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwpn, 0,
 	       "World Wide Port Name");
+
+	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "loop_down_time",
+	    CTLFLAG_RD, &isp->isp_osinfo.loop_down_time, 0,
+	    "How long Loop has been down");
+
+	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "loop_down_limit",
+	    CTLFLAG_RW, &isp->isp_osinfo.loop_down_limit, 0,
+	    "How long to wait for loop to come back up");
+
+	printf("loop_down %d loop_down_limit %d\n",
+	    isp->isp_osinfo.loop_down_time, isp->isp_osinfo.loop_down_limit);
 }
 #endif
 
@@ -2090,12 +2103,78 @@
 }
 
 static void
+isp_ldt(void *arg)
+{
+	ispsoftc_t *isp = arg;
+	fcportdb_t *lp;
+	static const char prom3[] =
+	    "PortID 0x%06x handle 0x%x role %s %s tgt %u because of %s\n"
+	    "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
+	struct cam_path *tmppath;
+	int dbidx, tgt;
+
+	isp_prt(isp, ISP_LOGALL, "LDT EXPIRED");
+	ISP_LOCK(isp);
+
+	/*
+	 * Notify to the OS all targets who we now consider have departed.
+	 */
+	for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
+		lp = &FCPARAM(isp)->portdb[dbidx];
+
+		if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
+			continue;
+		}
+		if (lp->ini_map_idx == 0) {
+			continue;
+		}
+
+		/*
+		 * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
+		 */
+
+		/*
+		 * Mark that we've announced that this device is gone....
+		 */
+		lp->reserved = 1;
+
+		/*
+		 * but *don't* change the state of the entry. Just clear
+		 * any target id stuff and announce to CAM that the
+		 * device is gone. This way any necessary PLOGO stuff
+		 * will happen when loop comes back up.
+		 */
+
+		tgt = lp->ini_map_idx - 1;
+		FCPARAM(isp)->isp_ini_map[tgt] = 0;
+		lp->ini_map_idx = 0;
+		isp_prt(isp, ISP_LOGCONFIG, prom3,
+		    lp->portid, lp->handle,
+		    roles[lp->roles & 0x3], "departed from", tgt,
+		    "LOOP Down Timeout",
+		    (uint32_t) (lp->node_wwn >> 32),
+		    (uint32_t) lp->node_wwn,
+		    (uint32_t) (lp->port_wwn >> 32),
+		    (uint32_t) lp->port_wwn);
+#if __FreeBSD_version >= 500000  
+		ISPLOCK_2_CAMLOCK(isp);
+		if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim),
+		    tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+			CAMLOCK_2_ISPLOCK(isp);
+			continue;
+		}
+		xpt_async(AC_LOST_DEVICE, tmppath, NULL);
+		xpt_free_path(tmppath);
+		CAMLOCK_2_ISPLOCK(isp);
+#endif
+	}
+}
+
+static void
 isp_kthread(void *arg)
 {
 	ispsoftc_t *isp = arg;
 	int slp;
-
-
 #if __FreeBSD_version < 500000  
         int s;
 
@@ -2796,15 +2875,13 @@
 isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
 {
 	int bus, rv = 0;
-	static const char *roles[4] = {
-	    "(none)", "Target", "Initiator", "Target/Initiator"
-	};
 	static const char prom[] =
 	    "PortID 0x%06x handle 0x%x role %s %s\n"
-            "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
+	    "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
 	static const char prom2[] =
 	    "PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
-            "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
+	    "      WWNN 0x%08x%08x WWPN 0x%08x%08x";
+	char *msg = NULL;
 	target_id_t tgt;
 	fcportdb_t *lp;
 	struct cam_path *tmppath;
@@ -2891,22 +2968,29 @@
 		}
 		break;
 	case ISPASYNC_LIP:
-		if (isp->isp_path) {
-			isp_freeze_loopdown(isp, "ISPASYNC_LIP");
+		if (msg == NULL) {
+			msg = "LIP Received";
 		}
-		isp_prt(isp, ISP_LOGINFO, "LIP Received");
-		break;
+		/* FALLTHROUGH */
 	case ISPASYNC_LOOP_RESET:
-		if (isp->isp_path) {
-			isp_freeze_loopdown(isp, "ISPASYNC_LOOP_RESET");
+		if (msg == NULL) {
+			msg = "LOOP Reset";
 		}
-		isp_prt(isp, ISP_LOGINFO, "Loop Reset Received");
-		break;
+		/* FALLTHROUGH */
 	case ISPASYNC_LOOP_DOWN:
+		if (msg == NULL) {
+			msg = "LOOP Down";
+		}
 		if (isp->isp_path) {
-			isp_freeze_loopdown(isp, "ISPASYNC_LOOP_DOWN");
+			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;
+isp_prt(isp, ISP_LOGALL, "LDT: starting loop down timer for %d seconds", isp->isp_osinfo.loop_down_limit);
 		}
-		isp_prt(isp, ISP_LOGINFO, "Loop DOWN");
+		isp_prt(isp, ISP_LOGINFO, msg);
 		break;
 	case ISPASYNC_LOOP_UP:
 		/*
@@ -2919,13 +3003,14 @@
 		break;
 	case ISPASYNC_DEV_ARRIVED:
 		lp = arg;
+		lp->reserved = 0;
 		if ((isp->isp_role & ISP_ROLE_INITIATOR) &&
 		    (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
 			int dbidx = lp - FCPARAM(isp)->portdb;
 			int i;
 
 			for (i = 0; i < MAX_FC_TARG; i++) {
-				if (i >= FL_ID || i <=  SNS_ID) {
+				if (i >= FL_ID && i <= SNS_ID) {
 					continue;
 				}
 				if (FCPARAM(isp)->isp_ini_map[i] == 0) {
@@ -3016,9 +3101,7 @@
 	case ISPASYNC_DEV_GONE:
 		lp = arg;
 		if (lp->ini_map_idx) {
-/*
- * XXX: HERE IS WHERE WE'D START A TIMER
- */
+			lp->reserved = 1;
 			tgt = lp->ini_map_idx - 1;
 			FCPARAM(isp)->isp_ini_map[tgt] = 0;
 			lp->ini_map_idx = 0;
@@ -3041,7 +3124,7 @@
 			xpt_free_path(tmppath);
 			CAMLOCK_2_ISPLOCK(isp);
 #endif
-		} else {
+		} else if (lp->reserved == 0) {
 			isp_prt(isp, ISP_LOGCONFIG, prom,
 			    lp->portid, lp->handle,
 		            roles[lp->roles & 0x3], "departed",
@@ -3049,6 +3132,7 @@
 			    (uint32_t) lp->node_wwn,
 		    	    (uint32_t) (lp->port_wwn >> 32),
 			    (uint32_t) lp->port_wwn);
+			lp->reserved = 1;
 		}
 		break;
 	case ISPASYNC_CHANGE_NOTIFY:
@@ -3061,6 +3145,11 @@
 		} else {
 			msg = "Other Change Notify";
 		}
+		if (isp->isp_osinfo.ldt_running) {
+			isp->isp_osinfo.ldt_running = 0;
+			untimeout(isp_ldt, isp, isp->isp_osinfo.ldt);
+			callout_handle_init(&isp->isp_osinfo.ldt);
+		}
 		isp_prt(isp, ISP_LOGINFO, msg);
 		isp_freeze_loopdown(isp, msg);
 #if __FreeBSD_version < 500000  

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

@@ -149,16 +149,18 @@
 	struct cam_sim		*sim2;
 	struct cam_path		*path2;
 	struct intr_config_hook	ehook;
-	uint16_t		loop_down_time;
-	uint16_t		loop_down_limit;
+	uint32_t		loop_down_time;
+	uint32_t		loop_down_limit;
 	uint32_t		: 5,
 		simqfrozen	: 3,
 		hysteresis	: 8,
-				: 4,
+				: 3,
+		ldt_running	: 1,
 		disabled	: 1,
 		fcbsy		: 1,
 		mboxcmd_done	: 1,
 		mboxbsy		: 1;
+	struct callout_handle 	ldt;	/* loop down timer */
 #if __FreeBSD_version >= 500000  
 	struct firmware *	fw;
 	struct mtx		lock;
@@ -168,9 +170,6 @@
 			char wwnn[17];
 			char wwpn[17];
 		} fc;
-		struct {
-			int iid;
-		} spi;
 	} sysctl_info;
 #endif
 	struct proc		*kproc;
@@ -204,10 +203,17 @@
 #define	CAMLOCK_2_ISPLOCK(isp)	\
 	mtx_unlock(&Giant); mtx_lock(&(isp)->isp_lock)
 #else
+#if __FreeBSD_version < 500000
 #define	ISP_LOCK(x)		do { } while (0)
 #define	ISP_UNLOCK(x)		do { } while (0)
 #define	ISPLOCK_2_CAMLOCK(isp)	do { } while (0)
 #define	CAMLOCK_2_ISPLOCK(isp)	do { } while (0)
+#else
+#define	ISP_LOCK(x)		GIANT_REQUIRED
+#define	ISP_UNLOCK(x)		do { } while (0)
+#define	ISPLOCK_2_CAMLOCK(isp)	do { } while (0)
+#define	CAMLOCK_2_ISPLOCK(isp)	GIANT_REQUIRED
+#endif
 #endif
 
 /*
@@ -404,8 +410,7 @@
 #include <dev/isp/isp_tpublic.h>
 #endif
 
-void isp_prt(ispsoftc_t *, int level, const char *, ...)
-	__printflike(3, 4);
+void isp_prt(ispsoftc_t *, int level, const char *, ...) __printflike(3, 4);
 /*
  * isp_osinfo definiitions && shorthand
  */

==== //depot/projects/newisp/dev/isp/isp_pci.c#17 (text+ko) ====

@@ -432,6 +432,8 @@
 	uint64_t wwn;
 	int bitmap, unit;
 
+	callout_handle_init(&isp->isp_osinfo.ldt);
+
 	unit = device_get_unit(dev);
 	if (getenv_int("isp_disable", &bitmap)) {
 		if (bitmap & (1 << unit)) {
@@ -578,6 +580,9 @@
 {
 	int tval;
 	const char *sptr;
+
+	callout_handle_init(&isp->isp_osinfo.ldt);
+
 	/*
 	 * Figure out if we're supposed to skip this one.
 	 */
@@ -733,7 +738,7 @@
 		isp->isp_osinfo.hysteresis = isp_fabric_hysteresis;
 	}
 
-	tval = 0;
+	tval = -1;
 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
 	    "loop_down_limit", &tval);
 	if (tval >= 0 && tval < 0xffff) {
@@ -795,7 +800,7 @@
 	isp = &pcs->pci_isp;
 
 	/*
-	 * Get Generic Options
+	 * Set and Get Generic Options
 	 */
 	isp_get_options(dev, isp);
 
@@ -814,7 +819,6 @@
 	 */
 	isp_get_pci_options(dev, &m1, &m2);
 
-
 	linesz = PCI_DFLT_LNSZ;
 	irq = regs = NULL;
 	rgd = rtp = iqd = 0;

==== //depot/projects/newisp/dev/isp/ispvar.h#12 (text+ko) ====

@@ -326,10 +326,10 @@
 	uint16_t	ini_map_idx	: 12,
 			autologin	: 1,	/* F/W does PLOGI/PLOGO */
 			state		: 3;
-	uint32_t			: 6,
+	uint32_t	reserved	: 6,
 			roles		: 2,
 			portid		: 24;
-	uint32_t			: 6,
+	uint32_t	new_reserved	: 6,
 			new_roles	: 2,
 			new_portid	: 24;
 	uint64_t	node_wwn;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611090514.kA95Eha3084751>