PERFORCE change 109812 for review
Matt Jacob
mjacob at FreeBSD.org
Sun Nov 12 18:57:18 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=109812
Change 109812 by mjacob at newisp on 2006/11/12 18:56:32
Macroize isp_mark_portdb so we can print out debugging aboutg
where we invalidate the portdb. Add more SANCFG printouts.
Add a ZOMBIE state to portdb entries- this is exempt from being
marked by isp_mark_portdb. When we arrive in isp_pdb_sync and
announce to the outer layers that a device is 'gone', it has the
option of setting the portdb entry as being 'ZOMBIE' and setting
a timer that will be used to clear the entry entirely or handle
it arriving again before the timeout.
For FreeBSD, implement both a loop down and a gone device timer.
Add a isp_mstohz function.
Affected files ...
.. //depot/projects/newisp/dev/isp/isp.c#29 edit
.. //depot/projects/newisp/dev/isp/isp_freebsd.c#23 edit
.. //depot/projects/newisp/dev/isp/isp_freebsd.h#16 edit
Differences ...
==== //depot/projects/newisp/dev/isp/isp.c#29 (text+ko) ====
@@ -60,6 +60,9 @@
*/
#define MBOX_DELAY_COUNT 1000000 / 100
+#define ISP_MARK_PORTDB(a, b) \
+ isp_prt(isp, ISP_LOGSANCFG, "line %d: markportdb", __LINE__); \
+ isp_mark_portdb(a, b)
/*
* Local static data
@@ -116,7 +119,7 @@
static int isp_getpdb(ispsoftc_t *, uint16_t, isp_pdb_t *, int);
static uint64_t isp_get_portname(ispsoftc_t *, int, int);
static int isp_fclink_test(ispsoftc_t *, int);
-static const char *isp2100_fw_statename(int);
+static const char *ispfc_fw_statename(int);
static int isp_pdb_sync(ispsoftc_t *);
static int isp_scan_loop(ispsoftc_t *);
static int isp_gid_ft_sns(ispsoftc_t *);
@@ -1172,7 +1175,7 @@
/*
* Do this *before* initializing the firmware.
*/
- isp_mark_portdb(isp, 0);
+ ISP_MARK_PORTDB(isp, 0);
FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
FCPARAM(isp)->isp_loopstate = LOOP_NIL;
@@ -2053,7 +2056,6 @@
int i;
for (i = 0; i < MAX_FC_TARG; i++) {
- fcp->isp_ini_map[i] = 0;
if (onprobation == 0) {
MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
} else {
@@ -2065,6 +2067,8 @@
fcp->portdb[i].state =
FC_PORTDB_STATE_PROBATIONAL;
break;
+ case FC_PORTDB_STATE_ZOMBIE:
+ break;
case FC_PORTDB_STATE_NIL:
default:
MEMZERO(&fcp->portdb[i], sizeof (fcportdb_t));
@@ -2415,8 +2419,8 @@
fcp = isp->isp_param;
- isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Entry");
- isp_mark_portdb(isp, 1);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Link Test Entry");
+ ISP_MARK_PORTDB(isp, 1);
/*
* Wait up to N microseconds for F/W to go to a ready state.
@@ -2431,9 +2435,10 @@
GET_NANOTIME(&hra);
isp_fw_state(isp);
if (lwfs != fcp->isp_fwstate) {
- isp_prt(isp, ISP_LOGINFO, "Firmware State <%s->%s>",
- isp2100_fw_statename((int)lwfs),
- isp2100_fw_statename((int)fcp->isp_fwstate));
+ isp_prt(isp, ISP_LOGCONFIG|ISP_LOGSANCFG,
+ "Firmware State <%s->%s>",
+ ispfc_fw_statename((int)lwfs),
+ ispfc_fw_statename((int)fcp->isp_fwstate));
lwfs = fcp->isp_fwstate;
}
if (fcp->isp_fwstate == FW_READY) {
@@ -2485,7 +2490,7 @@
* If we haven't gone to 'ready' state, return.
*/
if (fcp->isp_fwstate != FW_READY) {
- isp_prt(isp, ISP_LOGDEBUG0,
+ isp_prt(isp, ISP_LOGSANCFG,
"isp_fclink_test: not at FW_READY state");
return (-1);
}
@@ -2597,19 +2602,19 @@
/*
* Announce ourselves, too.
*/
- isp_prt(isp, ISP_LOGCONFIG, topology, fcp->isp_portid,
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, topology, fcp->isp_portid,
fcp->isp_loopid, toponames[fcp->isp_topo]);
- isp_prt(isp, ISP_LOGCONFIG, ourwwn,
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGCONFIG, ourwwn,
(uint32_t) (ISP_NODEWWN(isp) >> 32),
(uint32_t) ISP_NODEWWN(isp),
(uint32_t) (ISP_PORTWWN(isp) >> 32),
(uint32_t) ISP_PORTWWN(isp));
- isp_prt(isp, ISP_LOGDEBUG0, "FC Link Test Complete");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Link Test Complete");
return (0);
}
static const char *
-isp2100_fw_statename(int state)
+ispfc_fw_statename(int state)
{
switch(state) {
case FW_CONFIG_WAIT: return "Config Wait";
@@ -2688,6 +2693,8 @@
}
}
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Synchronizing PDBs");
+
fcp->isp_loopstate = LOOP_SYNCING_PDB;
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
@@ -2712,8 +2719,8 @@
/*
* It's up to the outer layers to clear isp_ini_map.
*/
+ lp->state = FC_PORTDB_STATE_NIL;
isp_async(isp, ISPASYNC_DEV_GONE, lp);
- lp->state = FC_PORTDB_STATE_NIL;
if (lp->autologin == 0) {
if (IS_24XX(isp)) {
int action =
@@ -2733,38 +2740,35 @@
}
lp->new_roles = 0;
lp->new_portid = 0;
+ /*
+ * Note that we might come out of this with our state
+ * set to FC_PORTDB_STATE_ZOMBIE.
+ */
break;
case FC_PORTDB_STATE_NEW:
/*
- * If *we* have a new target dole and *it* has a target
- * role, assign a new target id to it.
+ * It's up to the outer layers to assign a virtual
+ * target id in isp_ini_map (if any).
*/
lp->portid = lp->new_portid;
lp->roles = lp->new_roles;
- /*
- * It's up to the outer layers to assign a virtual
- * target id in isp_ini_map (if any).
- */
+ lp->state = FC_PORTDB_STATE_VALID;
isp_async(isp, ISPASYNC_DEV_ARRIVED, lp);
- lp->state = FC_PORTDB_STATE_VALID;
lp->new_roles = 0;
lp->new_portid = 0;
+ lp->reserved = 0;
+ lp->new_reserved = 0;
break;
case FC_PORTDB_STATE_CHANGED:
- /*
- * For now, just have a policy of accepting 'changed'
- * devices.
- */
- lp->portid = lp->new_portid;
- lp->roles = lp->new_roles;
- if (lp->ini_map_idx) {
- int t = lp->ini_map_idx - 1;
- fcp->isp_ini_map[t] = dbidx + 1;
- }
+/*
+ * XXXX FIX THIS
+ */
+ lp->state = FC_PORTDB_STATE_VALID;
isp_async(isp, ISPASYNC_DEV_CHANGED, lp);
- lp->state = FC_PORTDB_STATE_VALID;
lp->new_roles = 0;
lp->new_portid = 0;
+ lp->reserved = 0;
+ lp->new_reserved = 0;
break;
case FC_PORTDB_STATE_PENDING_VALID:
lp->portid = lp->new_portid;
@@ -2773,15 +2777,20 @@
int t = lp->ini_map_idx - 1;
fcp->isp_ini_map[t] = dbidx + 1;
}
+ lp->state = FC_PORTDB_STATE_VALID;
isp_async(isp, ISPASYNC_DEV_STAYED, lp);
- lp->state = FC_PORTDB_STATE_VALID;
if (dbidx != FL_ID) {
lp->new_roles = 0;
lp->new_portid = 0;
}
+ lp->reserved = 0;
+ lp->new_reserved = 0;
+ break;
+ case FC_PORTDB_STATE_ZOMBIE:
break;
default:
- isp_prt(isp, ISP_LOGERR, "eh? state %d for idx %d",
+ isp_prt(isp, ISP_LOGWARN,
+ "isp_scan_loop: state %d for idx %d",
lp->state, dbidx);
isp_dump_portdb(isp);
}
@@ -2807,7 +2816,7 @@
fcparam *fcp = isp->isp_param;
int i;
isp_pdb_t pdb;
- uint16_t dbidx, lim = 0;
+ uint16_t handle, lim = 0;
if (fcp->isp_fwstate < FW_READY ||
fcp->isp_loopstate < LOOP_PDB_RCVD) {
@@ -2844,17 +2853,18 @@
}
fcp->isp_loopstate = LOOP_SCANNING_LOOP;
- isp_prt(isp, ISP_LOGDEBUG0, "scanning loop 0..%d", lim-1);
+
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC scan loop 0..%d", lim-1);
/*
* Run through the list and get the port database info for each one.
*/
- for (dbidx = 0; dbidx < lim; dbidx++) {
+ for (handle = 0; handle < lim; handle++) {
/*
* But don't even try for ourselves...
*/
- if (dbidx == fcp->isp_loopid) {
+ if (handle == fcp->isp_loopid) {
continue;
}
@@ -2863,7 +2873,7 @@
* known to hang. This trick gets around that problem.
*/
if (IS_2100(isp) || IS_2200(isp)) {
- uint64_t node_wwn = isp_get_portname(isp, dbidx, 1);
+ uint64_t node_wwn = isp_get_portname(isp, handle, 1);
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
return (-1);
}
@@ -2875,29 +2885,29 @@
/*
* Get the port database entity for this index.
*/
- if (isp_getpdb(isp, dbidx, &pdb, 1) != 0) {
+ if (isp_getpdb(isp, handle, &pdb, 1) != 0) {
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
return (-1);
}
continue;
}
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
return (-1);
}
/*
* On *very* old 2100 firmware we would end up sometimes
* with the firmware returning the port database entry
- * for something else. We used to restart locally, but
- * now we punt.
+ * for something else. We used to restart this, but
+ * now we just punt.
*/
- if (IS_2100(isp) && pdb.handle != dbidx) {
+ if (IS_2100(isp) && pdb.handle != handle) {
isp_prt(isp, ISP_LOGWARN,
"giving up on synchronizing the port database");
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
return (-1);
}
@@ -2916,8 +2926,7 @@
* which shift on a loop.
*/
if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) {
- isp_prt(isp, ISP_LOGWARN,
- "bad pdb entry at loop %d", dbidx);
+ isp_prt(isp, ISP_LOGWARN, "bad pdb @ loop %d", handle);
isp_dump_portdb(isp);
continue;
}
@@ -2940,22 +2949,27 @@
/*
* Okay- we've found a non-nil entry that matches.
- * Check to make sure it's probational.
+ * Check to make sure it's probational or a zombie.
*/
- if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
+ if (lp->state != FC_PORTDB_STATE_PROBATIONAL &&
+ lp->state != FC_PORTDB_STATE_ZOMBIE) {
isp_prt(isp, ISP_LOGERR,
- "portdb entry %d not probational (0x%x)",
+ "[%d] not probational/zombie (0x%x)",
i, lp->state);
isp_dump_portdb(isp);
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
return (-1);
}
+ /*
+ * Mark the device as something the f/w logs into
+ * automatically.
+ */
lp->autologin = 1;
+
/*
- * Check to make sure it's really the same
- * device and update the initiator map before
- * we mark it as pending valid.
+ * Check to make see if really still the same
+ * device. If it is, we mark it pending valid.
*/
if (lp->portid == tmp.portid &&
lp->handle == tmp.handle &&
@@ -2963,12 +2977,15 @@
lp->new_portid = tmp.portid;
lp->new_roles = tmp.roles;
lp->state = FC_PORTDB_STATE_PENDING_VALID;
+ isp_prt(isp, ISP_LOGSANCFG,
+ "Loop Port 0x%06x at 0x%x Pending Valid",
+ tmp.portid, tmp.handle);
break;
}
/*
- * We can wipe out the old handle value here because
- * it's no longer valid.
+ * We can wipe out the old handle value
+ * here because it's no longer valid.
*/
lp->handle = tmp.handle;
@@ -2976,6 +2993,9 @@
* Claim that this has changed and let somebody else
* decide what to do.
*/
+ isp_prt(isp, ISP_LOGSANCFG,
+ "Loop Port 0x%06x at 0x%x changed",
+ tmp.portid, tmp.handle);
lp->state = FC_PORTDB_STATE_CHANGED;
lp->new_portid = tmp.portid;
lp->new_roles = tmp.roles;
@@ -2999,23 +3019,23 @@
}
}
if (i == MAX_FC_TARG) {
- isp_prt(isp, ISP_LOGERR,
- "could not find slot for new entry");
+ isp_prt(isp, ISP_LOGERR, "out of portdb entries");
continue;
}
lp = &fcp->portdb[i];
+ MEMZERO(lp, sizeof (fcportdb_t));
lp->autologin = 1;
lp->state = FC_PORTDB_STATE_NEW;
- lp->portid = 0;
- lp->roles = 0;
lp->new_portid = tmp.portid;
lp->new_roles = tmp.roles;
lp->handle = tmp.handle;
lp->port_wwn = tmp.port_wwn;
lp->node_wwn = tmp.node_wwn;
+ isp_prt(isp, ISP_LOGSANCFG,
+ "Loop Port 0x%06x at 0x%x is New Entry",
+ tmp.portid, tmp.handle);
}
-
fcp->isp_loopstate = LOOP_LSCAN_DONE;
return (0);
}
@@ -3196,7 +3216,7 @@
int portidx, portlim, r;
sns_gid_ft_rsp_t *rs0, *rs1;
- isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Scan Fabric");
if (fcp->isp_fwstate != FW_READY ||
fcp->isp_loopstate < LOOP_LSCAN_DONE) {
return (-1);
@@ -3206,7 +3226,8 @@
}
if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
- isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric Done (no fabric)");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "FC Scan Fabric Done (no fabric)");
return (0);
}
@@ -3241,7 +3262,7 @@
int level;
if (rs1->snscb_cthdr.ct_reason == 9 &&
rs1->snscb_cthdr.ct_explanation == 7) {
- level = ISP_LOGDEBUG0;
+ level = ISP_LOGSANCFG|ISP_LOGDEBUG0;
} else {
level = ISP_LOGWARN;
}
@@ -3286,8 +3307,8 @@
"fabric too big for scratch area: increase ISP2100_SCRLEN");
}
portlim = portidx + 1;
- isp_prt(isp, ISP_LOGDEBUG0, "got %d ports back from name server",
- portlim);
+ isp_prt(isp, ISP_LOGSANCFG,
+ "got %d ports back from name server", portlim);
for (portidx = 0; portidx < portlim; portidx++) {
int npidx;
@@ -3311,7 +3332,7 @@
rs1->snscb_ports[npidx].portid[0] = 0;
rs1->snscb_ports[npidx].portid[1] = 0;
rs1->snscb_ports[npidx].portid[2] = 0;
- isp_prt(isp, ISP_LOGDEBUG0,
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"removing duplicate PortID 0x%x entry from list",
portid);
}
@@ -3344,7 +3365,7 @@
((rs1->snscb_ports[portidx].portid[2]));
if (portid == 0) {
- isp_prt(isp, ISP_LOGDEBUG0,
+ isp_prt(isp, ISP_LOGSANCFG,
"skipping null PortID at idx %d", portidx);
continue;
}
@@ -3353,15 +3374,18 @@
* Skip ourselves...
*/
if (portid == fcp->isp_portid) {
- isp_prt(isp, ISP_LOGDEBUG0,
+ isp_prt(isp, ISP_LOGSANCFG,
"skip ourselves @ PortID 0x%06x", portid);
continue;
}
- isp_prt(isp, ISP_LOGDEBUG0, "Fabric Port 0x%06x", portid);
+ isp_prt(isp, ISP_LOGSANCFG,
+ "Checking Fabric Port 0x%06x", portid);
/*
* We now search our Port Database for any
- * probational entries with this PortID.
+ * probational entries with this PortID. We don't
+ * look for zombies here- only probational
+ * entries (we've already logged out of zombies).
*/
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
lp = &fcp->portdb[dbidx];
@@ -3402,12 +3426,15 @@
r = isp_getpdb(isp, lp->handle, &pdb, 0);
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp);
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
return (-1);
}
if (r != 0) {
lp->new_portid = portid;
lp->state = FC_PORTDB_STATE_DEAD;
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Fabric Port 0x%06x considered dead",
+ portid);
continue;
}
@@ -3424,8 +3451,8 @@
pdb.portid != portid ||
wwpn != lp->port_wwn ||
wwnn != lp->node_wwn) {
- isp_prt(isp, ISP_LOGDEBUG0, fconf, dbidx,
- pdb.handle, pdb.portid,
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ fconf, dbidx, pdb.handle, pdb.portid,
(uint32_t) (wwnn >> 32), (uint32_t) wwnn,
(uint32_t) (wwpn >> 32), (uint32_t) wwpn,
lp->handle, portid,
@@ -3448,7 +3475,7 @@
if (fcp->isp_loopstate !=
LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp);
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
return (-1);
}
continue;
@@ -3486,8 +3513,13 @@
lp->new_roles = nr;
if (pdb.portid != lp->portid || nr != lp->roles ||
handle_changed) {
+ isp_prt(isp, ISP_LOGSANCFG,
+ "Fabric Port 0x%06x changed", portid);
lp->state = FC_PORTDB_STATE_CHANGED;
} else {
+ isp_prt(isp, ISP_LOGSANCFG,
+ "Fabric Port 0x%06x Now Pending Valid",
+ portid);
lp->state = FC_PORTDB_STATE_PENDING_VALID;
}
continue;
@@ -3495,49 +3527,54 @@
/*
* Ah- a new entry. Search the database again for all non-NIL
- * entries to make sure we never ever make a database entry
- * with the same port id.
+ * entries to make sure we never ever make a new database entry
+ * with the same port id. While we're at it, mark where the
+ * last free entry was.
*/
- for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
- if (dbidx >= FL_ID && dbidx <= SNS_ID) {
+
+ dbidx = MAX_FC_TARG;
+ for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
+ if (lp >= &fcp->portdb[FL_ID] &&
+ lp <= &fcp->portdb[SNS_ID]) {
+ continue;
+ }
+ if (lp->state == FC_PORTDB_STATE_NIL) {
+ if (dbidx == MAX_FC_TARG) {
+ dbidx = lp - fcp->portdb;
+ }
continue;
}
- if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
+ if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
continue;
}
- if (fcp->portdb[dbidx].portid == portid) {
+ if (lp->portid == portid) {
break;
}
}
- if (dbidx != MAX_FC_TARG) {
+ if (lp < &fcp->portdb[MAX_FC_TARG]) {
isp_prt(isp, ISP_LOGWARN,
"PortID 0x%06x already at %d handle %d state %d",
- portid, dbidx, fcp->portdb[dbidx].handle,
- fcp->portdb[dbidx].state);
+ portid, dbidx, lp->handle, lp->state);
continue;
}
/*
- * Find an empty database entry for it.
+ * We should have the index of the first free entry seen.
*/
- for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
- if (dbidx >= FL_ID && dbidx <= SNS_ID) {
- continue;
- }
- if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
- break;
- }
- }
-
if (dbidx == MAX_FC_TARG) {
isp_prt(isp, ISP_LOGERR,
- "port database too small to login fabric device"
- "- increase MAX_FC_TARG");
+ "port database too small to login PortID 0x%06x"
+ "- increase MAX_FC_TARG", portid);
continue;
}
/*
+ * Otherwise, point to our new home.
+ */
+ lp = &fcp->portdb[dbidx];
+
+ /*
* Try to see if we are logged into this device,
* and maybe log into it.
*
@@ -3547,7 +3584,7 @@
if (isp_login_device(isp, portid, &pdb, &oldhandle)) {
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp);
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
return (-1);
}
continue;
@@ -3563,13 +3600,11 @@
* that we do not make more than one entry that has the same
* WWNN/WWPN duple
*/
- lp = &fcp->portdb[dbidx];
-
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
- if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
+ if (dbidx >= FL_ID && dbidx <= SNS_ID) {
continue;
}
- if (dbidx >= FL_ID && dbidx <= SNS_ID) {
+ if (fcp->portdb[dbidx].state == FC_PORTDB_STATE_NIL) {
continue;
}
if (fcp->portdb[dbidx].node_wwn == wwnn &&
@@ -3578,33 +3613,61 @@
}
}
- if (dbidx != MAX_FC_TARG) {
+ if (dbidx == MAX_FC_TARG) {
+ MEMZERO(lp, sizeof (fcportdb_t));
+ lp->handle = handle;
+ lp->node_wwn = wwnn;
+ lp->port_wwn = wwpn;
+ lp->new_portid = portid;
+ lp->new_roles = nr;
+ lp->state = FC_PORTDB_STATE_NEW;
+ isp_prt(isp, ISP_LOGSANCFG,
+ "Fabric Port 0x%06x is New Entry", portid);
+ continue;
+ }
+
+ if (fcp->portdb[dbidx].state != FC_PORTDB_STATE_ZOMBIE) {
isp_prt(isp, ISP_LOGWARN,
"PortID 0x%x 0x%08x%08x/0x%08x%08x %ld already at "
- "idx %d", portid,
+ "idx %d, state 0x%x", portid,
(uint32_t) (wwnn >> 32), (uint32_t) wwnn,
(uint32_t) (wwpn >> 32), (uint32_t) wwpn,
- (long) (lp - fcp->portdb), dbidx);
+ (long) (lp - fcp->portdb), dbidx,
+ fcp->portdb[dbidx].state);
continue;
}
+ /*
+ * We found a zombie entry that matches us.
+ * Revive it. We know that WWN and WWPN
+ * are the same. For fabric devices, we
+ * don't care that handle is different
+ * as we assign that. If role or portid
+ * are different, it maybe a changed device.
+ */
+ lp = &fcp->portdb[dbidx];
lp->handle = handle;
- lp->ini_map_idx = 0;
- lp->node_wwn = wwnn;
- lp->port_wwn = wwpn;
lp->new_portid = portid;
lp->new_roles = nr;
- lp->state = FC_PORTDB_STATE_NEW;
+ if (lp->portid != portid || lp->roles != nr) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Zombie Fabric Port 0x%06x Now Changed", portid);
+ lp->state = FC_PORTDB_STATE_CHANGED;
+ } else {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Zombie Fabric Port 0x%06x Now Pending Valid",
+ portid);
+ lp->state = FC_PORTDB_STATE_PENDING_VALID;
+ }
}
-
FC_SCRATCH_RELEASE(isp);
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
return (-1);
}
fcp->isp_loopstate = LOOP_FSCAN_DONE;
- isp_prt(isp, ISP_LOGDEBUG0, "FC Scan Fabric Done");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "FC Scan Fabric Done");
return (0);
}
@@ -3674,7 +3737,7 @@
}
if (i == lim) {
- isp_prt(isp, ISP_LOGINFO, "PLOGI 0x%06x failed", portid);
+ isp_prt(isp, ISP_LOGWARN, "PLOGI 0x%06x failed", portid);
return (-1);
}
@@ -3832,14 +3895,16 @@
FC_SCRATCH_RELEASE(isp);
if (ct->ct_cmd_resp == LS_RJT) {
- isp_prt(isp, ISP_LOGWARN, "Register FC4 Type rejected");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Register FC4 Type rejected");
return (-1);
} else if (ct->ct_cmd_resp == LS_ACC) {
- isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 Type accepted");
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Register FC4 Type accepted");
return(0);
} else {
isp_prt(isp, ISP_LOGWARN,
- "Register FC4 Type: %x", ct->ct_cmd_resp);
+ "Register FC4 Type: 0x%x", ct->ct_cmd_resp);
return (-1);
}
}
@@ -3934,9 +3999,12 @@
if (IS_FC(isp)) {
fcparam *fcp = isp->isp_param;
+ /*
+ * Try again later.
+ */
if (fcp->isp_fwstate != FW_READY ||
fcp->isp_loopstate != LOOP_READY) {
- return (CMD_RQLATER);
+ return (CMD_EAGAIN);
}
if (XS_TGT(xs) >= MAX_FC_TARG) {
@@ -3951,6 +4019,13 @@
XS_SETERR(xs, HBA_SELTIMEOUT);
return (CMD_COMPLETE);
}
+ if (fcp->portdb[hdlidx].state == FC_PORTDB_STATE_ZOMBIE) {
+ return (CMD_RQLATER);
+ }
+ if (fcp->portdb[hdlidx].state != FC_PORTDB_STATE_VALID) {
+ XS_SETERR(xs, HBA_SELTIMEOUT);
+ return (CMD_COMPLETE);
+ }
target = fcp->portdb[hdlidx].handle;
}
@@ -5111,7 +5186,7 @@
FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
isp->isp_sendmarker = 1;
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
isp_async(isp, ISPASYNC_LIP, NULL);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, bus, mbox)) {
@@ -5147,7 +5222,7 @@
isp->isp_sendmarker = 1;
FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
isp_async(isp, ISPASYNC_LOOP_UP, NULL);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, bus, mbox)) {
@@ -5160,7 +5235,7 @@
isp->isp_sendmarker = 1;
FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
FCPARAM(isp)->isp_loopstate = LOOP_NIL;
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
isp_async(isp, ISPASYNC_LOOP_DOWN, NULL);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, bus, mbox)) {
@@ -5173,7 +5248,7 @@
isp->isp_sendmarker = 1;
FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
FCPARAM(isp)->isp_loopstate = LOOP_NIL;
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
isp_async(isp, ISPASYNC_LOOP_RESET, NULL);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, bus, mbox)) {
@@ -5185,7 +5260,7 @@
case ASYNC_PDB_CHANGED:
isp->isp_sendmarker = 1;
FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_PDB);
break;
@@ -5195,12 +5270,12 @@
} else {
FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
}
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_SNS);
break;
case ASYNC_PTPMODE:
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
isp->isp_sendmarker = 1;
FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD;
@@ -5215,7 +5290,7 @@
case ASYNC_CONNMODE:
mbox = ISP_READ(isp, OUTMAILBOX1);
- isp_mark_portdb(isp, 1);
+ ISP_MARK_PORTDB(isp, 1);
switch (mbox) {
case ISP_CONN_LOOP:
isp_prt(isp, ISP_LOGINFO,
@@ -5707,14 +5782,6 @@
mbs.logval = MBLOGALL;
isp_mboxcmd_qnw(isp, &mbs, 1);
}
-
- /*
- * Probably overkill.
- */
- isp->isp_sendmarker = 1;
- FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
- isp_mark_portdb(isp, 1);
- isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_SELTIMEOUT);
}
@@ -5865,14 +5932,6 @@
mbs.logval = MBLOGALL;
isp_mboxcmd_qnw(isp, &mbs, 1);
}
-
- /*
- * Probably overkill.
- */
- isp->isp_sendmarker = 1;
- FCPARAM(isp)->isp_loopstate = LOOP_PDB_RCVD;
- isp_mark_portdb(isp, 1);
- isp_async(isp, ISPASYNC_CHANGE_NOTIFY, ISPASYNC_CHANGE_OTHER);
if (XS_NOERR(xs)) {
XS_SETERR(xs, HBA_SELTIMEOUT);
}
@@ -7104,7 +7163,7 @@
uint32_t tmp;
if (IS_FC(isp)) {
- isp_mark_portdb(isp, 0);
+ ISP_MARK_PORTDB(isp, 0);
}
isp_reset(isp);
if (isp->isp_state != ISP_RESETSTATE) {
==== //depot/projects/newisp/dev/isp/isp_freebsd.c#23 (text+ko) ====
@@ -41,6 +41,7 @@
#if __FreeBSD_version >= 500000
#include <sys/sysctl.h>
#endif
+#include <cam/cam_periph.h>
MODULE_VERSION(isp, 1);
@@ -50,10 +51,12 @@
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_lost_device_time = 60; /* grace time before reporting device lost */
+int isp_gone_device_time = 60; /* 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 d_ioctl_t ispioctl;
static void isp_intr_enable(void *);
@@ -657,16 +660,20 @@
"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",
+ 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",
+ 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);
+ SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "gone_device_time",
+ CTLFLAG_RW, &isp->isp_osinfo.gone_device_time, 0,
+ "How long to wait for a device to reappear");
}
#endif
@@ -2070,7 +2077,9 @@
if (XS_CMD_DONE_P(xs)) {
isp_prt(isp, ISP_LOGDEBUG2,
"watchdog cleanup for handle 0x%x", handle);
+ ISPLOCK_2_CAMLOCK(isp);
xpt_done((union ccb *) xs);
+ CAMLOCK_2_ISPLOCK(isp);
} else if (XS_CMD_GRACE_P(xs)) {
/*
* Make sure the command is *really* dead before we
@@ -2090,7 +2099,9 @@
"watchdog timeout for handle 0x%x", handle);
XS_SETERR(xs, CAM_CMD_TIMEOUT);
XS_CMD_C_WDOG(xs);
+ ISPLOCK_2_CAMLOCK(isp);
isp_done(xs);
+ CAMLOCK_2_ISPLOCK(isp);
} else {
XS_CMD_C_WDOG(xs);
xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
@@ -2098,20 +2109,103 @@
isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
}
} else {
- isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command");
+ isp_prt(isp, ISP_LOGWARN, "watchdog with no command");
+ }
+ ISP_UNLOCK(isp);
+}
+
+#if __FreeBSD_version >= 500000
+#define isp_make_here(isp, tgt) isp_announce(isp, tgt, AC_FOUND_DEVICE)
+#define isp_make_gone(isp, tgt) isp_announce(isp, tgt, AC_LOST_DEVICE)
+
+/*
+ * Support function for Announcement
+ */
+static void
+isp_announce(ispsoftc_t *isp, int tgt, int action)
+{
+ struct cam_path *tmppath;
+ ISPLOCK_2_CAMLOCK(isp);
+ if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim), tgt,
+ CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
+ xpt_async(action, tmppath, NULL);
+ xpt_free_path(tmppath);
+ }
+ CAMLOCK_2_ISPLOCK(isp);
+}
+#else
+#define isp_make_here(isp, tgt) do { ; } while (0)
+#define isp_make_gone(isp, tgt) do { ; } while (0)
+#endif
+
+
+/*
+ * Gone Device Timer Function- when we have decided that a device has gone
+ * away, we wait a specific period of time prior to telling the OS it has
+ * gone away.
+ *
+ * This timer function fires once a second and then scans the port database
+ * for devices that are marked dead but still have a virtual target assigned.
+ * We decrement a counter for that port database entry, and when it hits zero,
+ * we tell the OS the device has gone away.
+ */
+static void
+isp_gdt(void *arg)
+{
+ ispsoftc_t *isp = arg;
+ fcportdb_t *lp;
+ int dbidx, tgt, more_to_do = 0;
+
+ isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
+ ISP_LOCK(isp);
+ for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
+ lp = &FCPARAM(isp)->portdb[dbidx];
+
+ if (lp->state != FC_PORTDB_STATE_ZOMBIE) {
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list