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
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to