PERFORCE change 109591 for review
Matt Jacob
mjacob at FreeBSD.org
Thu Nov 9 05:14:45 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=109591
Change 109591 by mjacob at 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;
More information about the p4-projects
mailing list