PERFORCE change 109812 for review

Matt Jacob mjacob at FreeBSD.org
Sun Nov 12 18:57:18 UTC 2006


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

Change 109812 by mjacob at newisp on 2006/11/12 18:56:32

	Macroize isp_mark_portdb so we can print out debugging aboutg
	where we invalidate the portdb. Add more SANCFG printouts.
	
	Add a ZOMBIE state to portdb entries- this is exempt from being
	marked by isp_mark_portdb. When we arrive in isp_pdb_sync and
	announce to the outer layers that a device is 'gone', it has the
	option of setting the portdb entry as being 'ZOMBIE' and setting
	a timer that will be used to clear the entry entirely or handle
	it arriving again before the timeout.
	
	For FreeBSD, implement both a loop down and a gone device timer.
	
	Add a isp_mstohz function.

Affected files ...

.. //depot/projects/newisp/dev/isp/isp.c#29 edit
.. //depot/projects/newisp/dev/isp/isp_freebsd.c#23 edit
.. //depot/projects/newisp/dev/isp/isp_freebsd.h#16 edit

Differences ...

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

@@ -60,6 +60,9 @@
  */
 
 #define	MBOX_DELAY_COUNT	1000000 / 100
+#define	ISP_MARK_PORTDB(a, b)	\
+    isp_prt(isp, ISP_LOGSANCFG, "line %d: markportdb", __LINE__); \
+    isp_mark_portdb(a, b)
 
 /*
  * Local static data
@@ -116,7 +119,7 @@
 static int isp_getpdb(ispsoftc_t *, uint16_t, isp_pdb_t *, int);
 static uint64_t isp_get_portname(ispsoftc_t *, int, int);
 static int isp_fclink_test(ispsoftc_t *, int);
-static const char *isp2100_fw_statename(int);
+static const char *ispfc_fw_statename(int);
 static int isp_pdb_sync(ispsoftc_t *);
 static int isp_scan_loop(ispsoftc_t *);
 static int isp_gid_ft_sns(ispsoftc_t *);
@@ -1172,7 +1175,7 @@
 		/*
 		 * Do this *before* initializing the firmware.
 		 */
-		isp_mark_portdb(isp, 0);
+		ISP_MARK_PORTDB(isp, 0);
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_NIL;
 
@@ -2053,7 +2056,6 @@
 	int i;
 
 	for (i = 0; i < MAX_FC_TARG; i++) {
-		fcp->isp_ini_map[i] = 0;
 		if (onprobation == 0) {
 			MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
 		} else {
@@ -2065,6 +2067,8 @@
 				fcp->portdb[i].state =
 					FC_PORTDB_STATE_PROBATIONAL;
 				break;
+			case FC_PORTDB_STATE_ZOMBIE:
+				break;
 			case FC_PORTDB_STATE_NIL:
 			default:
 				MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
@@ -2415,8 +2419,8 @@
 
 	fcp = isp->isp_param;
 
-	isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Entry");
-	isp_mark_portdb(isp, 1);
+	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Link Test Entry");
+	ISP_MARK_PORTDB(isp, 1);
 
 	/*
 	 * Wait up to N microseconds for F/W to go to a ready state.
@@ -2431,9 +2435,10 @@
 		GET_NANOTIME(&hra);
 		isp_fw_state(isp);
 		if (lwfs != fcp->isp_fwstate) {
-			isp_prt(isp, ISP_LOGINFO, "Firmware State <%s->%s>",
-			    isp2100_fw_statename((int)lwfs),
-			    isp2100_fw_statename((int)fcp->isp_fwstate));
+			isp_prt(isp, ISP_LOGCONFIG|ISP_LOGSANCFG,
+			    "Firmware State <%s->%s>",
+			    ispfc_fw_statename((int)lwfs),
+			    ispfc_fw_statename((int)fcp->isp_fwstate));
 			lwfs = fcp->isp_fwstate;
 		}
 		if (fcp->isp_fwstate == FW_READY) {
@@ -2485,7 +2490,7 @@
 	 * If we haven't gone to 'ready' state, return.
 	 */
 	if (fcp->isp_fwstate != FW_READY) {
-		isp_prt(isp, ISP_LOGDEBUG0,
+		isp_prt(isp, ISP_LOGSANCFG,
 		    "isp_fclink_test: not at FW_READY state");
 		return (-1);
 	}
@@ -2597,19 +2602,19 @@
 	/*
 	 * Announce ourselves, too.
 	 */
-	isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_portid,
+	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, topology, fcp->isp_portid,
 	    fcp->isp_loopid, toponames[fcp->isp_topo]);
-	isp_prt(isp, ISP_LOGCONFIG, ourwwn,
+	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, ourwwn,
 	    (uint32_t) (ISP_NODEWWN(isp) >> 32),
 	    (uint32_t) ISP_NODEWWN(isp),
 	    (uint32_t) (ISP_PORTWWN(isp) >> 32),
 	    (uint32_t) ISP_PORTWWN(isp));
-	isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Complete");
+	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Link Test Complete");
 	return (0);
 }
 
 static const char *
-isp2100_fw_statename(int state)
+ispfc_fw_statename(int state)
 {
 	switch(state) {
 	case FW_CONFIG_WAIT:	return "Config Wait";
@@ -2688,6 +2693,8 @@
 		}
 	}
 
+	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Synchronizing PDBs");
+
 	fcp->isp_loopstate = LOOP_SYNCING_PDB;
 
 	for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
@@ -2712,8 +2719,8 @@
 			/*
 			 * It's up to the outer layers to clear isp_ini_map.
 			 */
+			lp->state = FC_PORTDB_STATE_NIL;
 			isp_async(isp, ISPASYNC_DEV_GONE, lp);
-			lp->state = FC_PORTDB_STATE_NIL;
 			if (lp->autologin == 0) {
 				if (IS_24XX(isp)) {
 					int action =
@@ -2733,38 +2740,35 @@
 			}
 			lp->new_roles = 0;
 			lp->new_portid = 0;
+			/*
+			 * Note that we might come out of this with our state
+			 * set to FC_PORTDB_STATE_ZOMBIE.
+			 */
 			break;
 		case FC_PORTDB_STATE_NEW:
 			/*
-			 * If *we* have a new target dole and *it* has a target
-			 * role, assign a new target id to it.
+			 * It's up to the outer layers to assign a virtual
+			 * target id in isp_ini_map (if any).
 			 */
 			lp->portid = lp->new_portid;
 			lp->roles = lp->new_roles;
-			/*
-			 * It's up to the outer layers to assign a virtual
-			 * target id in isp_ini_map (if any).
-			 */
+			lp->state = FC_PORTDB_STATE_VALID;
 			isp_async(isp, ISPASYNC_DEV_ARRIVED, lp);
-			lp->state = FC_PORTDB_STATE_VALID;
 			lp->new_roles = 0;
 			lp->new_portid = 0;
+			lp->reserved = 0;
+			lp->new_reserved = 0;
 			break;
 		case FC_PORTDB_STATE_CHANGED:
-			/*
-			 * For now, just have a policy of accepting 'changed'
-			 * devices.
-			 */
-			lp->portid = lp->new_portid;
-			lp->roles = lp->new_roles;
-			if (lp->ini_map_idx) {
-				int t = lp->ini_map_idx - 1;
-				fcp->isp_ini_map[t] = dbidx + 1;
-			}
+/*
+ * XXXX FIX THIS
+ */
+			lp->state = FC_PORTDB_STATE_VALID;
 			isp_async(isp, ISPASYNC_DEV_CHANGED, lp);
-			lp->state = FC_PORTDB_STATE_VALID;
 			lp->new_roles = 0;
 			lp->new_portid = 0;
+			lp->reserved = 0;
+			lp->new_reserved = 0;
 			break;
 		case FC_PORTDB_STATE_PENDING_VALID:
 			lp->portid = lp->new_portid;
@@ -2773,15 +2777,20 @@
 				int t = lp->ini_map_idx - 1;
 				fcp->isp_ini_map[t] = dbidx + 1;
 			}
+			lp->state = FC_PORTDB_STATE_VALID;
 			isp_async(isp, ISPASYNC_DEV_STAYED, lp);
-			lp->state = FC_PORTDB_STATE_VALID;
 			if (dbidx != FL_ID) {
 				lp->new_roles = 0;
 				lp->new_portid = 0;
 			}
+			lp->reserved = 0;
+			lp->new_reserved = 0;
+			break;
+		case FC_PORTDB_STATE_ZOMBIE:
 			break;
 		default:
-			isp_prt(isp, ISP_LOGERR, "eh? state %d for idx %d",
+			isp_prt(isp, ISP_LOGWARN,
+			    "isp_scan_loop: state %d for idx %d",
 			    lp->state, dbidx);
 			isp_dump_portdb(isp);
 		}
@@ -2807,7 +2816,7 @@
 	fcparam *fcp = isp->isp_param;
 	int i;
 	isp_pdb_t pdb;
-	uint16_t dbidx, lim = 0;
+	uint16_t handle, lim = 0;
 
 	if (fcp->isp_fwstate < FW_READY ||
 	    fcp->isp_loopstate < LOOP_PDB_RCVD) {
@@ -2844,17 +2853,18 @@
 	}
 
 	fcp->isp_loopstate = LOOP_SCANNING_LOOP;
-	isp_prt(isp, ISP_LOGDEBUG0, "scanning loop 0..%d", lim-1);
+
+	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC scan loop 0..%d", lim-1);
 
 
 	/*
 	 * Run through the list and get the port database info for each one.
 	 */
-	for (dbidx = 0; dbidx < lim; dbidx++) {
+	for (handle = 0; handle < lim; handle++) {
 		/*
 		 * But don't even try for ourselves...
 	 	 */
-		if (dbidx == fcp->isp_loopid) {
+		if (handle == fcp->isp_loopid) {
 			continue;
 		}
 
@@ -2863,7 +2873,7 @@
 		 * known to hang. This trick gets around that problem.
 		 */
 		if (IS_2100(isp) || IS_2200(isp)) {
-			uint64_t node_wwn = isp_get_portname(isp, dbidx, 1);
+			uint64_t node_wwn = isp_get_portname(isp, handle, 1);
 			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
 				return (-1);
 			}
@@ -2875,29 +2885,29 @@
 		/*
 		 * Get the port database entity for this index.
 		 */
-		if (isp_getpdb(isp, dbidx, &pdb, 1) != 0) {
+		if (isp_getpdb(isp, handle, &pdb, 1) != 0) {
 			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
-				isp_mark_portdb(isp, 1);
+				ISP_MARK_PORTDB(isp, 1);
 				return (-1);
 			}
 			continue;
 		}
 
 		if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
-			isp_mark_portdb(isp, 1);
+			ISP_MARK_PORTDB(isp, 1);
 			return (-1);
 		}
 
 		/*
 		 * On *very* old 2100 firmware we would end up sometimes
 		 * with the firmware returning the port database entry
-		 * for something else. We used to restart locally, but
-		 * now we punt.
+		 * for something else. We used to restart this, but
+		 * now we just punt.
 		 */
-		if (IS_2100(isp) && pdb.handle != dbidx) {
+		if (IS_2100(isp) && pdb.handle != handle) {
 			isp_prt(isp, ISP_LOGWARN,
 			    "giving up on synchronizing the port database");
-			isp_mark_portdb(isp, 1);
+			ISP_MARK_PORTDB(isp, 1);
 			return (-1);
 		}
 
@@ -2916,8 +2926,7 @@
 		 * which shift on a loop.
 		 */
 		if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) {
-			isp_prt(isp, ISP_LOGWARN,
-			    "bad pdb entry at loop %d", dbidx);
+			isp_prt(isp, ISP_LOGWARN, "bad pdb @ loop %d", handle);
 			isp_dump_portdb(isp);
 			continue;
 		}
@@ -2940,22 +2949,27 @@
 
 			/*
 			 * Okay- we've found a non-nil entry that matches.
-			 * Check to make sure it's probational.
+			 * Check to make sure it's probational or a zombie.
 			 */
-			if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
+			if (lp->state != FC_PORTDB_STATE_PROBATIONAL &&
+			    lp->state != FC_PORTDB_STATE_ZOMBIE) {
 				isp_prt(isp, ISP_LOGERR,
-				    "portdb entry %d not probational (0x%x)",
+				    "[%d] not probational/zombie (0x%x)",
 				    i, lp->state);
 				isp_dump_portdb(isp);
-				isp_mark_portdb(isp, 1);
+				ISP_MARK_PORTDB(isp, 1);
 				return (-1);
 			}
 
+			/*
+			 * Mark the device as something the f/w logs into
+			 * automatically.
+			 */
 			lp->autologin = 1;
+
 			/*
-			 * Check to make sure it's really the same
-			 * device and update the initiator map before
-			 * we mark it as pending valid.
+			 * Check to make see if really still the same
+			 * device. If it is, we mark it pending valid.
 			 */
 			if (lp->portid == tmp.portid &&
 			    lp->handle == tmp.handle &&
@@ -2963,12 +2977,15 @@
 				lp->new_portid = tmp.portid;
 				lp->new_roles = tmp.roles;
 				lp->state = FC_PORTDB_STATE_PENDING_VALID;
+				isp_prt(isp, ISP_LOGSANCFG,
+				    "Loop Port 0x%06x at 0x%x Pending Valid",
+				    tmp.portid, tmp.handle);
 				break;
 			}
 		
 			/*
-			 * We can wipe out the old handle value here because
-			 * it's no longer valid.
+			 * We can wipe out the old handle value
+			 * here because it's no longer valid.
 			 */
 			lp->handle = tmp.handle;
 
@@ -2976,6 +2993,9 @@
 			 * Claim that this has changed and let somebody else
 			 * decide what to do.
 			 */
+			isp_prt(isp, ISP_LOGSANCFG,
+			    "Loop Port 0x%06x at 0x%x changed",
+			    tmp.portid, tmp.handle);
 			lp->state = FC_PORTDB_STATE_CHANGED;
 			lp->new_portid = tmp.portid;
 			lp->new_roles = tmp.roles;
@@ -2999,23 +3019,23 @@
 			}
 		}
 		if (i == MAX_FC_TARG) {
-			isp_prt(isp, ISP_LOGERR,
-			    "could not find slot for new entry");
+			isp_prt(isp, ISP_LOGERR, "out of portdb entries");
 			continue;
 		}
 		lp = &fcp->portdb[i];
 
+		MEMZERO(lp, sizeof (fcportdb_t));
 		lp->autologin = 1;
 		lp->state = FC_PORTDB_STATE_NEW;
-		lp->portid = 0;
-		lp->roles = 0;
 		lp->new_portid = tmp.portid;
 		lp->new_roles = tmp.roles;
 		lp->handle = tmp.handle;
 		lp->port_wwn = tmp.port_wwn;
 		lp->node_wwn = tmp.node_wwn;
+		isp_prt(isp, ISP_LOGSANCFG,
+		    "Loop Port 0x%06x at 0x%x is New Entry",
+		    tmp.portid, tmp.handle);
 	}
-
 	fcp->isp_loopstate = LOOP_LSCAN_DONE;
 	return (0);
 }
@@ -3196,7 +3216,7 @@
 	int portidx, portlim, r;
 	sns_gid_ft_rsp_t *rs0, *rs1;
 
-	isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric");
+	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Scan Fabric");
 	if (fcp->isp_fwstate != FW_READY ||
 	    fcp->isp_loopstate < LOOP_LSCAN_DONE) {
 		return (-1);
@@ -3206,7 +3226,8 @@
 	}
 	if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) {
 		fcp->isp_loopstate = LOOP_FSCAN_DONE;
-		isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric Done (no fabric)");
+		isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+		    "FC Scan Fabric Done (no fabric)");
 		return (0);
 	}
 
@@ -3241,7 +3262,7 @@
 		int level;
 		if (rs1->snscb_cthdr.ct_reason == 9 &&
 		    rs1->snscb_cthdr.ct_explanation == 7) {
-			level = ISP_LOGDEBUG0;
+			level = ISP_LOGSANCFG|ISP_LOGDEBUG0;
 		} else {
 			level = ISP_LOGWARN;
 		}
@@ -3286,8 +3307,8 @@
 		    "fabric too big for scratch area: increase ISP2100_SCRLEN");
 	}
 	portlim = portidx + 1;
-	isp_prt(isp, ISP_LOGDEBUG0, "got %d ports back from name server",
-	    portlim);
+	isp_prt(isp, ISP_LOGSANCFG,
+	    "got %d ports back from name server", portlim);
 
 	for (portidx = 0; portidx < portlim; portidx++) {
 		int npidx;
@@ -3311,7 +3332,7 @@
 			rs1->snscb_ports[npidx].portid[0] = 0;
 			rs1->snscb_ports[npidx].portid[1] = 0;
 			rs1->snscb_ports[npidx].portid[2] = 0;
-			isp_prt(isp, ISP_LOGDEBUG0,
+			isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
 			    "removing duplicate PortID 0x%x entry from list",
 			    portid);
 		}
@@ -3344,7 +3365,7 @@
 		    ((rs1->snscb_ports[portidx].portid[2]));
 
 		if (portid == 0) {
-			isp_prt(isp, ISP_LOGDEBUG0,
+			isp_prt(isp, ISP_LOGSANCFG,
 			    "skipping null PortID at idx %d", portidx);
 			continue;
 		}
@@ -3353,15 +3374,18 @@
 		 * Skip ourselves...
 		 */
 		if (portid == fcp->isp_portid) {
-			isp_prt(isp, ISP_LOGDEBUG0,
+			isp_prt(isp, ISP_LOGSANCFG,
 			    "skip ourselves @ PortID 0x%06x", portid);
 			continue;
 		}
-		isp_prt(isp, ISP_LOGDEBUG0, "Fabric Port 0x%06x", portid);
+		isp_prt(isp, ISP_LOGSANCFG,
+		    "Checking Fabric Port 0x%06x", portid);
 
 		/*
 		 * We now search our Port Database for any
-		 * probational entries with this PortID.
+		 * probational entries with this PortID. We don't
+		 * look for zombies here- only probational
+		 * entries (we've already logged out of zombies).
 		 */
 		for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
 			lp = &fcp->portdb[dbidx];
@@ -3402,12 +3426,15 @@
 			r = isp_getpdb(isp, lp->handle, &pdb, 0);
 			if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
 				FC_SCRATCH_RELEASE(isp);
-				isp_mark_portdb(isp, 1);
+				ISP_MARK_PORTDB(isp, 1);
 				return (-1);
 			}
 			if (r != 0) {
 				lp->new_portid = portid;
 				lp->state = FC_PORTDB_STATE_DEAD;
+				isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+				    "Fabric Port 0x%06x considered dead",
+				    portid);
 				continue;
 			}
 
@@ -3424,8 +3451,8 @@
 			    pdb.portid != portid ||
 			    wwpn != lp->port_wwn ||
 			    wwnn != lp->node_wwn) {
-				isp_prt(isp, ISP_LOGDEBUG0, fconf, dbidx,
-				    pdb.handle, pdb.portid,
+				isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+				    fconf, dbidx, pdb.handle, pdb.portid,
 				    (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
 				    (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
 				    lp->handle, portid,
@@ -3448,7 +3475,7 @@
 					if (fcp->isp_loopstate !=
 					    LOOP_SCANNING_FABRIC) {
 						FC_SCRATCH_RELEASE(isp);
-						isp_mark_portdb(isp, 1);
+						ISP_MARK_PORTDB(isp, 1);
 						return (-1);
 					}
 					continue;
@@ -3486,8 +3513,13 @@
 			lp->new_roles = nr;
 			if (pdb.portid != lp->portid || nr != lp->roles ||
 			    handle_changed) {
+				isp_prt(isp, ISP_LOGSANCFG,
+				    "Fabric Port 0x%06x changed", portid);
 				lp->state = FC_PORTDB_STATE_CHANGED;
 			} else {
+				isp_prt(isp, ISP_LOGSANCFG,
+				    "Fabric Port 0x%06x Now Pending Valid",
+				    portid);
 				lp->state = FC_PORTDB_STATE_PENDING_VALID;
 			}
 			continue;
@@ -3495,49 +3527,54 @@
 
 		/*
 		 * Ah- a new entry. Search the database again for all non-NIL
-		 * entries to make sure we never ever make a database entry
-		 * with the same port id.
+		 * entries to make sure we never ever make a new database entry
+		 * with the same port id. While we're at it, mark where the
+		 * last free entry was.
 		 */
-		for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
-			if (dbidx >= FL_ID && dbidx <= SNS_ID) {
+	
+		dbidx = MAX_FC_TARG;
+		for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
+			if (lp >= &fcp->portdb[FL_ID] &&
+			    lp <= &fcp->portdb[SNS_ID]) {
+				continue;
+			}
+			if (lp->state == FC_PORTDB_STATE_NIL) {
+				if (dbidx == MAX_FC_TARG) {
+					dbidx = lp - fcp->portdb;
+				}
 				continue;
 			}
-			if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
+			if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
 				continue;
 			}
-			if (fcp->portdb[dbidx].portid == portid) {
+			if (lp->portid == portid) {
 				break;
 			}
 		}
 
-		if (dbidx != MAX_FC_TARG) {
+		if (lp < &fcp->portdb[MAX_FC_TARG]) {
 			isp_prt(isp, ISP_LOGWARN,
 			    "PortID 0x%06x already at %d handle %d state %d",
-			    portid, dbidx, fcp->portdb[dbidx].handle,
-			    fcp->portdb[dbidx].state);
+			    portid, dbidx, lp->handle, lp->state);
 			continue;
 		}
 
 		/*
-		 * Find an empty database entry for it.
+		 * We should have the index of the first free entry seen.
 		 */
-		for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
-			if (dbidx >= FL_ID && dbidx <= SNS_ID) {
-				continue;
-			}
-			if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
-				break;
-			}
-		}
-
 		if (dbidx == MAX_FC_TARG) {
 			isp_prt(isp, ISP_LOGERR,
-			    "port database too small to login fabric device"
-			    "- increase MAX_FC_TARG");
+			    "port database too small to login PortID 0x%06x"
+			    "- increase MAX_FC_TARG", portid);
 			continue;
 		}
 
 		/*
+		 * Otherwise, point to our new home.
+		 */
+		lp = &fcp->portdb[dbidx];
+
+		/*
 		 * Try to see if we are logged into this device,
 		 * and maybe log into it.
 		 *
@@ -3547,7 +3584,7 @@
 		if (isp_login_device(isp, portid, &pdb, &oldhandle)) {
 			if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
 				FC_SCRATCH_RELEASE(isp);
-				isp_mark_portdb(isp, 1);
+				ISP_MARK_PORTDB(isp, 1);
 				return (-1);
 			}
 			continue;
@@ -3563,13 +3600,11 @@
 		 * that we do not make more than one entry that has the same
 		 * WWNN/WWPN duple
 		 */
-		lp = &fcp->portdb[dbidx];
-
 		for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
-			if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
+			if (dbidx >= FL_ID && dbidx <= SNS_ID) {
 				continue;
 			}
-			if (dbidx >= FL_ID && dbidx <= SNS_ID) {
+			if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
 				continue;
 			}
 			if (fcp->portdb[dbidx].node_wwn == wwnn &&
@@ -3578,33 +3613,61 @@
 			}
 		}
 
-		if (dbidx != MAX_FC_TARG) {
+		if (dbidx == MAX_FC_TARG) {
+			MEMZERO(lp, sizeof (fcportdb_t));
+			lp->handle = handle;
+			lp->node_wwn = wwnn;
+			lp->port_wwn = wwpn;
+			lp->new_portid = portid;
+			lp->new_roles = nr;
+			lp->state = FC_PORTDB_STATE_NEW;
+			isp_prt(isp, ISP_LOGSANCFG,
+			    "Fabric Port 0x%06x is New Entry", portid);
+			continue;
+		}
+
+    		if (fcp->portdb[dbidx].state != FC_PORTDB_STATE_ZOMBIE) {
 			isp_prt(isp, ISP_LOGWARN,
 			    "PortID 0x%x 0x%08x%08x/0x%08x%08x %ld already at "
-			    "idx %d", portid,
+			    "idx %d, state 0x%x", portid,
 			    (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
 			    (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
-			    (long) (lp - fcp->portdb), dbidx);
+			    (long) (lp - fcp->portdb), dbidx,
+			    fcp->portdb[dbidx].state);
 			continue;
 		}
 
+		/*
+		 * We found a zombie entry that matches us.
+		 * Revive it. We know that WWN and WWPN
+		 * are the same. For fabric devices, we
+		 * don't care that handle is different
+		 * as we assign that. If role or portid
+		 * are different, it maybe a changed device.
+		 */
+		lp = &fcp->portdb[dbidx];
 		lp->handle = handle;
-		lp->ini_map_idx = 0;
-		lp->node_wwn = wwnn;
-		lp->port_wwn = wwpn;
 		lp->new_portid = portid;
 		lp->new_roles = nr;
-		lp->state = FC_PORTDB_STATE_NEW;
+		if (lp->portid != portid || lp->roles != nr) {
+			isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+			    "Zombie Fabric Port 0x%06x Now Changed", portid);
+			lp->state = FC_PORTDB_STATE_CHANGED;
+		} else {
+			isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+			    "Zombie Fabric Port 0x%06x Now Pending Valid",
+			    portid);
+			lp->state = FC_PORTDB_STATE_PENDING_VALID;
+		}
 	}
 
-
 	FC_SCRATCH_RELEASE(isp);
 	if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		return (-1);
 	}
 	fcp->isp_loopstate = LOOP_FSCAN_DONE;
-	isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric Done");
+	isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Scan Fabric Done");
 	return (0);
 }
 
@@ -3674,7 +3737,7 @@
 	}
 
 	if (i == lim) {
-		isp_prt(isp, ISP_LOGINFO, "PLOGI 0x%06x failed", portid);
+		isp_prt(isp, ISP_LOGWARN, "PLOGI 0x%06x failed", portid);
 		return (-1);
 	}
 
@@ -3832,14 +3895,16 @@
 	FC_SCRATCH_RELEASE(isp);
 
 	if (ct->ct_cmd_resp == LS_RJT) {
-		isp_prt(isp, ISP_LOGWARN, "Register FC4 Type rejected");
+		isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+		    "Register FC4 Type rejected");
 		return (-1);
 	} else if (ct->ct_cmd_resp == LS_ACC) {
-		isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 Type accepted");
+		isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+		    "Register FC4 Type accepted");
 		return(0);
 	} else {
 		isp_prt(isp, ISP_LOGWARN,
-		    "Register FC4 Type: %x", ct->ct_cmd_resp);
+		    "Register FC4 Type: 0x%x", ct->ct_cmd_resp);
 		return (-1);
 	}
 }
@@ -3934,9 +3999,12 @@
 	if (IS_FC(isp)) {
 		fcparam *fcp = isp->isp_param;
 
+		/*
+		 * Try again later.
+		 */
 		if (fcp->isp_fwstate != FW_READY ||
 		    fcp->isp_loopstate != LOOP_READY) {
-			return (CMD_RQLATER);
+			return (CMD_EAGAIN);
 		}
 
 		if (XS_TGT(xs) >= MAX_FC_TARG) {
@@ -3951,6 +4019,13 @@
 			XS_SETERR(xs, HBA_SELTIMEOUT);
 			return (CMD_COMPLETE);
 		}
+		if (fcp->portdb[hdlidx].state == FC_PORTDB_STATE_ZOMBIE) {
+			return (CMD_RQLATER);
+		}
+		if (fcp->portdb[hdlidx].state != FC_PORTDB_STATE_VALID) {
+			XS_SETERR(xs, HBA_SELTIMEOUT);
+			return (CMD_COMPLETE);
+		}
 		target = fcp->portdb[hdlidx].handle;
 	}
 
@@ -5111,7 +5186,7 @@
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
 		isp->isp_sendmarker = 1;
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		isp_async(isp, ISPASYNC_LIP, NULL);
 #ifdef	ISP_TARGET_MODE
 		if (isp_target_async(isp, bus, mbox)) {
@@ -5147,7 +5222,7 @@
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		isp_async(isp, ISPASYNC_LOOP_UP, NULL);
 #ifdef	ISP_TARGET_MODE
 		if (isp_target_async(isp, bus, mbox)) {
@@ -5160,7 +5235,7 @@
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_NIL;
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		isp_async(isp, ISPASYNC_LOOP_DOWN, NULL);
 #ifdef	ISP_TARGET_MODE
 		if (isp_target_async(isp, bus, mbox)) {
@@ -5173,7 +5248,7 @@
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_NIL;
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		isp_async(isp, ISPASYNC_LOOP_RESET, NULL);
 #ifdef	ISP_TARGET_MODE
 		if (isp_target_async(isp, bus, mbox)) {
@@ -5185,7 +5260,7 @@
 	case ASYNC_PDB_CHANGED:
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_PDB);
 		break;
 
@@ -5195,12 +5270,12 @@
 		} else {
 			FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
 		}
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_SNS);
 		break;
 
 	case ASYNC_PTPMODE:
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		isp->isp_sendmarker = 1;
 		FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
 		FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
@@ -5215,7 +5290,7 @@
 
 	case ASYNC_CONNMODE:
 		mbox = ISP_READ(isp, OUTMAILBOX1);
-		isp_mark_portdb(isp, 1);
+		ISP_MARK_PORTDB(isp, 1);
 		switch (mbox) {
 		case ISP_CONN_LOOP:
 			isp_prt(isp, ISP_LOGINFO,
@@ -5707,14 +5782,6 @@
 			mbs.logval = MBLOGALL;
 			isp_mboxcmd_qnw(isp, &mbs, 1);
 		}
-
-		/*
-		 * Probably overkill.
-		 */
-		isp->isp_sendmarker = 1;
-		FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
-		isp_mark_portdb(isp, 1);
-		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
 		if (XS_NOERR(xs)) {
 			XS_SETERR(xs, HBA_SELTIMEOUT);
 		}
@@ -5865,14 +5932,6 @@
 			mbs.logval = MBLOGALL;
 			isp_mboxcmd_qnw(isp, &mbs, 1);
 		}
-
-		/*
-		 * Probably overkill.
-		 */
-		isp->isp_sendmarker = 1;
-		FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
-		isp_mark_portdb(isp, 1);
-		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
 		if (XS_NOERR(xs)) {
 			XS_SETERR(xs, HBA_SELTIMEOUT);
 		}
@@ -7104,7 +7163,7 @@
 	uint32_t tmp;
 
 	if (IS_FC(isp)) {
-		isp_mark_portdb(isp, 0);
+		ISP_MARK_PORTDB(isp, 0);
 	}
 	isp_reset(isp);
 	if (isp->isp_state != ISP_RESETSTATE) {

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

@@ -41,6 +41,7 @@
 #if	__FreeBSD_version >= 500000
 #include <sys/sysctl.h>
 #endif
+#include <cam/cam_periph.h>
 
 
 MODULE_VERSION(isp, 1);
@@ -50,10 +51,12 @@
 int isp_loop_down_limit = 300;	/* default loop down limit */
 int isp_change_is_bad = 0;	/* "changed" devices are bad */
 int isp_quickboot_time = 5;	/* don't wait more than N secs for loop up */
-int isp_lost_device_time = 60;	/* grace time before reporting device lost */
+int isp_gone_device_time = 60;	/* grace time before reporting device lost */
 static const char *roles[4] = {
     "(none)", "Target", "Initiator", "Target/Initiator"
 };
+static const char prom3[] =
+    "PortID 0x%06x Departed from Target %u because of %s";
 
 static d_ioctl_t ispioctl;
 static void isp_intr_enable(void *);
@@ -657,16 +660,20 @@
 	       "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",
+	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",
+	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);
+	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+	    "gone_device_time",
+	    CTLFLAG_RW, &isp->isp_osinfo.gone_device_time, 0,
+	    "How long to wait for a device to reappear");
 }
 #endif
 
@@ -2070,7 +2077,9 @@
 		if (XS_CMD_DONE_P(xs)) {
 			isp_prt(isp, ISP_LOGDEBUG2,
 			    "watchdog cleanup for handle 0x%x", handle);
+			ISPLOCK_2_CAMLOCK(isp);
 			xpt_done((union ccb *) xs);
+			CAMLOCK_2_ISPLOCK(isp);
 		} else if (XS_CMD_GRACE_P(xs)) {
 			/*
 			 * Make sure the command is *really* dead before we
@@ -2090,7 +2099,9 @@
 			    "watchdog timeout for handle 0x%x", handle);
 			XS_SETERR(xs, CAM_CMD_TIMEOUT);
 			XS_CMD_C_WDOG(xs);
+			ISPLOCK_2_CAMLOCK(isp);
 			isp_done(xs);
+			CAMLOCK_2_ISPLOCK(isp);
 		} else {
 			XS_CMD_C_WDOG(xs);
 			xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
@@ -2098,20 +2109,103 @@
 			isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
 		}
 	} else {
-		isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command");
+		isp_prt(isp, ISP_LOGWARN, "watchdog with no command");
+	}
+	ISP_UNLOCK(isp);
+}
+
+#if __FreeBSD_version >= 500000  
+#define	isp_make_here(isp, tgt)	isp_announce(isp, tgt, AC_FOUND_DEVICE)
+#define	isp_make_gone(isp, tgt)	isp_announce(isp, tgt, AC_LOST_DEVICE)
+
+/*
+ * Support function for Announcement
+ */
+static void
+isp_announce(ispsoftc_t *isp, int tgt, int action)
+{
+	struct cam_path *tmppath;
+	ISPLOCK_2_CAMLOCK(isp);
+	if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim), tgt,
+	    CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
+		xpt_async(action, tmppath, NULL);
+		xpt_free_path(tmppath);
+	}
+	CAMLOCK_2_ISPLOCK(isp);
+}
+#else
+#define	isp_make_here(isp, tgt)	do { ; } while (0)
+#define	isp_make_gone(isp, tgt)	do { ; } while (0)
+#endif
+
+
+/*
+ * Gone Device Timer Function- when we have decided that a device has gone
+ * away, we wait a specific period of time prior to telling the OS it has
+ * gone away.
+ *
+ * This timer function fires once a second and then scans the port database
+ * for devices that are marked dead but still have a virtual target assigned.
+ * We decrement a counter for that port database entry, and when it hits zero,
+ * we tell the OS the device has gone away.
+ */
+static void
+isp_gdt(void *arg)
+{
+	ispsoftc_t *isp = arg;
+	fcportdb_t *lp;
+	int dbidx, tgt, more_to_do = 0;
+
+	isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
+	ISP_LOCK(isp);
+	for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
+		lp = &FCPARAM(isp)->portdb[dbidx];
+
+		if (lp->state != FC_PORTDB_STATE_ZOMBIE) {

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


More information about the p4-projects mailing list