Unify and cleanup FC ports scan.

This commit is contained in:
Alexander Motin 2015-11-17 16:33:46 +00:00
parent 4a38fe54fa
commit b6bd5f7fc1
3 changed files with 151 additions and 217 deletions

View File

@ -64,12 +64,6 @@ __FBSDID("$FreeBSD$");
* General defines
*/
#define MBOX_DELAY_COUNT 1000000 / 100
#define ISP_MARK_PORTDB(a, b, c) \
do { \
isp_prt(isp, ISP_LOG_SANCFG, \
"Chan %d ISP_MARK_PORTDB@LINE %d", (b), __LINE__); \
isp_mark_portdb((a), (b), (c)); \
} while (0)
/*
* Local static data
@ -132,7 +126,7 @@ static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *
static int isp_register_fc4_type(ispsoftc_t *, int);
static int isp_register_fc4_type_24xx(ispsoftc_t *, int);
static uint16_t isp_next_handle(ispsoftc_t *, uint16_t *);
static void isp_fw_state(ispsoftc_t *, int);
static int isp_fw_state(ispsoftc_t *, int);
static void isp_mboxcmd_qnw(ispsoftc_t *, mbreg_t *, int);
static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
@ -149,6 +143,19 @@ static void isp_parse_nvram_12160(ispsoftc_t *, int, uint8_t *);
static void isp_parse_nvram_2100(ispsoftc_t *, uint8_t *);
static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
static void
isp_change_fw_state(ispsoftc_t *isp, int chan, int state)
{
fcparam *fcp = FCPARAM(isp, chan);
if (fcp->isp_fwstate == state)
return;
isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG,
"Chan %d Firmware state <%s->%s>", chan,
isp_fc_fw_statename(fcp->isp_fwstate), isp_fc_fw_statename(state));
fcp->isp_fwstate = state;
}
/*
* Reset Hardware.
*
@ -1267,8 +1274,9 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
isp->isp_nchan = 1;
}
}
for (i = 0; i < isp->isp_nchan; i++) {
isp_fw_state(isp, i);
if (IS_FC(isp)) {
for (i = 0; i < isp->isp_nchan; i++)
isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
}
if (isp->isp_dead) {
isp_shutdown(isp);
@ -2577,7 +2585,10 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock)
pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x", chan, id, pdb->portid, un.bill.pdb_flags, un.bill.pdb_curstate);
isp_prt(isp, ISP_LOGDEBUG1,
"Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x",
chan, id, pdb->portid, un.bill.pdb_flags,
un.bill.pdb_curstate);
if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
mbs.param[0] = MBOX_NOT_LOGGED_IN;
if (dolock) {
@ -2592,6 +2603,8 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock)
pdb->portid = BITS2WORD(un.fred.pdb_portid_bits);
ISP_MEMCPY(pdb->portname, un.fred.pdb_portname, 8);
ISP_MEMCPY(pdb->nodename, un.fred.pdb_nodename, 8);
isp_prt(isp, ISP_LOGDEBUG1,
"Chan %d handle 0x%x Port 0x%06x", chan, id, pdb->portid);
}
if (dolock) {
FC_SCRATCH_RELEASE(isp, chan);
@ -2699,13 +2712,8 @@ static uint64_t
isp_get_wwn(ispsoftc_t *isp, int chan, int loopid, int nodename)
{
uint64_t wwn = INI_NONE;
fcparam *fcp = FCPARAM(isp, chan);
mbreg_t mbs;
if (fcp->isp_fwstate < FW_READY ||
fcp->isp_loopstate < LOOP_PDB_RCVD) {
return (wwn);
}
MBSINIT(&mbs, MBOX_GET_PORT_NAME,
MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
if (ISP_CAP_2KLOGIN(isp)) {
@ -2758,7 +2766,6 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
{
mbreg_t mbs;
int check_for_fabric, r;
uint8_t lwfs;
int loopid;
fcparam *fcp;
fcportdb_t *lp;
@ -2767,20 +2774,21 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
fcp = FCPARAM(isp, chan);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Link Test Entry", chan);
ISP_MARK_PORTDB(isp, chan, 1);
/* Mark port database entries for following scan. */
isp_mark_portdb(isp, chan, 1);
if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
return (0);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
fcp->isp_loopstate = LOOP_TESTING_LINK;
/*
* Wait up to N microseconds for F/W to go to a ready state.
*/
lwfs = FW_CONFIG_WAIT;
GET_NANOTIME(&hra);
while (1) {
isp_fw_state(isp, chan);
if (lwfs != fcp->isp_fwstate) {
isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG, "Chan %d Firmware State <%s->%s>", chan, isp_fc_fw_statename((int)lwfs), isp_fc_fw_statename((int)fcp->isp_fwstate));
lwfs = fcp->isp_fwstate;
}
isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
if (fcp->isp_fwstate == FW_READY) {
break;
}
@ -2860,7 +2868,7 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
}
if (alpa_map[i] && fcp->isp_loopid != i) {
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d deriving loopid %d from AL_PA map (AL_PA 0x%x) and ignoring returned value %d (AL_PA 0x%x)",
"Chan %d Deriving loopid %d from AL_PA map (AL_PA 0x%x) and ignoring returned value %d (AL_PA 0x%x)",
chan, i, alpa_map[i], fcp->isp_loopid, alpa);
fcp->isp_loopid = i;
}
@ -2953,11 +2961,12 @@ not_on_fabric:
}
}
fcp->isp_loopstate = LOOP_LTEST_DONE;
/*
* Announce ourselves, too.
*/
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, topology, chan, (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) fcp->isp_wwpn, fcp->isp_portid, fcp->isp_loopid, isp_fc_toponame(fcp));
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Link Test Complete", chan);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
return (0);
}
@ -2967,19 +2976,10 @@ not_on_fabric:
* At this point, we've scanned the local loop (if any) and the fabric
* and performed fabric logins on all new devices.
*
* Our task here is to go through our port database and remove any entities
* Our task here is to go through our port database removing any entities
* that are still marked probational (issuing PLOGO for ones which we had
* PLOGI'd into) or are dead.
*
* Our task here is to also check policy to decide whether devices which
* have *changed* in some way should still be kept active. For example,
* if a device has just changed PortID, we can either elect to treat it
* as an old device or as a newly arrived device (and notify the outer
* layer appropriately).
*
* We also do initiator map target id assignment here for new initiator
* devices and refresh old ones ot make sure that they point to the correct
* entities.
* PLOGI'd into) or are dead, and notifying upper layers about new/changed
* devices.
*/
static int
isp_pdb_sync(ispsoftc_t *isp, int chan)
@ -2988,44 +2988,14 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
fcportdb_t *lp;
uint16_t dbidx;
if (fcp->isp_loopstate == LOOP_READY) {
if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
return (-1);
}
if (fcp->isp_loopstate > LOOP_SYNCING_PDB) {
return (0);
}
/*
* Make sure we're okay for doing this right now.
*/
if (fcp->isp_loopstate != LOOP_PDB_RCVD &&
fcp->isp_loopstate != LOOP_FSCAN_DONE &&
fcp->isp_loopstate != LOOP_LSCAN_DONE) {
isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: bad loopstate %d",
fcp->isp_loopstate);
return (-1);
}
if (fcp->isp_topo == TOPO_FL_PORT ||
fcp->isp_topo == TOPO_NL_PORT ||
fcp->isp_topo == TOPO_N_PORT) {
if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
if (isp_scan_loop(isp, chan) != 0) {
isp_prt(isp, ISP_LOGWARN,
"isp_pdb_sync: isp_scan_loop failed");
return (-1);
}
}
}
if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
if (isp_scan_fabric(isp, chan) != 0) {
isp_prt(isp, ISP_LOGWARN,
"isp_pdb_sync: isp_scan_fabric failed");
return (-1);
}
}
}
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Synchronizing PDBs", chan);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
fcp->isp_loopstate = LOOP_SYNCING_PDB;
@ -3101,6 +3071,7 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
*/
fcp->loop_seen_once = 1;
fcp->isp_loopstate = LOOP_READY;
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
return (0);
}
@ -3117,36 +3088,34 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
uint16_t handles[LOCAL_LOOP_LIM];
uint16_t handle;
if (fcp->isp_fwstate < FW_READY ||
fcp->isp_loopstate < LOOP_PDB_RCVD) {
if (fcp->isp_loopstate < LOOP_LTEST_DONE) {
return (-1);
}
if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
return (0);
}
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
if (fcp->isp_topo != TOPO_NL_PORT && fcp->isp_topo != TOPO_FL_PORT &&
fcp->isp_topo != TOPO_N_PORT) {
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d no loop topology to scan", chan);
"Chan %d FC loop scan done (no loop)", chan);
fcp->isp_loopstate = LOOP_LSCAN_DONE;
return (0);
}
fcp->isp_loopstate = LOOP_SCANNING_LOOP;
lim = LOCAL_LOOP_LIM;
r = isp_gethandles(isp, chan, handles, &lim, 1, 1);
if (r != 0) {
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d getting list of handles failed with %x", chan, r);
"Chan %d Getting list of handles failed with %x", chan, r);
fail:
ISP_MARK_PORTDB(isp, chan, 1);
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d FC scan loop DONE (bad)", chan);
"Chan %d FC loop scan done (bad)", chan);
return (-1);
}
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop -- %d ports",
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
chan, lim);
/*
@ -3172,8 +3141,12 @@ fail:
*/
if (IS_2100(isp) || IS_2200(isp)) {
uint64_t node_wwn = isp_get_wwn(isp, chan, handle, 1);
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
goto fail;
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
abort:
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d FC loop scan done (abort)", chan);
return (-1);
}
if (node_wwn == INI_NONE) {
continue;
}
@ -3185,15 +3158,15 @@ fail:
r = isp_getpdb(isp, chan, handle, &pdb, 1);
if (r != 0) {
isp_prt(isp, ISP_LOGDEBUG1,
"Chan %d FC scan loop handle %d returned %x",
"Chan %d FC Scan Loop handle %d returned %x",
chan, handle, r);
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
goto fail;
goto abort;
continue;
}
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
goto fail;
goto abort;
/*
* On *very* old 2100 firmware we would end up sometimes
@ -3279,7 +3252,9 @@ fail:
lp->new_portid = tmp.portid;
lp->new_prli_word3 = tmp.prli_word3;
lp->state = FC_PORTDB_STATE_PENDING_VALID;
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Loop Port 0x%06x@0x%04x Pending Valid", chan, tmp.portid, tmp.handle);
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d Loop port 0x%06x@0x%04x now pending valid",
chan, tmp.portid, tmp.handle);
continue;
}
@ -3293,7 +3268,9 @@ fail:
* Claim that this has changed and let somebody else
* decide what to do.
*/
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Loop Port 0x%06x@0x%04x changed", chan, tmp.portid, tmp.handle);
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d Loop port 0x%06x@0x%04x changed",
chan, tmp.portid, tmp.handle);
lp->state = FC_PORTDB_STATE_CHANGED;
lp->new_portid = tmp.portid;
lp->new_prli_word3 = tmp.prli_word3;
@ -3324,10 +3301,14 @@ fail:
lp->handle = tmp.handle;
lp->port_wwn = tmp.port_wwn;
lp->node_wwn = tmp.node_wwn;
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Loop Port 0x%06x@0x%04x is New Entry", chan, tmp.portid, tmp.handle);
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d Loop port 0x%06x@0x%04x is a new entry",
chan, tmp.portid, tmp.handle);
}
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
goto abort;
fcp->isp_loopstate = LOOP_LSCAN_DONE;
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop DONE", chan);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
return (0);
}
@ -3513,28 +3494,33 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
int portidx, portlim, r;
sns_gid_ft_rsp_t *rs0, *rs1;
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Scan Fabric", chan);
if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_LSCAN_DONE) {
if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
return (-1);
}
if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) {
return (0);
}
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Scan Fabric Done (no fabric)", chan);
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d FC fabric scan done (no fabric)", chan);
return (0);
}
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
if (FC_SCRATCH_ACQUIRE(isp, chan)) {
isp_prt(isp, ISP_LOGERR, sacq);
ISP_MARK_PORTDB(isp, chan, 1);
fail:
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d FC fabric scan done (bad)", chan);
return (-1);
}
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
abort:
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d FC fabric scan done (abort)", chan);
return (-1);
}
@ -3551,10 +3537,9 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
isp_dump_chip_portdb(isp, chan, 0);
}
if (r) {
fcp->isp_loopstate = LOOP_PDB_RCVD;
fcp->isp_loopstate = LOOP_LTEST_DONE;
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
goto fail;
}
if (IS_24XX(isp)) {
@ -3564,9 +3549,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
}
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
goto abort;
}
if (r > 0) {
@ -3574,7 +3557,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
FC_SCRATCH_RELEASE(isp, chan);
return (0);
} else if (r < 0) {
fcp->isp_loopstate = LOOP_PDB_RCVD; /* try again */
fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
FC_SCRATCH_RELEASE(isp, chan);
return (0);
}
@ -3584,9 +3567,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF);
isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
goto abort;
}
if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) {
int level;
@ -3631,7 +3612,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
}
portlim = portidx + 1;
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d got %d ports back from name server", chan, portlim);
"Chan %d Got %d ports back from name server", chan, portlim);
for (portidx = 0; portidx < portlim; portidx++) {
int npidx;
@ -3686,35 +3667,19 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
if (portid == 0) {
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d skipping null PortID at idx %d",
"Chan %d Skipping null PortID at idx %d",
chan, portidx);
continue;
}
/*
* Skip ourselves here and on other channels. If we're
* multi-id, we can't check the portids in other FCPARAM
* arenas because the resolutions here aren't synchronized.
* The best way to do this is to exclude looking at portids
* that have the same domain and area code as our own
* portid.
*/
if (ISP_CAP_MULTI_ID(isp) && isp->isp_nchan > 1) {
if ((portid >> 8) == (fcp->isp_portid >> 8)) {
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d skip PortID 0x%06x",
chan, portid);
continue;
}
} else if (portid == fcp->isp_portid) {
if (portid == fcp->isp_portid) {
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d skip ourselves on @ PortID 0x%06x",
chan, portid);
"Chan %d Skipping our PortID 0x%06x", chan, portid);
continue;
}
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d Checking Fabric Port 0x%06x", chan, portid);
"Chan %d Checking fabric port 0x%06x", chan, portid);
/*
* We now search our Port Database for any
@ -3759,10 +3724,8 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
*/
r = isp_getpdb(isp, chan, lp->handle, &pdb, 0);
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
goto abort;
}
if (r != 0) {
lp->new_portid = portid;
@ -3806,19 +3769,14 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
&FCPARAM(isp, 0)->isp_lasthdl)) {
lp->new_portid = portid;
lp->state = FC_PORTDB_STATE_DEAD;
if (fcp->isp_loopstate !=
if (fcp->isp_loopstate <
LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
goto abort;
}
continue;
}
if (fcp->isp_loopstate !=
LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
goto abort;
}
MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
@ -3852,10 +3810,14 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
lp->new_portid = portid;
lp->new_prli_word3 = nr;
if (pdb.portid != lp->portid || nr != lp->prli_word3 || handle_changed) {
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric Port 0x%06x changed", chan, portid);
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d Fabric port 0x%06x changed",
chan, portid);
lp->state = FC_PORTDB_STATE_CHANGED;
} else {
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric Port 0x%06x Now Pending Valid", chan, portid);
isp_prt(isp, ISP_LOG_SANCFG,
"Chan %d Fabric port 0x%06x now pending valid",
chan, portid);
lp->state = FC_PORTDB_STATE_PENDING_VALID;
}
continue;
@ -3922,17 +3884,13 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
*/
if (isp_login_device(isp, chan, portid, &pdb,
&FCPARAM(isp, 0)->isp_lasthdl)) {
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
goto abort;
}
continue;
}
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
FC_SCRATCH_RELEASE(isp, chan);
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
goto abort;
}
handle = pdb.handle;
@ -3964,7 +3922,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
lp->new_portid = portid;
lp->new_prli_word3 = nr;
lp->state = FC_PORTDB_STATE_NEW;
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric Port 0x%06x is a New Entry", chan, portid);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric port 0x%06x is a new entry", chan, portid);
continue;
}
@ -3993,21 +3951,20 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
lp->new_portid = portid;
lp->new_prli_word3 = nr;
if (lp->portid != portid || lp->prli_word3 != nr) {
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie Fabric Port 0x%06x Now Changed", chan, portid);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie fabric port 0x%06x now changed", chan, portid);
lp->state = FC_PORTDB_STATE_CHANGED;
} else {
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie Fabric Port 0x%06x Now Pending Valid", chan, portid);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie fabric port 0x%06x now pending valid", chan, portid);
lp->state = FC_PORTDB_STATE_PENDING_VALID;
}
}
FC_SCRATCH_RELEASE(isp, chan);
if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
ISP_MARK_PORTDB(isp, chan, 1);
return (-1);
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
goto abort;
}
FC_SCRATCH_RELEASE(isp, chan);
fcp->isp_loopstate = LOOP_FSCAN_DONE;
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Scan Fabric Done", chan);
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
return (0);
}
@ -4359,7 +4316,7 @@ isp_start(XS_T *xs)
/*
* Try again later.
*/
if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) {
if (fcp->isp_loopstate != LOOP_READY) {
return (CMD_RQLATER);
}
@ -5850,7 +5807,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
isp->isp_dead = 1;
isp->isp_state = ISP_CRASHED;
FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
FCPARAM(isp, chan)->isp_fwstate = FW_CONFIG_WAIT;
isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
/*
* Were we waiting for a mailbox command to complete?
* If so, it's dead, so wake up the waiter.
@ -5923,10 +5880,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
continue;
}
fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_LIP_RCVD;
fcp->isp_loopstate = LOOP_NIL;
ISP_SET_SENDMARKER(isp, chan, 1);
ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_LIP, chan);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, chan, mbox)) {
@ -5982,10 +5937,6 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
}
ISP_SET_SENDMARKER(isp, chan, 1);
fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_LIP_RCVD;
ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_LOOP_UP, chan);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, chan, mbox)) {
@ -6008,10 +5959,9 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
}
ISP_SET_SENDMARKER(isp, chan, 1);
fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_NIL;
ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, chan, mbox)) {
acked = 1;
@ -6033,9 +5983,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
}
ISP_SET_SENDMARKER(isp, chan, 1);
fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_NIL;
ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_LOOP_RESET, chan);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, chan, mbox)) {
@ -6067,9 +6015,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
if (fcp->role == ISP_ROLE_NONE) {
continue;
}
ISP_SET_SENDMARKER(isp, chan, 1);
fcp->isp_loopstate = LOOP_PDB_RCVD;
ISP_MARK_PORTDB(isp, chan, 1);
if (fcp->isp_loopstate > LOOP_LTEST_DONE)
fcp->isp_loopstate = LOOP_LTEST_DONE;
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
}
break;
@ -6093,12 +6040,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
continue;
}
if (fcp->isp_topo == TOPO_F_PORT) {
if (fcp->isp_loopstate > LOOP_LSCAN_DONE)
fcp->isp_loopstate = LOOP_LSCAN_DONE;
} else {
fcp->isp_loopstate = LOOP_PDB_RCVD;
}
ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_SNS);
}
break;
@ -6114,7 +6057,6 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
}
chan = 0;
mbox = ISP_READ(isp, OUTMAILBOX1);
ISP_MARK_PORTDB(isp, chan, 1);
switch (mbox) {
case ISP_CONN_LOOP:
isp_prt(isp, ISP_LOGINFO,
@ -6143,10 +6085,9 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
"Unknown connection mode (0x%x)", mbox);
break;
}
ISP_SET_SENDMARKER(isp, chan, 1);
FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_OTHER);
FCPARAM(isp, chan)->sendmarker = 1;
FCPARAM(isp, chan)->isp_fwstate = FW_CONFIG_WAIT;
FCPARAM(isp, chan)->isp_loopstate = LOOP_LIP_RCVD;
break;
case ASYNC_RCV_ERR:
@ -7557,19 +7498,19 @@ out:
}
}
static void
static int
isp_fw_state(ispsoftc_t *isp, int chan)
{
if (IS_FC(isp)) {
mbreg_t mbs;
fcparam *fcp = FCPARAM(isp, chan);
MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
fcp->isp_fwstate = mbs.param[1];
return (mbs.param[1]);
}
}
return (FW_ERROR);
}
static void
@ -7939,7 +7880,7 @@ isp_reinit(ispsoftc_t *isp, int do_load_defaults)
isp_clear_commands(isp);
if (IS_FC(isp)) {
for (i = 0; i < isp->isp_nchan; i++)
ISP_MARK_PORTDB(isp, i, -1);
isp_mark_portdb(isp, i, -1);
}
return (res);
}

View File

@ -400,31 +400,24 @@ isp_fc_runstate(ispsoftc_t *isp, int chan, int tval)
if (fcp->role == ISP_ROLE_NONE) {
return (0);
}
if (fcp->isp_fwstate < FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
if (isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval) != 0) {
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: linktest failed for channel %d", chan);
return (-1);
}
if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: f/w not ready for channel %d", chan);
return (-1);
}
if (isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval) != 0) {
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: linktest failed for channel %d", chan);
return (-1);
}
if (isp_control(isp, ISPCTL_SCAN_LOOP, chan) != 0) {
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan loop fails on channel %d", chan);
return (LOOP_PDB_RCVD);
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan loop failed on channel %d", chan);
return (LOOP_LTEST_DONE);
}
if (isp_control(isp, ISPCTL_SCAN_FABRIC, chan) != 0) {
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan fabric fails on channel %d", chan);
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan fabric failed on channel %d", chan);
return (LOOP_LSCAN_DONE);
}
if (isp_control(isp, ISPCTL_PDB_SYNC, chan) != 0) {
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: pdb_sync fails on channel %d", chan);
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: pdb_sync failed on channel %d", chan);
return (LOOP_FSCAN_DONE);
}
if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) {
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: f/w not ready again on channel %d", chan);
if (fcp->isp_loopstate != LOOP_READY) {
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: not ready again on channel %d", chan);
return (-1);
}
return (0);
@ -536,7 +529,7 @@ isp_fc_fw_statename(int state)
{
switch (state) {
case FW_CONFIG_WAIT: return "Config Wait";
case FW_WAIT_AL_PA: return "Waiting for AL_PA";
case FW_WAIT_LINK: return "Wait Link";
case FW_WAIT_LOGIN: return "Wait Login";
case FW_READY: return "Ready";
case FW_LOSS_OF_SYNC: return "Loss Of Sync";
@ -552,9 +545,9 @@ isp_fc_loop_statename(int state)
{
switch (state) {
case LOOP_NIL: return "NIL";
case LOOP_LIP_RCVD: return "LIP Received";
case LOOP_PDB_RCVD: return "PDB Received";
case LOOP_SCANNING_LOOP: return "Scanning";
case LOOP_TESTING_LINK: return "Testing Link";
case LOOP_LTEST_DONE: return "Link Test Done";
case LOOP_SCANNING_LOOP: return "Scanning Loop";
case LOOP_LSCAN_DONE: return "Loop Scan Done";
case LOOP_SCANNING_FABRIC: return "Scanning Fabric";
case LOOP_FSCAN_DONE: return "Fabric Scan Done";
@ -568,7 +561,7 @@ const char *
isp_fc_toponame(fcparam *fcp)
{
if (fcp->isp_fwstate != FW_READY) {
if (fcp->isp_loopstate < LOOP_LTEST_DONE) {
return "Unavailable";
}
switch (fcp->isp_topo) {
@ -2527,7 +2520,8 @@ isp_find_chan_by_did(ispsoftc_t *isp, uint32_t did, uint16_t *cp)
*cp = ISP_NOCHAN;
for (chan = 0; chan < isp->isp_nchan; chan++) {
fcparam *fcp = FCPARAM(isp, chan);
if ((fcp->role & ISP_ROLE_TARGET) == 0 || fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
if ((fcp->role & ISP_ROLE_TARGET) == 0 ||
fcp->isp_loopstate < LOOP_LTEST_DONE) {
continue;
}
if (fcp->isp_portid == did) {

View File

@ -482,7 +482,7 @@ typedef struct {
} fcparam;
#define FW_CONFIG_WAIT 0
#define FW_WAIT_AL_PA 1
#define FW_WAIT_LINK 1
#define FW_WAIT_LOGIN 2
#define FW_READY 3
#define FW_LOSS_OF_SYNC 4
@ -491,8 +491,8 @@ typedef struct {
#define FW_NON_PART 7
#define LOOP_NIL 0
#define LOOP_LIP_RCVD 1
#define LOOP_PDB_RCVD 2
#define LOOP_TESTING_LINK 1
#define LOOP_LTEST_DONE 2
#define LOOP_SCANNING_LOOP 3
#define LOOP_LSCAN_DONE 4
#define LOOP_SCANNING_FABRIC 5
@ -861,10 +861,10 @@ void isp_done(XS_T *);
* Update any operating parameters (speed, etc.)
* ... ISPCTL_FCLINK_TEST, int channel);
* Test FC link status on this channel
* ... ISPCTL_SCAN_FABRIC, int channel);
* Scan fabric on this channel
* ... ISPCTL_SCAN_LOOP, int channel);
* Scan local loop on this channel
* ... ISPCTL_SCAN_FABRIC, int channel);
* Scan fabric on this channel
* ... ISPCTL_PDB_SYNC, int channel);
* Synchronize port database on this channel
* ... ISPCTL_SEND_LIP, int channel);
@ -881,12 +881,11 @@ void isp_done(XS_T *);
* Change role of specified channel
*
* ISPCTL_PDB_SYNC is somewhat misnamed. It actually is the final step, in
* order, of ISPCTL_FCLINK_TEST, ISPCTL_SCAN_FABRIC, and ISPCTL_SCAN_LOOP.
* order, of ISPCTL_FCLINK_TEST, ISPCTL_SCAN_LOOP, and ISPCTL_SCAN_FABRIC.
* The main purpose of ISPCTL_PDB_SYNC is to complete management of logging
* and logging out of fabric devices (if one is on a fabric) and then marking
* the 'loop state' as being ready to now be used for sending commands to
* devices. Originally fabric name server and local loop scanning were
* part of this function. It's now been separated to allow for finer control.
* devices.
*/
typedef enum {
ISPCTL_RESET_BUS,