Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Nov 2015 21:58:51 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r291532 - stable/10/sys/dev/isp
Message-ID:  <201511302158.tAULwpgl077590@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Nov 30 21:58:51 2015
New Revision: 291532
URL: https://svnweb.freebsd.org/changeset/base/291532

Log:
  MFC r291365, r291369: One more round of port scanner rewrite.
  
   - Make scan aborted by event restart immediately and infinitely.
   - Improve handling of some loop events from firmware.
   - Remove loop down timer, adding its functionality to scanner thread.
   - Some more unification and simplification.

Modified:
  stable/10/sys/dev/isp/isp.c
  stable/10/sys/dev/isp/isp_freebsd.c
  stable/10/sys/dev/isp/isp_freebsd.h
  stable/10/sys/dev/isp/isp_library.c
  stable/10/sys/dev/isp/isp_pci.c
  stable/10/sys/dev/isp/ispvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/isp/isp.c
==============================================================================
--- stable/10/sys/dev/isp/isp.c	Mon Nov 30 21:57:54 2015	(r291531)
+++ stable/10/sys/dev/isp/isp.c	Mon Nov 30 21:58:51 2015	(r291532)
@@ -2810,6 +2810,8 @@ isp_fclink_test(ispsoftc_t *isp, int cha
 
 	fcp = FCPARAM(isp, chan);
 
+	if (fcp->isp_loopstate < LOOP_HAVE_LINK)
+		return (-1);
 	if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
 		return (0);
 
@@ -2825,15 +2827,13 @@ isp_fclink_test(ispsoftc_t *isp, int cha
 		if (fcp->isp_fwstate == FW_READY) {
 			break;
 		}
+		if (fcp->isp_loopstate < LOOP_TESTING_LINK)
+			goto abort;
 		GET_NANOTIME(&hrb);
 		if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
 			break;
 		ISP_SLEEP(isp, 1000);
 	}
-
-	/*
-	 * If we haven't gone to 'ready' state, return.
-	 */
 	if (fcp->isp_fwstate != FW_READY) {
 		isp_prt(isp, ISP_LOG_SANCFG,
 		    "Chan %d Firmware is not ready (%s)",
@@ -2938,6 +2938,12 @@ not_on_fabric:
 		}
 	}
 
+	if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
+abort:
+		isp_prt(isp, ISP_LOG_SANCFG,
+		    "Chan %d FC link test aborted", chan);
+		return (1);
+	}
 	fcp->isp_loopstate = LOOP_LTEST_DONE;
 	isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
 	    "Chan %d WWPN %016jx WWNN %016jx",
@@ -2968,12 +2974,10 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
 	fcportdb_t *lp;
 	uint16_t dbidx;
 
-	if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
+	if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
 		return (-1);
-	}
-	if (fcp->isp_loopstate > LOOP_SYNCING_PDB) {
+	if (fcp->isp_loopstate >= LOOP_READY)
 		return (0);
-	}
 
 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
 
@@ -3025,12 +3029,12 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
 		}
 	}
 
-	/*
-	 * If we get here, we've for sure seen not only a valid loop
-	 * but know what is or isn't on it, so mark this for usage
-	 * in isp_start.
-	 */
-	fcp->loop_seen_once = 1;
+	if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
+		isp_prt(isp, ISP_LOG_SANCFG,
+		    "Chan %d FC PDB sync aborted", chan);
+		return (1);
+	}
+
 	fcp->isp_loopstate = LOOP_READY;
 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
 	return (0);
@@ -3154,12 +3158,11 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
 	uint16_t handles[LOCAL_LOOP_LIM];
 	uint16_t handle;
 
-	if (fcp->isp_loopstate < LOOP_LTEST_DONE) {
+	if (fcp->isp_loopstate < LOOP_LTEST_DONE)
 		return (-1);
-	}
-	if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
+	if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
 		return (0);
-	}
+
 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
 	fcp->isp_loopstate = LOOP_SCANNING_LOOP;
 	if (TOPO_IS_FABRIC(fcp->isp_topo)) {
@@ -3214,8 +3217,8 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
 			if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
 abort:
 				isp_prt(isp, ISP_LOG_SANCFG,
-				    "Chan %d FC loop scan done (abort)", chan);
-				return (-1);
+				    "Chan %d FC loop scan aborted", chan);
+				return (1);
 			}
 			if (node_wwn == INI_NONE) {
 				continue;
@@ -3424,12 +3427,11 @@ isp_scan_fabric(ispsoftc_t *isp, int cha
 	int portidx, portlim, r;
 	sns_gid_ft_rsp_t *rs0, *rs1;
 
-	if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
+	if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
 		return (-1);
-	}
-	if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) {
+	if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
 		return (0);
-	}
+
 	isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
 	fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
 	if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
@@ -3450,8 +3452,8 @@ fail:
 abort:
 		FC_SCRATCH_RELEASE(isp, chan);
 		isp_prt(isp, ISP_LOG_SANCFG,
-		    "Chan %d FC fabric scan done (abort)", chan);
-		return (-1);
+		    "Chan %d FC fabric scan aborted", chan);
+		return (1);
 	}
 
 	/*
@@ -3478,11 +3480,11 @@ abort:
 	if (r > 0) {
 		fcp->isp_loopstate = LOOP_FSCAN_DONE;
 		FC_SCRATCH_RELEASE(isp, chan);
-		return (0);
+		return (-1);
 	} else if (r < 0) {
 		fcp->isp_loopstate = LOOP_LTEST_DONE;	/* try again */
 		FC_SCRATCH_RELEASE(isp, chan);
-		return (0);
+		return (-1);
 	}
 
 	MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan);
@@ -3504,7 +3506,7 @@ abort:
 		    rs1->snscb_cthdr.ct_explanation);
 		FC_SCRATCH_RELEASE(isp, chan);
 		fcp->isp_loopstate = LOOP_FSCAN_DONE;
-		return (0);
+		return (-1);
 	}
 
 	/* Check our buffer was big enough to get the full list. */
@@ -5657,11 +5659,10 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 			fcp = FCPARAM(isp, chan);
 			int topo = fcp->isp_topo;
 
-			if (fcp->role == ISP_ROLE_NONE) {
+			if (fcp->role == ISP_ROLE_NONE)
 				continue;
-			}
-
-			fcp->isp_loopstate = LOOP_NIL;
+			if (fcp->isp_loopstate > LOOP_HAVE_LINK)
+				fcp->isp_loopstate = LOOP_HAVE_LINK;
 			ISP_SET_SENDMARKER(isp, chan, 1);
 			isp_async(isp, ISPASYNC_LIP, chan);
 #ifdef	ISP_TARGET_MODE
@@ -5714,6 +5715,9 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 			fcp = FCPARAM(isp, chan);
 			if (fcp->role == ISP_ROLE_NONE)
 				continue;
+			fcp->isp_linkstate = 1;
+			if (fcp->isp_loopstate < LOOP_HAVE_LINK)
+				fcp->isp_loopstate = LOOP_HAVE_LINK;
 			ISP_SET_SENDMARKER(isp, chan, 1);
 			isp_async(isp, ISPASYNC_LOOP_UP, chan);
 #ifdef	ISP_TARGET_MODE
@@ -5734,6 +5738,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 			if (fcp->role == ISP_ROLE_NONE)
 				continue;
 			ISP_SET_SENDMARKER(isp, chan, 1);
+			fcp->isp_linkstate = 0;
 			fcp->isp_loopstate = LOOP_NIL;
 			isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
 #ifdef	ISP_TARGET_MODE
@@ -5754,7 +5759,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 			if (fcp->role == ISP_ROLE_NONE)
 				continue;
 			ISP_SET_SENDMARKER(isp, chan, 1);
-			fcp->isp_loopstate = LOOP_NIL;
+			if (fcp->isp_loopstate > LOOP_HAVE_LINK)
+				fcp->isp_loopstate = LOOP_HAVE_LINK;
 			isp_async(isp, ISPASYNC_LOOP_RESET, chan);
 #ifdef	ISP_TARGET_MODE
 			if (isp_target_async(isp, chan, mbox)) {
@@ -5797,6 +5803,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 				continue;
 			if (fcp->isp_loopstate > LOOP_LTEST_DONE)
 				fcp->isp_loopstate = LOOP_LTEST_DONE;
+			else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
+				fcp->isp_loopstate = LOOP_HAVE_LINK;
 			isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
 			    ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
 		}
@@ -5820,6 +5828,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 			break;
 		if (fcp->isp_loopstate > LOOP_LTEST_DONE)
 			fcp->isp_loopstate = LOOP_LTEST_DONE;
+		else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
+			fcp->isp_loopstate = LOOP_HAVE_LINK;
 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
 		    ISPASYNC_CHANGE_SNS, portid);
 		break;
@@ -5867,7 +5877,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint
 			break;
 		}
 		ISP_SET_SENDMARKER(isp, chan, 1);
-		FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
+		FCPARAM(isp, chan)->isp_loopstate = LOOP_HAVE_LINK;
 		isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_OTHER);
 		break;
 	case ASYNC_P2P_INIT_ERR:
@@ -5939,16 +5949,29 @@ isp_handle_other_response(ispsoftc_t *is
 				if (fcp->role == ISP_ROLE_NONE)
 					continue;
 				c = (chan == 0) ? 127 : (chan - 1);
-				if (rid.ridacq_map[c / 16] & (1 << (c % 16))) {
-					fcp->isp_loopstate = LOOP_NIL;
+				if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
+				    chan == 0) {
+					fcp->isp_loopstate = LOOP_HAVE_LINK;
 					isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
 					    chan, ISPASYNC_CHANGE_OTHER);
+				} else {
+					fcp->isp_loopstate = LOOP_NIL;
+					isp_async(isp, ISPASYNC_LOOP_DOWN,
+					    chan);
 				}
 			}
 		} else {
-			FCPARAM(isp, rid.ridacq_vp_index)->isp_loopstate = LOOP_NIL;
-			isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
-			    rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
+			fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index);
+			if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
+			    rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
+				fcp->isp_loopstate = LOOP_HAVE_LINK;
+				isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
+				    rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
+			} else {
+				fcp->isp_loopstate = LOOP_NIL;
+				isp_async(isp, ISPASYNC_LOOP_DOWN,
+				    rid.ridacq_vp_index);
+			}
 		}
 		return (1);
 	case RQSTYPE_ATIO:

Modified: stable/10/sys/dev/isp/isp_freebsd.c
==============================================================================
--- stable/10/sys/dev/isp/isp_freebsd.c	Mon Nov 30 21:57:54 2015	(r291531)
+++ stable/10/sys/dev/isp/isp_freebsd.c	Mon Nov 30 21:58:51 2015	(r291532)
@@ -50,13 +50,13 @@ __FBSDID("$FreeBSD$");
 MODULE_VERSION(isp, 1);
 MODULE_DEPEND(isp, cam, 1, 1, 1);
 int isp_announced = 0;
-int isp_fabric_hysteresis = 5;
 int isp_loop_down_limit = 60;	/* default loop down limit */
 int isp_quickboot_time = 7;	/* don't wait more than N secs for loop up */
 int isp_gone_device_time = 30;	/* grace time before reporting device lost */
 static const char prom3[] = "Chan %d [%u] PortID 0x%06x Departed because of %s";
 
-static void isp_freeze_loopdown(ispsoftc_t *, int, char *);
+static void isp_freeze_loopdown(ispsoftc_t *, int);
+static void isp_loop_changed(ispsoftc_t *isp, int chan);
 static d_ioctl_t ispioctl;
 static void isp_intr_enable(void *);
 static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
@@ -64,8 +64,6 @@ static void isp_poll(struct cam_sim *);
 static timeout_t isp_watchdog;
 static timeout_t isp_gdt;
 static task_fn_t isp_gdt_task;
-static timeout_t isp_ldt;
-static task_fn_t isp_ldt_task;
 static void isp_kthread(void *);
 static void isp_action(struct cam_sim *, union ccb *);
 static int isp_timer_count;
@@ -168,25 +166,13 @@ isp_attach_chan(ispsoftc_t *isp, struct 
 		fc->isp = isp;
 		fc->ready = 1;
 
-		callout_init_mtx(&fc->ldt, &isp->isp_osinfo.lock, 0);
 		callout_init_mtx(&fc->gdt, &isp->isp_osinfo.lock, 0);
-		TASK_INIT(&fc->ltask, 1, isp_ldt_task, fc);
 		TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc);
-
-		/*
-		 * We start by being "loop down" if we have an initiator role
-		 */
-		if (fcp->role & ISP_ROLE_INITIATOR) {
-			isp_freeze_loopdown(isp, chan, "isp_attach");
-			callout_reset(&fc->ldt, isp_quickboot_time * hz, isp_ldt, fc);
-			isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Starting Initial Loop Down Timer @ %lu", (unsigned long) time_uptime);
-		}
+		isp_loop_changed(isp, chan);
 		ISP_UNLOCK(isp);
 		if (THREAD_CREATE(isp_kthread, fc, &fc->kproc, 0, 0, "%s: fc_thrd%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) {
 			xpt_free_path(fc->path);
 			ISP_LOCK(isp);
-			if (callout_active(&fc->ldt))
-				callout_stop(&fc->ldt);
 			xpt_bus_deregister(cam_sim_path(fc->sim));
 			ISP_UNLOCK(isp);
 			cam_sim_free(fc->sim, FALSE);
@@ -377,13 +363,13 @@ isp_detach(ispsoftc_t *isp)
 }
 
 static void
-isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg)
+isp_freeze_loopdown(ispsoftc_t *isp, int chan)
 {
 	if (IS_FC(isp)) {
 		struct isp_fc *fc = ISP_FC_PC(isp, chan);
 		if (fc->simqfrozen == 0) {
 			isp_prt(isp, ISP_LOGDEBUG0,
-			    "Chan %d %s -- freeze simq (loopdown)", chan, msg);
+			    "Chan %d Freeze simq (loopdown)", chan);
 			fc->simqfrozen = SIMQFRZ_LOOPDOWN;
 #if __FreeBSD_version >= 1000039
 			xpt_hold_boot();
@@ -391,7 +377,7 @@ isp_freeze_loopdown(ispsoftc_t *isp, int
 			xpt_freeze_simq(fc->sim, 1);
 		} else {
 			isp_prt(isp, ISP_LOGDEBUG0,
-			    "Chan %d %s -- mark frozen (loopdown)", chan, msg);
+			    "Chan %d Mark simq frozen (loopdown)", chan);
 			fc->simqfrozen |= SIMQFRZ_LOOPDOWN;
 		}
 	}
@@ -405,7 +391,8 @@ isp_unfreeze_loopdown(ispsoftc_t *isp, i
 		int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
 		fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
 		if (wasfrozen && fc->simqfrozen == 0) {
-			isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d releasing simq", __func__, chan);
+			isp_prt(isp, ISP_LOGDEBUG0,
+			    "Chan %d Release simq", chan);
 			xpt_release_simq(fc->sim, 1);
 #if __FreeBSD_version >= 1000039
 			xpt_release_boot();
@@ -481,7 +468,7 @@ ispioctl(struct cdev *dev, u_long c, cad
 				break;
 			}
 			ISP_LOCK(isp);
-			if (isp_fc_runstate(isp, chan, 5 * 1000000)) {
+			if (isp_fc_runstate(isp, chan, 5 * 1000000) != LOOP_READY) {
 				retval = EIO;
 			} else {
 				retval = 0;
@@ -3270,41 +3257,59 @@ isp_gdt_task(void *arg, int pending)
 }
 
 /*
- * Loop Down Timer Function- when loop goes down, a timer is started and
- * and after it expires we come here and take all probational devices that
- * the OS knows about and the tell the OS that they've gone away.
- * 
+ * When loop goes down we remember the time and freeze CAM command queue.
+ * During some time period we are trying to reprobe the loop.  But if we
+ * fail, we tell the OS that devices have gone away and drop the freeze.
+ *
  * We don't clear the devices out of our port database because, when loop
  * come back up, we have to do some actual cleanup with the chip at that
  * point (implicit PLOGO, e.g., to get the chip's port database state right).
  */
 static void
-isp_ldt(void *arg)
+isp_loop_changed(ispsoftc_t *isp, int chan)
 {
-	struct isp_fc *fc = arg;
-	taskqueue_enqueue(taskqueue_thread, &fc->ltask);
+	fcparam *fcp = FCPARAM(isp, chan);
+	struct isp_fc *fc = ISP_FC_PC(isp, chan);
+
+	if (fc->loop_down_time)
+		return;
+	isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop changed", chan);
+	if (fcp->role & ISP_ROLE_INITIATOR)
+		isp_freeze_loopdown(isp, chan);
+	fc->loop_dead = 0;
+	fc->loop_down_time = time_uptime;
+	wakeup(fc);
 }
 
 static void
-isp_ldt_task(void *arg, int pending)
+isp_loop_up(ispsoftc_t *isp, int chan)
 {
-	struct isp_fc *fc = arg;
-	ispsoftc_t *isp = fc->isp;
-	int chan = fc - isp->isp_osinfo.pc.fc;
+	struct isp_fc *fc = ISP_FC_PC(isp, chan);
+
+	isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop is up", chan);
+	fc->loop_seen_once = 1;
+	fc->loop_dead = 0;
+	fc->loop_down_time = 0;
+	isp_unfreeze_loopdown(isp, chan);
+}
+
+static void
+isp_loop_dead(ispsoftc_t *isp, int chan)
+{
+	fcparam *fcp = FCPARAM(isp, chan);
+	struct isp_fc *fc = ISP_FC_PC(isp, chan);
 	fcportdb_t *lp;
 	struct ac_contract ac;
 	struct ac_device_changed *adc;
 	int dbidx, i;
 
-	ISP_LOCK(isp);
-	isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop Down Timer expired @ %lu", chan, (unsigned long) time_uptime);
-	callout_deactivate(&fc->ldt);
+	isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop is dead", chan);
 
 	/*
 	 * Notify to the OS all targets who we now consider have departed.
 	 */
 	for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
-		lp = &FCPARAM(isp, chan)->portdb[dbidx];
+		lp = &fcp->portdb[dbidx];
 
 		if (lp->state == FC_PORTDB_STATE_NIL)
 			continue;
@@ -3347,14 +3352,8 @@ isp_ldt_task(void *arg, int pending)
 	}
 
 	isp_unfreeze_loopdown(isp, chan);
-	/*
-	 * The loop down timer has expired. Wake up the kthread
-	 * to notice that fact (or make it false).
-	 */
 	fc->loop_dead = 1;
-	fc->loop_down_time = fc->loop_down_limit+1;
-	wakeup(fc);
-	ISP_UNLOCK(isp);
+	fc->loop_down_time = 0;
 }
 
 static void
@@ -3363,15 +3362,18 @@ isp_kthread(void *arg)
 	struct isp_fc *fc = arg;
 	ispsoftc_t *isp = fc->isp;
 	int chan = fc - isp->isp_osinfo.pc.fc;
-	int slp = 0;
+	int slp = 0, d;
+	int lb, lim;
 
 	mtx_lock(&isp->isp_osinfo.lock);
 
 	while (isp->isp_osinfo.is_exiting == 0) {
-		int lb, lim;
-
-		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d checking FC state", __func__, chan);
+		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0,
+		    "Chan %d Checking FC state", chan);
 		lb = isp_fc_runstate(isp, chan, 250000);
+		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0,
+		    "Chan %d FC got to %s state", chan,
+		    isp_fc_loop_statename(lb));
 
 		/*
 		 * Our action is different based upon whether we're supporting
@@ -3381,87 +3383,44 @@ isp_kthread(void *arg)
 		 *
 		 * If not, we simply just wait for loop to come up.
 		 */
-		if (lb && (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR)) {
-			/*
-			 * Increment loop down time by the last sleep interval
-			 */
-			fc->loop_down_time += slp;
-
-			if (lb < 0) {
-				isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC loop not up (down count %d)", __func__, chan, fc->loop_down_time);
-			} else {
-				isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC got to %d (down count %d)", __func__, chan, lb, fc->loop_down_time);
-			}
-
+		if (lb == LOOP_READY || lb < 0) {
+			slp = 0;
+		} else {
 			/*
 			 * If we've never seen loop up and we've waited longer
 			 * than quickboot time, or we've seen loop up but we've
 			 * waited longer than loop_down_limit, give up and go
 			 * to sleep until loop comes up.
 			 */
-			if (FCPARAM(isp, chan)->loop_seen_once == 0) {
+			if (fc->loop_seen_once == 0)
 				lim = isp_quickboot_time;
-			} else {
+			else
 				lim = fc->loop_down_limit;
-			}
-			if (fc->loop_down_time >= lim) {
-				isp_freeze_loopdown(isp, chan, "loop limit hit");
+			d = time_uptime - fc->loop_down_time;
+			if (d >= lim)
 				slp = 0;
-			} else if (fc->loop_down_time < 10) {
+			else if (d < 10)
 				slp = 1;
-			} else if (fc->loop_down_time < 30) {
+			else if (d < 30)
 				slp = 5;
-			} else if (fc->loop_down_time < 60) {
+			else if (d < 60)
 				slp = 10;
-			} else if (fc->loop_down_time < 120) {
+			else if (d < 120)
 				slp = 20;
-			} else {
-				slp = 30;
-			}
-
-		} else if (lb) {
-			isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC Loop Down", __func__, chan);
-			fc->loop_down_time += slp;
-			if (fc->loop_down_time > 300)
-				slp = 0;
 			else
-				slp = 60;
-		} else {
-			isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC state OK", __func__, chan);
-			fc->loop_down_time = 0;
-			slp = 0;
+				slp = 30;
 		}
 
-
-		/*
-		 * If this is past the first loop up or the loop is dead and if we'd frozen the simq, unfreeze it
-		 * now so that CAM can start sending us commands.
-		 *
-		 * If the FC state isn't okay yet, they'll hit that in isp_start which will freeze the queue again
-		 * or kill the commands, as appropriate.
-		 */
-
-		if (FCPARAM(isp, chan)->loop_seen_once || fc->loop_dead) {
-			isp_unfreeze_loopdown(isp, chan);
+		if (slp == 0) {
+			if (lb == LOOP_READY)
+				isp_loop_up(isp, chan);
+			else
+				isp_loop_dead(isp, chan);
 		}
 
-		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep time %d", __func__, chan, slp);
-
+		isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0,
+		    "Chan %d sleep for %d seconds", chan, slp);
 		msleep(fc, &isp->isp_osinfo.lock, PRIBIO, "ispf", slp * hz);
-
-		/*
-		 * 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
-		 * for all commands and delay hysteresis seconds before starting
-		 * the FC state evaluation. This gives the loop/fabric a chance
-		 * to settle.
-		 */
-		if (slp == 0 && fc->hysteresis) {
-			isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep hysteresis ticks %d", __func__, chan, fc->hysteresis * hz);
-			mtx_unlock(&isp->isp_osinfo.lock);
-			pause("ispt", fc->hysteresis * hz);
-			mtx_lock(&isp->isp_osinfo.lock);
-		}
 	}
 	fc->num_threads -= 1;
 	mtx_unlock(&isp->isp_osinfo.lock);
@@ -3471,7 +3430,7 @@ isp_kthread(void *arg)
 static void
 isp_action(struct cam_sim *sim, union ccb *ccb)
 {
-	int bus, tgt, ts, error, lim;
+	int bus, tgt, ts, error;
 	ispsoftc_t *isp;
 	struct ccb_trans_settings *cts;
 
@@ -3535,26 +3494,13 @@ isp_action(struct cam_sim *sim, union cc
 			break;
 		case CMD_RQLATER:
 			/*
-			 * We get this result for FC devices if the loop state isn't ready yet
-			 * or if the device in question has gone zombie on us.
-			 *
-			 * If we've never seen Loop UP at all, we requeue this request and wait
-			 * for the initial loop up delay to expire.
+			 * We get this result if the loop isn't ready
+			 * or if the device in question has gone zombie.
 			 */
-			lim = ISP_FC_PC(isp, bus)->loop_down_limit;
-			if (FCPARAM(isp, bus)->loop_seen_once == 0 || ISP_FC_PC(isp, bus)->loop_down_time >= lim) {
-				if (FCPARAM(isp, bus)->loop_seen_once == 0) {
-					isp_prt(isp, ISP_LOGDEBUG0,
-					    "%d.%jx loop not seen yet @ %lu",
-					    XS_TGT(ccb), (uintmax_t)XS_LUN(ccb),
-					    (unsigned long) time_uptime);
-				} else {
-					isp_prt(isp, ISP_LOGDEBUG0,
-					    "%d.%jx downtime (%d) > lim (%d)",
-					    XS_TGT(ccb), (uintmax_t)XS_LUN(ccb),
-					    ISP_FC_PC(isp, bus)->loop_down_time,
-					    lim);
-				}
+			if (ISP_FC_PC(isp, bus)->loop_dead) {
+				isp_prt(isp, ISP_LOGDEBUG0,
+				    "%d.%jx loop is dead",
+				    XS_TGT(ccb), (uintmax_t)XS_LUN(ccb));
 				ccb->ccb_h.status = CAM_SEL_TIMEOUT;
 				isp_done((struct ccb_scsiio *) ccb);
 				break;
@@ -4260,49 +4206,20 @@ isp_async(ispsoftc_t *isp, ispasync_t cm
 			msg = "LOOP Reset";
 		/* FALLTHROUGH */
 	case ISPASYNC_LOOP_DOWN:
-	{
 		if (msg == NULL)
 			msg = "LOOP Down";
 		va_start(ap, cmd);
 		bus = va_arg(ap, int);
 		va_end(ap);
-
-		FCPARAM(isp, bus)->isp_linkstate = 0;
-
-		fc = ISP_FC_PC(isp, bus);
-		if (cmd == ISPASYNC_LOOP_DOWN && fc->ready) {
-			/*
-			 * We don't do any simq freezing if we are only in target mode
-			 */
-			if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) {
-				if (fc->path) {
-					isp_freeze_loopdown(isp, bus, msg);
-				}
-			}
-			if (!callout_active(&fc->ldt)) {
-				callout_reset(&fc->ldt, fc->loop_down_limit * hz, isp_ldt, fc);
-				isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Starting Loop Down Timer @ %lu", (unsigned long) time_uptime);
-			}
-		}
 		isp_fcp_reset_crn(isp, bus, /*tgt*/0, /*tgt_set*/ 0);
-
-		isp_prt(isp, ISP_LOGINFO, "Chan %d: %s", bus, msg);
+		isp_loop_changed(isp, bus);
+		isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg);
 		break;
-	}
 	case ISPASYNC_LOOP_UP:
 		va_start(ap, cmd);
 		bus = va_arg(ap, int);
 		va_end(ap);
-		fc = ISP_FC_PC(isp, bus);
-		/*
-		 * Now we just note that Loop has come up. We don't
-		 * actually do anything because we're waiting for a
-		 * Change Notify before activating the FC cleanup
-		 * thread to look at the state of the loop again.
-		 */
-		FCPARAM(isp, bus)->isp_linkstate = 1;
-		fc->loop_dead = 0;
-		fc->loop_down_time = 0;
+		isp_loop_changed(isp, bus);
 		isp_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus);
 		break;
 	case ISPASYNC_DEV_ARRIVED:
@@ -4435,18 +4352,7 @@ changed:
 			msg = "Other Change Notify";
 			isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg);
 		}
-
-		/*
-		 * If the loop down timer is running, cancel it.
-		 */
-		if (fc->ready && callout_active(&fc->ldt)) {
-			isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Stopping Loop Down Timer @ %lu", (unsigned long) time_uptime);
-			callout_stop(&fc->ldt);
-		}
-		if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) {
-			isp_freeze_loopdown(isp, bus, msg);
-		}
-		wakeup(fc);
+		isp_loop_changed(isp, bus);
 		break;
 	}
 #ifdef	ISP_TARGET_MODE

Modified: stable/10/sys/dev/isp/isp_freebsd.h
==============================================================================
--- stable/10/sys/dev/isp/isp_freebsd.h	Mon Nov 30 21:57:54 2015	(r291531)
+++ stable/10/sys/dev/isp/isp_freebsd.h	Mon Nov 30 21:58:51 2015	(r291532)
@@ -228,9 +228,9 @@ struct isp_fc {
 	bus_dmamap_t tdmap;
 	uint64_t def_wwpn;
 	uint64_t def_wwnn;
-	uint32_t loop_down_time;
-	uint32_t loop_down_limit;
-	uint32_t gone_device_time;
+	time_t loop_down_time;
+	int loop_down_limit;
+	int gone_device_time;
 	/*
 	 * Per target/lun info- just to keep a per-ITL nexus crn count
 	 */
@@ -239,15 +239,13 @@ struct isp_fc {
 	uint32_t
 		simqfrozen	: 3,
 		default_id	: 8,
-		hysteresis	: 8,
 		def_role	: 2,	/* default role */
 		gdt_running	: 1,
 		loop_dead	: 1,
+		loop_seen_once	: 1,
 		fcbsy		: 1,
 		ready		: 1;
-	struct callout ldt;	/* loop down timer */
 	struct callout gdt;	/* gone device timer */
-	struct task ltask;
 	struct task gtask;
 #ifdef	ISP_TARGET_MODE
 	struct tslist lun_hash[LUN_HASH_SIZE];
@@ -698,7 +696,6 @@ extern uint64_t isp_default_wwn(ispsoftc
  * driver global data
  */
 extern int isp_announced;
-extern int isp_fabric_hysteresis;
 extern int isp_loop_down_limit;
 extern int isp_gone_device_time;
 extern int isp_quickboot_time;

Modified: stable/10/sys/dev/isp/isp_library.c
==============================================================================
--- stable/10/sys/dev/isp/isp_library.c	Mon Nov 30 21:57:54 2015	(r291531)
+++ stable/10/sys/dev/isp/isp_library.c	Mon Nov 30 21:58:51 2015	(r291532)
@@ -394,33 +394,31 @@ isp_print_bytes(ispsoftc_t *isp, const c
 int
 isp_fc_runstate(ispsoftc_t *isp, int chan, int tval)
 {
-	fcparam *fcp;
+	fcparam *fcp = FCPARAM(isp, chan);
+	int res;
 
-	fcp = FCPARAM(isp, chan);
-        if (fcp->role == ISP_ROLE_NONE) {
-		return (0);
-	}
-	if (isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval) != 0) {
-		isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: linktest failed for channel %d", chan);
+again:
+	if (fcp->role == ISP_ROLE_NONE)
 		return (-1);
-	}
-	if (isp_control(isp, ISPCTL_SCAN_LOOP, chan) != 0) {
-		isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan loop failed on channel %d", chan);
-		return (LOOP_LTEST_DONE);
-	}
-	if (isp_control(isp, ISPCTL_SCAN_FABRIC, chan) != 0) {
-		isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan fabric failed on channel %d", chan);
-		return (LOOP_LSCAN_DONE);
-	}
-	if (isp_control(isp, ISPCTL_PDB_SYNC, chan) != 0) {
-		isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: pdb_sync failed on channel %d", chan);
-		return (LOOP_FSCAN_DONE);
-	}
-	if (fcp->isp_loopstate != LOOP_READY) {
-		isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: not ready again on channel %d", chan);
-		return (-1);
-	}
-	return (0);
+	res = isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval);
+	if (res > 0)
+		goto again;
+	if (res < 0)
+		return (fcp->isp_loopstate);
+	res = isp_control(isp, ISPCTL_SCAN_LOOP, chan);
+	if (res > 0)
+		goto again;
+	if (res < 0)
+		return (fcp->isp_loopstate);
+	res = isp_control(isp, ISPCTL_SCAN_FABRIC, chan);
+	if (res > 0)
+		goto again;
+	if (res < 0)
+		return (fcp->isp_loopstate);
+	res = isp_control(isp, ISPCTL_PDB_SYNC, chan);
+	if (res > 0)
+		goto again;
+	return (fcp->isp_loopstate);
 }
 
 /*
@@ -545,6 +543,7 @@ isp_fc_loop_statename(int state)
 {
 	switch (state) {
 	case LOOP_NIL:                  return "NIL";
+	case LOOP_HAVE_LINK:            return "Have Link";
 	case LOOP_TESTING_LINK:         return "Testing Link";
 	case LOOP_LTEST_DONE:           return "Link Test Done";
 	case LOOP_SCANNING_LOOP:        return "Scanning Loop";

Modified: stable/10/sys/dev/isp/isp_pci.c
==============================================================================
--- stable/10/sys/dev/isp/isp_pci.c	Mon Nov 30 21:57:54 2015	(r291531)
+++ stable/10/sys/dev/isp/isp_pci.c	Mon Nov 30 21:58:51 2015	(r291532)
@@ -638,16 +638,6 @@ isp_get_specific_options(device_t dev, i
 		}
 	}
 
-	tval = 0;
-	snprintf(name, sizeof(name), "%shysteresis", prefix);
-	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
-	    "name", &tval);
-	if (tval >= 0 && tval < 256) {
-		ISP_FC_PC(isp, chan)->hysteresis = tval;
-	} else {
-		ISP_FC_PC(isp, chan)->hysteresis = isp_fabric_hysteresis;
-	}
-
 	tval = -1;
 	snprintf(name, sizeof(name), "%sloop_down_limit", prefix);
 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),

Modified: stable/10/sys/dev/isp/ispvar.h
==============================================================================
--- stable/10/sys/dev/isp/ispvar.h	Mon Nov 30 21:57:54 2015	(r291531)
+++ stable/10/sys/dev/isp/ispvar.h	Mon Nov 30 21:58:51 2015	(r291532)
@@ -438,10 +438,9 @@ typedef struct {
 	int			isp_loopstate;		/* Loop State */
 	int			isp_topo;		/* Connection Type */
 
-	uint32_t				: 3,
+	uint32_t				: 4,
 				fctape_enabled	: 1,
 				sendmarker	: 1,
-				loop_seen_once	: 1,
 				role		: 2,
 				isp_portid	: 24;	/* S_ID */
 
@@ -490,14 +489,15 @@ typedef struct {
 #define	FW_NON_PART		7
 
 #define	LOOP_NIL		0
-#define	LOOP_TESTING_LINK	1
-#define	LOOP_LTEST_DONE		2
-#define	LOOP_SCANNING_LOOP	3
-#define	LOOP_LSCAN_DONE		4
-#define	LOOP_SCANNING_FABRIC	5
-#define	LOOP_FSCAN_DONE		6
-#define	LOOP_SYNCING_PDB	7
-#define	LOOP_READY		8
+#define	LOOP_HAVE_LINK		1
+#define	LOOP_TESTING_LINK	2
+#define	LOOP_LTEST_DONE		3
+#define	LOOP_SCANNING_LOOP	4
+#define	LOOP_LSCAN_DONE		5
+#define	LOOP_SCANNING_FABRIC	6
+#define	LOOP_FSCAN_DONE		7
+#define	LOOP_SYNCING_PDB	8
+#define	LOOP_READY		9
 
 #define	TOPO_NL_PORT		0
 #define	TOPO_FL_PORT		1



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