Date: Thu, 9 Nov 2006 05:14:43 GMT From: Matt Jacob <mjacob@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 109591 for review Message-ID: <200611090514.kA95Eha3084751@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=109591 Change 109591 by mjacob@newisp on 2006/11/09 05:14:05 Add a loop down timer that will then cause devices to get marked lost if it expires. This is a tunable value that can be set. Affected files ... .. //depot/projects/newisp/dev/isp/isp_freebsd.c#21 edit .. //depot/projects/newisp/dev/isp/isp_freebsd.h#13 edit .. //depot/projects/newisp/dev/isp/isp_pci.c#17 edit .. //depot/projects/newisp/dev/isp/ispvar.h#12 edit Differences ... ==== //depot/projects/newisp/dev/isp/isp_freebsd.c#21 (text+ko) ==== @@ -50,12 +50,16 @@ int isp_loop_down_limit = 300; /* default loop down limit */ int isp_quickboot_time = 5; /* don't wait more than N secs for loop up */ int isp_lost_device_time = 30; /* grace time before reporting device lost */ +static const char *roles[4] = { + "(none)", "Target", "Initiator", "Target/Initiator" +}; static d_ioctl_t ispioctl; static void isp_intr_enable(void *); static void isp_cam_async(void *, uint32_t, struct cam_path *, void *); static void isp_poll(struct cam_sim *); static timeout_t isp_watchdog; +static timeout_t isp_ldt; static void isp_kthread(void *); static void isp_action(struct cam_sim *, union ccb *); @@ -633,12 +637,9 @@ struct sysctl_oid *tree = device_get_sysctl_tree(isp->isp_osinfo.dev); if (IS_SCSI(isp)) { - isp->isp_osinfo.sysctl_info.spi.iid = DEFAULT_IID(isp); - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "iid", - CTLFLAG_RD, &isp->isp_osinfo.sysctl_info.spi.iid, 0, - "Initiator ID"); return; } + snprintf(isp->isp_osinfo.sysctl_info.fc.wwnn, sizeof (isp->isp_osinfo.sysctl_info.fc.wwnn), "0x%08x%08x", (uint32_t) (ISP_NODEWWN(isp) >> 32), (uint32_t) ISP_NODEWWN(isp)); @@ -650,9 +651,21 @@ SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "wwnn", CTLFLAG_RD, isp->isp_osinfo.sysctl_info.fc.wwnn, 0, "World Wide Node Name"); + SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "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", + 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"); + + printf("loop_down %d loop_down_limit %d\n", + isp->isp_osinfo.loop_down_time, isp->isp_osinfo.loop_down_limit); } #endif @@ -2090,12 +2103,78 @@ } static void +isp_ldt(void *arg) +{ + ispsoftc_t *isp = arg; + fcportdb_t *lp; + static const char prom3[] = + "PortID 0x%06x handle 0x%x role %s %s tgt %u because of %s\n" + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + struct cam_path *tmppath; + int dbidx, tgt; + + isp_prt(isp, ISP_LOGALL, "LDT EXPIRED"); + ISP_LOCK(isp); + + /* + * Notify to the OS all targets who we now consider have departed. + */ + for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { + lp = &FCPARAM(isp)->portdb[dbidx]; + + if (lp->state != FC_PORTDB_STATE_PROBATIONAL) { + continue; + } + if (lp->ini_map_idx == 0) { + continue; + } + + /* + * XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST! + */ + + /* + * Mark that we've announced that this device is gone.... + */ + lp->reserved = 1; + + /* + * but *don't* change the state of the entry. Just clear + * any target id stuff and announce to CAM that the + * device is gone. This way any necessary PLOGO stuff + * will happen when loop comes back up. + */ + + tgt = lp->ini_map_idx - 1; + FCPARAM(isp)->isp_ini_map[tgt] = 0; + lp->ini_map_idx = 0; + isp_prt(isp, ISP_LOGCONFIG, prom3, + lp->portid, lp->handle, + roles[lp->roles & 0x3], "departed from", tgt, + "LOOP Down Timeout", + (uint32_t) (lp->node_wwn >> 32), + (uint32_t) lp->node_wwn, + (uint32_t) (lp->port_wwn >> 32), + (uint32_t) lp->port_wwn); +#if __FreeBSD_version >= 500000 + ISPLOCK_2_CAMLOCK(isp); + if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim), + tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + CAMLOCK_2_ISPLOCK(isp); + continue; + } + xpt_async(AC_LOST_DEVICE, tmppath, NULL); + xpt_free_path(tmppath); + CAMLOCK_2_ISPLOCK(isp); +#endif + } +} + +static void isp_kthread(void *arg) { ispsoftc_t *isp = arg; int slp; - - #if __FreeBSD_version < 500000 int s; @@ -2796,15 +2875,13 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg) { int bus, rv = 0; - static const char *roles[4] = { - "(none)", "Target", "Initiator", "Target/Initiator" - }; static const char prom[] = "PortID 0x%06x handle 0x%x role %s %s\n" - " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; static const char prom2[] = "PortID 0x%06x handle 0x%x role %s %s tgt %u\n" - " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + " WWNN 0x%08x%08x WWPN 0x%08x%08x"; + char *msg = NULL; target_id_t tgt; fcportdb_t *lp; struct cam_path *tmppath; @@ -2891,22 +2968,29 @@ } break; case ISPASYNC_LIP: - if (isp->isp_path) { - isp_freeze_loopdown(isp, "ISPASYNC_LIP"); + if (msg == NULL) { + msg = "LIP Received"; } - isp_prt(isp, ISP_LOGINFO, "LIP Received"); - break; + /* FALLTHROUGH */ case ISPASYNC_LOOP_RESET: - if (isp->isp_path) { - isp_freeze_loopdown(isp, "ISPASYNC_LOOP_RESET"); + if (msg == NULL) { + msg = "LOOP Reset"; } - isp_prt(isp, ISP_LOGINFO, "Loop Reset Received"); - break; + /* FALLTHROUGH */ case ISPASYNC_LOOP_DOWN: + if (msg == NULL) { + msg = "LOOP Down"; + } if (isp->isp_path) { - isp_freeze_loopdown(isp, "ISPASYNC_LOOP_DOWN"); + isp_freeze_loopdown(isp, msg); + } + if (isp->isp_osinfo.ldt_running == 0) { + isp->isp_osinfo.ldt = timeout(isp_ldt, isp, + isp->isp_osinfo.loop_down_limit * hz); + isp->isp_osinfo.ldt_running = 1; +isp_prt(isp, ISP_LOGALL, "LDT: starting loop down timer for %d seconds", isp->isp_osinfo.loop_down_limit); } - isp_prt(isp, ISP_LOGINFO, "Loop DOWN"); + isp_prt(isp, ISP_LOGINFO, msg); break; case ISPASYNC_LOOP_UP: /* @@ -2919,13 +3003,14 @@ break; case ISPASYNC_DEV_ARRIVED: lp = arg; + lp->reserved = 0; if ((isp->isp_role & ISP_ROLE_INITIATOR) && (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) { int dbidx = lp - FCPARAM(isp)->portdb; int i; for (i = 0; i < MAX_FC_TARG; i++) { - if (i >= FL_ID || i <= SNS_ID) { + if (i >= FL_ID && i <= SNS_ID) { continue; } if (FCPARAM(isp)->isp_ini_map[i] == 0) { @@ -3016,9 +3101,7 @@ case ISPASYNC_DEV_GONE: lp = arg; if (lp->ini_map_idx) { -/* - * XXX: HERE IS WHERE WE'D START A TIMER - */ + lp->reserved = 1; tgt = lp->ini_map_idx - 1; FCPARAM(isp)->isp_ini_map[tgt] = 0; lp->ini_map_idx = 0; @@ -3041,7 +3124,7 @@ xpt_free_path(tmppath); CAMLOCK_2_ISPLOCK(isp); #endif - } else { + } else if (lp->reserved == 0) { isp_prt(isp, ISP_LOGCONFIG, prom, lp->portid, lp->handle, roles[lp->roles & 0x3], "departed", @@ -3049,6 +3132,7 @@ (uint32_t) lp->node_wwn, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn); + lp->reserved = 1; } break; case ISPASYNC_CHANGE_NOTIFY: @@ -3061,6 +3145,11 @@ } else { msg = "Other Change Notify"; } + if (isp->isp_osinfo.ldt_running) { + isp->isp_osinfo.ldt_running = 0; + untimeout(isp_ldt, isp, isp->isp_osinfo.ldt); + callout_handle_init(&isp->isp_osinfo.ldt); + } isp_prt(isp, ISP_LOGINFO, msg); isp_freeze_loopdown(isp, msg); #if __FreeBSD_version < 500000 ==== //depot/projects/newisp/dev/isp/isp_freebsd.h#13 (text+ko) ==== @@ -149,16 +149,18 @@ struct cam_sim *sim2; struct cam_path *path2; struct intr_config_hook ehook; - uint16_t loop_down_time; - uint16_t loop_down_limit; + uint32_t loop_down_time; + uint32_t loop_down_limit; uint32_t : 5, simqfrozen : 3, hysteresis : 8, - : 4, + : 3, + ldt_running : 1, disabled : 1, fcbsy : 1, mboxcmd_done : 1, mboxbsy : 1; + struct callout_handle ldt; /* loop down timer */ #if __FreeBSD_version >= 500000 struct firmware * fw; struct mtx lock; @@ -168,9 +170,6 @@ char wwnn[17]; char wwpn[17]; } fc; - struct { - int iid; - } spi; } sysctl_info; #endif struct proc *kproc; @@ -204,10 +203,17 @@ #define CAMLOCK_2_ISPLOCK(isp) \ mtx_unlock(&Giant); mtx_lock(&(isp)->isp_lock) #else +#if __FreeBSD_version < 500000 #define ISP_LOCK(x) do { } while (0) #define ISP_UNLOCK(x) do { } while (0) #define ISPLOCK_2_CAMLOCK(isp) do { } while (0) #define CAMLOCK_2_ISPLOCK(isp) do { } while (0) +#else +#define ISP_LOCK(x) GIANT_REQUIRED +#define ISP_UNLOCK(x) do { } while (0) +#define ISPLOCK_2_CAMLOCK(isp) do { } while (0) +#define CAMLOCK_2_ISPLOCK(isp) GIANT_REQUIRED +#endif #endif /* @@ -404,8 +410,7 @@ #include <dev/isp/isp_tpublic.h> #endif -void isp_prt(ispsoftc_t *, int level, const char *, ...) - __printflike(3, 4); +void isp_prt(ispsoftc_t *, int level, const char *, ...) __printflike(3, 4); /* * isp_osinfo definiitions && shorthand */ ==== //depot/projects/newisp/dev/isp/isp_pci.c#17 (text+ko) ==== @@ -432,6 +432,8 @@ uint64_t wwn; int bitmap, unit; + callout_handle_init(&isp->isp_osinfo.ldt); + unit = device_get_unit(dev); if (getenv_int("isp_disable", &bitmap)) { if (bitmap & (1 << unit)) { @@ -578,6 +580,9 @@ { int tval; const char *sptr; + + callout_handle_init(&isp->isp_osinfo.ldt); + /* * Figure out if we're supposed to skip this one. */ @@ -733,7 +738,7 @@ isp->isp_osinfo.hysteresis = isp_fabric_hysteresis; } - tval = 0; + tval = -1; (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "loop_down_limit", &tval); if (tval >= 0 && tval < 0xffff) { @@ -795,7 +800,7 @@ isp = &pcs->pci_isp; /* - * Get Generic Options + * Set and Get Generic Options */ isp_get_options(dev, isp); @@ -814,7 +819,6 @@ */ isp_get_pci_options(dev, &m1, &m2); - linesz = PCI_DFLT_LNSZ; irq = regs = NULL; rgd = rtp = iqd = 0; ==== //depot/projects/newisp/dev/isp/ispvar.h#12 (text+ko) ==== @@ -326,10 +326,10 @@ uint16_t ini_map_idx : 12, autologin : 1, /* F/W does PLOGI/PLOGO */ state : 3; - uint32_t : 6, + uint32_t reserved : 6, roles : 2, portid : 24; - uint32_t : 6, + uint32_t new_reserved : 6, new_roles : 2, new_portid : 24; uint64_t node_wwn;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611090514.kA95Eha3084751>