PERFORCE change 109909 for review
Matt Jacob
mjacob at FreeBSD.org
Tue Nov 14 08:33:59 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=109909
Change 109909 by mjacob at newisp on 2006/11/14 08:33:00
More cleanup on initial startup conditions that have loop down.
Clean up sleeping in isp_kthread. Add more ISP_LOGSANCFG lines.
Affected files ...
.. //depot/projects/newisp/dev/isp/isp_freebsd.c#27 edit
Differences ...
==== //depot/projects/newisp/dev/isp/isp_freebsd.c#27 (text+ko) ====
@@ -50,14 +50,15 @@
int isp_fabric_hysteresis = 5;
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_gone_device_time = 60; /* grace time before reporting device lost */
+int isp_quickboot_time = 15; /* 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 *roles[4] = {
"(none)", "Target", "Initiator", "Target/Initiator"
};
static const char prom3[] =
"PortID 0x%06x Departed from Target %u because of %s";
+static void isp_freeze_loopdown(ispsoftc_t *, char *);
static d_ioctl_t ispioctl;
static void isp_intr_enable(void *);
static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
@@ -180,7 +181,6 @@
if (IS_FC(isp)) {
ISPLOCK_2_CAMLOCK(isp);
#if __FreeBSD_version >= 500000
- /* XXX: LOCK VIOLATION */
cv_init(&isp->isp_osinfo.kthread_cv, "isp_kthread_cv");
if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
RFHIGHPID, 0, "%s: fc_thrd",
@@ -198,6 +198,17 @@
return;
}
CAMLOCK_2_ISPLOCK(isp);
+ /*
+ * We start by being "loop down" if we have an initiator role
+ */
+ if (isp->isp_role & ISP_ROLE_INITIATOR) {
+ isp_freeze_loopdown(isp, "isp_attach");
+ isp->isp_osinfo.ldt =
+ timeout(isp_ldt, isp, isp_quickboot_time * hz);
+ isp->isp_osinfo.ldt_running = 1;
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Starting Initial Loop Down Timer");
+ }
}
@@ -268,7 +279,7 @@
isp_sysctl_update(isp);
}
-static __inline void
+static void
isp_freeze_loopdown(ispsoftc_t *isp, char *msg)
{
if (isp->isp_osinfo.simqfrozen == 0) {
@@ -661,11 +672,6 @@
"World Wide Port Name");
SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
- "loop_down_time",
- CTLFLAG_RD, &isp->isp_osinfo.loop_down_time, 0,
- "How long Loop has been down");
-
- SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"loop_down_limit",
CTLFLAG_RW, &isp->isp_osinfo.loop_down_limit, 0,
"How long to wait for loop to come back up");
@@ -2226,7 +2232,7 @@
fcportdb_t *lp;
int dbidx, tgt;
- isp_prt(isp, ISP_LOGDEBUG0, "LDT timer expired");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
ISP_LOCK(isp);
/*
@@ -2265,13 +2271,29 @@
"Loop Down Timeout");
isp_make_gone(isp, tgt);
}
+
+ /*
+ * The loop down timer has expired. Wake up the kthread
+ * to notice that fact (or make it false).
+ */
+ isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
+#if __FreeBSD_version < 500000
+ wakeup(&isp->isp_osinfo.kproc);
+#else
+#ifdef ISP_SMPLOCK
+ cv_signal(&isp->isp_osinfo.kthread_cv);
+#else
+ wakeup(&isp->isp_osinfo.kthread_cv);
+#endif
+#endif
+ ISP_UNLOCK(isp);
}
static void
isp_kthread(void *arg)
{
ispsoftc_t *isp = arg;
- int slp;
+ int slp = 0;
#if __FreeBSD_version < 500000
int s;
@@ -2288,21 +2310,25 @@
* gotten good fibre channel state.
*/
for (;;) {
- int wasfrozen, lb;
+ int wasfrozen, lb, lim;
- isp_prt(isp, ISP_LOGDEBUG0, "kthread: checking FC state");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "isp_kthread: checking FC state");
isp->isp_osinfo.mbox_sleep_ok = 1;
lb = isp_fc_runstate(isp, 250000);
isp->isp_osinfo.mbox_sleep_ok = 0;
if (lb) {
- unsigned int inc = 1;
+ /*
+ * Increment loop down time by the last sleep interval
+ */
+ isp->isp_osinfo.loop_down_time += slp;
if (lb < 0) {
- isp_prt(isp, ISP_LOGDEBUG0,
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"kthread: FC loop not up (down count %d)",
isp->isp_osinfo.loop_down_time);
} else {
- isp_prt(isp, ISP_LOGDEBUG0,
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"kthread: FC got to %d (down count %d)",
lb, isp->isp_osinfo.loop_down_time);
}
@@ -2310,33 +2336,33 @@
/*
* If we've never seen loop up and we've waited longer
- * than quickboot time, give up and go to sleep until
- * loop comes up. Otherwise, increment the loop down
- * time and figure out how long to sleep to the next
- * check.
+ * 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)->loop_seen_once == 0 &&
- isp->isp_osinfo.loop_down_time >=
- isp_quickboot_time) {
- isp->isp_osinfo.loop_down_time = 0xffff;
+ if (FCPARAM(isp)->loop_seen_once == 0) {
+ lim = isp_quickboot_time;
+ } else {
+ lim = isp->isp_osinfo.loop_down_limit;
+ }
+ if (isp->isp_osinfo.loop_down_time >= lim) {
+ isp_freeze_loopdown(isp, "loop limit hit");
slp = 0;
- } else if (isp->isp_osinfo.loop_down_time > 30) {
- inc = 30;
- slp = 30 * hz;
- } else if (isp->isp_osinfo.loop_down_time > 1) {
- slp = hz;
+ } else if (isp->isp_osinfo.loop_down_time < 10) {
+ slp = 1;
+ } else if (isp->isp_osinfo.loop_down_time < 30) {
+ slp = 5;
+ } else if (isp->isp_osinfo.loop_down_time < 60) {
+ slp = 10;
+ } else if (isp->isp_osinfo.loop_down_time < 120) {
+ slp = 20;
} else {
- slp = 1;
+ slp = 30;
}
- inc += isp->isp_osinfo.loop_down_time;
- if (inc < 0xffff) {
- isp->isp_osinfo.loop_down_time = inc;
- } else {
- isp->isp_osinfo.loop_down_time = 0xfffe;
- }
} else {
- isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state OK");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "isp_kthread: FC state OK");
isp->isp_osinfo.loop_down_time = 0;
slp = 0;
}
@@ -2350,18 +2376,24 @@
wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
- isp_prt(isp, ISP_LOGDEBUG0, "kthread: releasing simq");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "isp_kthread: releasing simq");
ISPLOCK_2_CAMLOCK(isp);
xpt_release_simq(isp->isp_sim, 1);
CAMLOCK_2_ISPLOCK(isp);
}
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "isp_kthread: sleep time %d", slp);
#if __FreeBSD_version < 500000
- tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf", slp);
+ tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf",
+ slp * hz);
#else
#ifdef ISP_SMPLOCK
- cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock, slp);
+ cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock,
+ slp * hz);
#else
- (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf", slp);
+ (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf",
+ slp * hz);
#endif
#endif
/*
@@ -2372,6 +2404,9 @@
* to settle.
*/
if (slp == 0 && isp->isp_osinfo.hysteresis) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "isp_kthread: sleep hysteresis tick time %d",
+ isp->isp_osinfo.hysteresis * hz);
(void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
(isp->isp_osinfo.hysteresis * hz));
}
@@ -2381,7 +2416,7 @@
static void
isp_action(struct cam_sim *sim, union ccb *ccb)
{
- int bus, tgt, error;
+ int bus, tgt, error, lim;
ispsoftc_t *isp;
struct ccb_trans_settings *cts;
@@ -2456,11 +2491,37 @@
}
break;
case CMD_RQLATER:
- ISPLOCK_2_CAMLOCK(isp);
/*
* This can only happen for Fibre Channel
*/
KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
+
+ /*
+ * Handle initial and subsequent loop down cases
+ */
+ if (FCPARAM(isp)->loop_seen_once == 0) {
+ lim = isp_quickboot_time;
+ } else {
+ lim = isp->isp_osinfo.loop_down_limit;
+ }
+ if (isp->isp_osinfo.loop_down_time >= lim) {
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "%d.%d downtime (%d) > lim (%d)",
+ XS_TGT(ccb), XS_LUN(ccb),
+ isp->isp_osinfo.loop_down_time, lim);
+ ccb->ccb_h.status =
+ CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ ISPLOCK_2_CAMLOCK(isp);
+ xpt_done(ccb);
+ break;
+ }
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "%d.%d retry later", XS_TGT(ccb), XS_LUN(ccb));
+ /*
+ * Otherwise, retry in a while.
+ */
+ ISPLOCK_2_CAMLOCK(isp);
cam_freeze_devq(ccb->ccb_h.path);
cam_release_devq(ccb->ccb_h.path,
RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
@@ -3244,6 +3305,8 @@
* If the loop down timer is running, cancel it.
*/
if (isp->isp_osinfo.ldt_running) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Stopping Loop Down Timer");
isp->isp_osinfo.ldt_running = 0;
untimeout(isp_ldt, isp, isp->isp_osinfo.ldt);
callout_handle_init(&isp->isp_osinfo.ldt);
More information about the p4-projects
mailing list