diff options
-rw-r--r-- | sys/dev/isp/isp.c | 76 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 2 | ||||
-rw-r--r-- | sys/dev/isp/isp_library.c | 10 | ||||
-rw-r--r-- | sys/dev/isp/ispvar.h | 1 |
4 files changed, 70 insertions, 19 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 8f8d6ae..27544cd 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -2320,7 +2320,8 @@ isp_mark_portdb(ispsoftc_t *isp, int chan) lp = &fcp->portdb[i]; if (lp->state == FC_PORTDB_STATE_NIL) continue; - if ((lp->portid & 0xfffc00) == 0xfffc00) + if (lp->portid >= DOMAIN_CONTROLLER_BASE && + lp->portid <= DOMAIN_CONTROLLER_END) continue; fcp->portdb[i].probational = 1; } @@ -2787,9 +2788,6 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay) fcp = FCPARAM(isp, chan); - /* Mark port database entries probational for following scan. */ - isp_mark_portdb(isp, chan); - if (fcp->isp_loopstate >= LOOP_LTEST_DONE) return (0); @@ -3079,6 +3077,48 @@ isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb) } /* + * Fix port IDs for logged-in initiators on pre-2400 chips. + * For those chips we are not receiving login events, adding initiators + * based on ATIO requests, but there is no port ID in that structure. + */ +static void +isp_fix_portids(ispsoftc_t *isp, int chan) +{ + fcparam *fcp = FCPARAM(isp, chan); + isp_pdb_t pdb; + uint64_t wwpn; + int i, r; + + for (i = 0; i < MAX_FC_TARG; i++) { + fcportdb_t *lp = &fcp->portdb[i]; + + if (lp->state == FC_PORTDB_STATE_NIL || + lp->state == FC_PORTDB_STATE_ZOMBIE) + continue; + if (VALID_PORT(lp->portid)) + continue; + + r = isp_getpdb(isp, chan, lp->handle, &pdb, 1); + if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) + return; + if (r != 0) { + isp_prt(isp, ISP_LOGDEBUG1, + "Chan %d FC Scan Loop handle %d returned %x", + chan, lp->handle, r); + continue; + } + + MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname); + if (lp->port_wwn != wwpn) + continue; + lp->portid = lp->new_portid = pdb.portid; + isp_prt(isp, ISP_LOG_SANCFG, + "Chan %d Port 0x%06x@0x%04x is fixed", + chan, pdb.portid, pdb.handle); + } +} + +/* * Scan local loop for devices. */ static int @@ -3097,13 +3137,18 @@ isp_scan_loop(ispsoftc_t *isp, int chan) return (0); } isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan); + fcp->isp_loopstate = LOOP_SCANNING_LOOP; if (TOPO_IS_FABRIC(fcp->isp_topo)) { + if (!IS_24XX(isp)) { + isp_fix_portids(isp, chan); + if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) + goto abort; + } isp_prt(isp, ISP_LOG_SANCFG, "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); @@ -3121,6 +3166,7 @@ isp_scan_loop(ispsoftc_t *isp, int chan) /* * Run through the list and get the port database info for each one. */ + isp_mark_portdb(isp, chan); for (idx = 0; idx < lim; idx++) { handle = handles[idx]; @@ -3162,8 +3208,6 @@ abort: isp_prt(isp, ISP_LOGDEBUG1, "Chan %d FC Scan Loop handle %d returned %x", chan, handle, r); - if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) - goto abort; continue; } @@ -3363,13 +3407,13 @@ isp_scan_fabric(ispsoftc_t *isp, int chan) return (0); } isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan); + fcp->isp_loopstate = LOOP_SCANNING_FABRIC; if (!TOPO_IS_FABRIC(fcp->isp_topo)) { fcp->isp_loopstate = LOOP_FSCAN_DONE; 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); @@ -3493,7 +3537,7 @@ abort: * than one entry that has the same PortID or the same * WWNN/WWPN duple, we enter the device into our database. */ - + isp_mark_portdb(isp, chan); for (portidx = 0; portidx < portlim; portidx++) { portid = ((rs1->snscb_ports[portidx].portid[0]) << 16) | ((rs1->snscb_ports[portidx].portid[1]) << 8) | @@ -3502,13 +3546,13 @@ abort: "Chan %d Checking fabric port 0x%06x", chan, portid); if (portid == 0) { isp_prt(isp, ISP_LOG_SANCFG, - "Chan %d Skipping null PortID at idx %d", + "Chan %d Port at idx %d is zero", chan, portidx); continue; } if (portid == fcp->isp_portid) { isp_prt(isp, ISP_LOG_SANCFG, - "Chan %d Skipping our PortID 0x%06x", chan, portid); + "Chan %d Port 0x%06x is our", chan, portid); continue; } @@ -3555,8 +3599,11 @@ abort: } relogin: - if ((fcp->role & ISP_ROLE_INITIATOR) == 0) + if ((fcp->role & ISP_ROLE_INITIATOR) == 0) { + isp_prt(isp, ISP_LOG_SANCFG, + "Chan %d Port 0x%06x is not logged in", chan, portid); continue; + } if (isp_login_device(isp, chan, portid, &pdb, &FCPARAM(isp, 0)->isp_lasthdl)) { @@ -5850,11 +5897,14 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt if (fcp->role == ISP_ROLE_NONE) continue; c = (chan == 0) ? 127 : (chan - 1); - if (rid.ridacq_map[c / 16] & (1 << (c % 16))) + if (rid.ridacq_map[c / 16] & (1 << (c % 16))) { + fcp->isp_loopstate = LOOP_NIL; isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_OTHER); + } } } else { + FCPARAM(isp, rid.ridacq_vp_index)->isp_loopstate = LOOP_NIL; isp_async(isp, ISPASYNC_CHANGE_NOTIFY, rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER); } diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index bb297e5..f7efbed 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -2342,7 +2342,7 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep) atp->bytes_xfered = 0; atp->lun = aep->at_lun; atp->nphdl = aep->at_iid; - atp->portid = PORT_NONE; + atp->portid = PORT_ANY; atp->oxid = 0; atp->cdb0 = atiop->cdb_io.cdb_bytes[0]; atp->tattr = aep->at_tag_type; diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index eccc781..80ed53f 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -2580,12 +2580,12 @@ isp_add_wwn_entry(ispsoftc_t *isp, int chan, uint64_t wwpn, uint64_t wwnn, * so log them verbosely and dump the whole port database. */ if ((VALID_INI(wwpn) && isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) || - (s_id != PORT_NONE && isp_find_pdb_by_portid(isp, chan, s_id, &lp))) { + (VALID_PORT(s_id) && isp_find_pdb_by_portid(isp, chan, s_id, &lp))) { change = 0; lp->new_portid = lp->portid; lp->new_prli_word3 = lp->prli_word3; - if (s_id != PORT_NONE && lp->portid != s_id) { - if (lp->portid == PORT_NONE) { + if (VALID_PORT(s_id) && lp->portid != s_id) { + if (!VALID_PORT(lp->portid)) { isp_prt(isp, ISP_LOGTINFO, "Chan %d WWPN 0x%016llx handle 0x%x " "gets PortID 0x%06x", @@ -2804,13 +2804,13 @@ isp_del_wwn_entries(ispsoftc_t *isp, isp_notify_t *mp) return; } } - if (mp->nt_wwn != INI_ANY) { + if (VALID_INI(mp->nt_wwn)) { if (isp_find_pdb_by_wwpn(isp, mp->nt_channel, mp->nt_wwn, &lp)) { isp_del_wwn_entry(isp, mp->nt_channel, lp->port_wwn, lp->handle, lp->portid); return; } } - if (mp->nt_sid != PORT_ANY && mp->nt_sid != PORT_NONE) { + if (VALID_PORT(mp->nt_sid)) { if (isp_find_pdb_by_portid(isp, mp->nt_channel, mp->nt_sid, &lp)) { isp_del_wwn_entry(isp, mp->nt_channel, lp->port_wwn, lp->handle, lp->portid); return; diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index 0e3df75..e4e5a08 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -282,6 +282,7 @@ typedef struct { #define FABRIC_PORT_ID 0xFFFFFE #define PORT_ANY 0xFFFFFF #define PORT_NONE 0 +#define VALID_PORT(port) (port != PORT_NONE && port != PORT_ANY) #define DOMAIN_CONTROLLER_BASE 0xFFFC00 #define DOMAIN_CONTROLLER_END 0xFFFCFF |