From owner-p4-projects@FreeBSD.ORG Tue Nov 14 08:33:59 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 5397216A417; Tue, 14 Nov 2006 08:33:59 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E4BC116A403 for ; Tue, 14 Nov 2006 08:33:58 +0000 (UTC) (envelope-from mjacob@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id AE34043D45 for ; Tue, 14 Nov 2006 08:33:58 +0000 (GMT) (envelope-from mjacob@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id kAE8XwlX065346 for ; Tue, 14 Nov 2006 08:33:58 GMT (envelope-from mjacob@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id kAE8Xw0v065342 for perforce@freebsd.org; Tue, 14 Nov 2006 08:33:58 GMT (envelope-from mjacob@freebsd.org) Date: Tue, 14 Nov 2006 08:33:58 GMT Message-Id: <200611140833.kAE8Xw0v065342@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to mjacob@freebsd.org using -f From: Matt Jacob To: Perforce Change Reviews Cc: Subject: PERFORCE change 109909 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Nov 2006 08:33:59 -0000 http://perforce.freebsd.org/chv.cgi?CH=109909 Change 109909 by mjacob@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);