summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp/isp_library.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-05 08:31:48 +0000
committermav <mav@FreeBSD.org>2015-10-05 08:31:48 +0000
commitec7deb53d18cdb5720ef959156dcf8fcff0247f9 (patch)
treecef4ce32df3befdd43da3ea6ae0fded0a69f468d /sys/dev/isp/isp_library.c
parent9b07ecd0998dda43886587a22afa4d7bb60c8ffd (diff)
downloadFreeBSD-src-ec7deb53d18cdb5720ef959156dcf8fcff0247f9.zip
FreeBSD-src-ec7deb53d18cdb5720ef959156dcf8fcff0247f9.tar.gz
MFC r285459: Unify port database use for target and initiator roles.
Aside from cleaner and more consistent code, this allows ports to be both target and initiator same time, and easily switch from any role to any.
Diffstat (limited to 'sys/dev/isp/isp_library.c')
-rw-r--r--sys/dev/isp/isp_library.c270
1 files changed, 106 insertions, 164 deletions
diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c
index 2f7dc4e..f7ee7bb 100644
--- a/sys/dev/isp/isp_library.c
+++ b/sys/dev/isp/isp_library.c
@@ -411,10 +411,6 @@ isp_fc_runstate(ispsoftc_t *isp, int chan, int tval)
}
}
- if ((fcp->role & ISP_ROLE_INITIATOR) == 0) {
- return (0);
- }
-
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);
@@ -444,7 +440,7 @@ isp_dump_portdb(ispsoftc_t *isp, int chan)
int i;
for (i = 0; i < MAX_FC_TARG; i++) {
- char mb[4], buf1[64], buf2[64];
+ char buf1[64], buf2[64];
const char *dbs[8] = {
"NIL ",
"PROB",
@@ -457,18 +453,13 @@ isp_dump_portdb(ispsoftc_t *isp, int chan)
};
fcportdb_t *lp = &fcp->portdb[i];
- if (lp->state == FC_PORTDB_STATE_NIL && lp->target_mode == 0) {
+ if (lp->state == FC_PORTDB_STATE_NIL) {
continue;
}
- if (lp->dev_map_idx) {
- ISP_SNPRINTF(mb, sizeof (mb), "%3d", ((int) lp->dev_map_idx) - 1);
- } else {
- ISP_SNPRINTF(mb, sizeof (mb), "---");
- }
isp_gen_role_str(buf1, sizeof (buf1), lp->prli_word3);
isp_gen_role_str(buf2, sizeof (buf2), lp->new_prli_word3);
- isp_prt(isp, ISP_LOGALL, "Chan %d [%d]: hdl 0x%x %s al%d tgt %s %s 0x%06x =>%s 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x",
- chan, i, lp->handle, dbs[lp->state], lp->autologin, mb, buf1, lp->portid, buf2, lp->new_portid,
+ isp_prt(isp, ISP_LOGALL, "Chan %d [%d]: hdl 0x%x %s al%d %s 0x%06x =>%s 0x%06x; WWNN 0x%08x%08x WWPN 0x%08x%08x",
+ chan, i, lp->handle, dbs[lp->state], lp->autologin, buf1, lp->portid, buf2, lp->new_portid,
(uint32_t) (lp->node_wwn >> 32), (uint32_t) (lp->node_wwn), (uint32_t) (lp->port_wwn >> 32), (uint32_t) (lp->port_wwn));
}
}
@@ -603,20 +594,8 @@ isp_fc_change_role(ispsoftc_t *isp, int chan, int new_role)
return (ENXIO);
}
if (chan == 0) {
- isp_clear_commands(isp);
- isp_reset(isp, 0);
- if (isp->isp_state != ISP_RESETSTATE) {
- isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__);
- return (EIO);
- }
fcp->role = new_role;
- isp_init(isp);
- if (isp->isp_state != ISP_INITSTATE) {
- isp_prt(isp, ISP_LOGERR, "%s: cannot init card", __func__);
- return (EIO);
- }
- isp->isp_state = ISP_RUNSTATE;
- return (0);
+ return (isp_reinit(isp, 0));
} else if (ISP_CAP_MULTI_ID(isp)) {
mbreg_t mbs;
vp_modify_t *vp;
@@ -2347,8 +2326,10 @@ isp_destroy_tgt_handle(ispsoftc_t *isp, uint32_t handle)
}
}
+#endif
+
/*
- * Find target mode entries
+ * Find port database entries
*/
int
isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr)
@@ -2359,10 +2340,10 @@ isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr)
if (chan >= isp->isp_nchan)
return (0);
fcp = FCPARAM(isp, chan);
- for (i = MAX_FC_TARG - 1; i >= 0; i--) {
+ for (i = 0; i < MAX_FC_TARG; i++) {
fcportdb_t *lp = &fcp->portdb[i];
- if (lp->target_mode == 0)
+ if (lp->state == FC_PORTDB_STATE_NIL)
continue;
if (lp->port_wwn == wwn) {
*lptr = lp;
@@ -2372,8 +2353,10 @@ isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr)
return (0);
}
+#ifdef ISP_TARGET_MODE
+
int
-isp_find_pdb_by_loopid(ispsoftc_t *isp, int chan, uint32_t loopid, fcportdb_t **lptr)
+isp_find_pdb_by_handle(ispsoftc_t *isp, int chan, uint32_t handle, fcportdb_t **lptr)
{
fcparam *fcp;
int i;
@@ -2381,9 +2364,15 @@ isp_find_pdb_by_loopid(ispsoftc_t *isp, int chan, uint32_t loopid, fcportdb_t **
if (chan >= isp->isp_nchan)
return (0);
fcp = FCPARAM(isp, chan);
- if ((i = fcp->isp_tgt_map[loopid]) > 0) {
- *lptr = &fcp->portdb[i - 1];
- return (1);
+ for (i = 0; i < MAX_FC_TARG; i++) {
+ fcportdb_t *lp = &fcp->portdb[i];
+
+ if (lp->state == FC_PORTDB_STATE_NIL)
+ continue;
+ if (lp->handle == handle) {
+ *lptr = lp;
+ return (1);
+ }
}
return (0);
}
@@ -2397,10 +2386,10 @@ isp_find_pdb_by_sid(ispsoftc_t *isp, int chan, uint32_t sid, fcportdb_t **lptr)
if (chan >= isp->isp_nchan)
return (0);
fcp = FCPARAM(isp, chan);
- for (i = MAX_FC_TARG - 1; i >= 0; i--) {
+ for (i = 0; i < MAX_FC_TARG; i++) {
fcportdb_t *lp = &fcp->portdb[i];
- if (lp->target_mode == 0)
+ if (lp->state == FC_PORTDB_STATE_NIL)
continue;
if (lp->portid == sid) {
*lptr = lp;
@@ -2437,14 +2426,13 @@ isp_add_wwn_entry(ispsoftc_t *isp, int chan, uint64_t ini, uint16_t nphdl, uint3
char buf[64];
fcparam *fcp;
fcportdb_t *lp;
- isp_notify_t nt;
- int i, something, take, taken;
+ int i, change;
fcp = FCPARAM(isp, chan);
if (nphdl >= MAX_NPORT_HANDLE) {
- isp_prt(isp, ISP_LOGWARN, "Chan %d IID 0x%016llx "
- "N-Port handle 0x%04x Port ID 0x%06x -- bad handle",
- chan, (unsigned long long) ini, nphdl, s_id);
+ isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN, "Chan %d WWPN 0x%016llx "
+ "PortID 0x%06x handle 0x%x -- bad handle",
+ chan, (unsigned long long) ini, s_id, nphdl);
return;
}
@@ -2453,146 +2441,118 @@ isp_add_wwn_entry(ispsoftc_t *isp, int chan, uint64_t ini, uint16_t nphdl, uint3
* with new parameters. Some cases of update can be suspicious,
* so log them verbosely and dump the whole port database.
*/
- if ((i = fcp->isp_tgt_map[nphdl]) > 0) {
- take = taken = i - 1;
- lp = &fcp->portdb[taken];
- something = 0;
+ if ((VALID_INI(ini) && isp_find_pdb_by_wwn(isp, chan, ini, &lp)) ||
+ (s_id != PORT_NONE && isp_find_pdb_by_sid(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) {
isp_prt(isp, ISP_LOGTINFO,
- "Chan %d IID 0x%016llx N-port handle 0x%04x "
- "gets Port ID 0x%06x",
+ "Chan %d WWPN 0x%016llx handle 0x%x "
+ "gets PortID 0x%06x",
chan, (unsigned long long) lp->port_wwn,
nphdl, s_id);
} else {
isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN,
- "Chan %d IID 0x%016llx N-port handle 0x%04x "
- "changes Port ID 0x%06x to 0x%06x",
+ "Chan %d WWPN 0x%016llx handle 0x%x "
+ "changes PortID 0x%06x to 0x%06x",
chan, (unsigned long long) lp->port_wwn,
nphdl, lp->portid, s_id);
if (isp->isp_dblev & (ISP_LOGTINFO|ISP_LOGWARN))
isp_dump_portdb(isp, chan);
}
- lp->portid = s_id;
- something++;
+ lp->new_portid = s_id;
+ change++;
}
if (VALID_INI(ini) && lp->port_wwn != ini) {
if (!VALID_INI(lp->port_wwn)) {
isp_prt(isp, ISP_LOGTINFO,
- "Chan %d N-port handle 0x%04x Port ID "
- "0x%06x gets WWN 0x%016llxx",
- chan, nphdl, lp->portid,
+ "Chan %d PortID 0x%06x handle 0x%x "
+ "gets WWN 0x%016llxx",
+ chan, lp->portid, nphdl,
(unsigned long long) ini);
} else if (lp->port_wwn != ini) {
isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN,
- "Chan %d N-port handle 0x%04x Port ID "
- "0x%06x changes WWN 0x%016llx to 0x%016llx",
- chan, nphdl, lp->portid,
+ "Chan %d PortID 0x%06x handle 0x%x "
+ "changes WWN 0x%016llx to 0x%016llx",
+ chan, lp->portid, nphdl,
(unsigned long long) lp->port_wwn,
(unsigned long long) ini);
if (isp->isp_dblev & (ISP_LOGTINFO|ISP_LOGWARN))
isp_dump_portdb(isp, chan);
}
lp->port_wwn = ini;
- something++;
+ change++;
}
- if (lp->prli_word3 != prli_params) {
- lp->prli_word3 = prli_params;
- isp_gen_role_str(buf, sizeof (buf), lp->prli_word3);
+ if (prli_params != 0 && lp->prli_word3 != prli_params) {
+ isp_gen_role_str(buf, sizeof (buf), prli_params);
isp_prt(isp, ISP_LOGTINFO|ISP_LOGCONFIG,
- "Chan %d IID 0x%016llx N-Port Handle 0x%04x "
- "Port ID 0x%06x changes PRLI Word 3 %s",
+ "Chan %d WWPN 0x%016llx PortID 0x%06x "
+ "handle 0x%x changes PRLI Word 3 %s",
chan, (unsigned long long) lp->port_wwn,
- lp->handle, lp->portid, buf);
- something++;
+ lp->portid, lp->handle, buf);
+ lp->new_prli_word3 = prli_params;
+ change++;
}
- if (!something) {
- isp_prt(isp, ISP_LOGTINFO,
- "Chan %d IID 0x%016llx N-Port Handle 0x%04x "
- "Port ID 0x%06x reentered",
+ if (lp->handle != nphdl) {
+ isp_prt(isp, ISP_LOGTINFO|ISP_LOGCONFIG,
+ "Chan %d WWPN 0x%016llx PortID 0x%06x "
+ "changes handle 0x%x to 0x%x",
chan, (unsigned long long) lp->port_wwn,
- lp->handle, lp->portid);
- }
- } else
- take = taken = -1;
-
- /*
- * Search for records colliding on handler, Port ID or WWN.
- * Remove any found collisions, logging suspicious cases of
- * still valid records.
- */
- for (i = 0; i < MAX_FC_TARG; i++) {
- lp = &fcp->portdb[i];
- if (lp->target_mode == 0 || i == take)
- continue;
- if (lp->handle != nphdl && lp->portid != s_id &&
- lp->port_wwn != ini)
- continue;
- if (lp->state == FC_PORTDB_STATE_VALID) {
- isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN,
- "Chan %d IID 0x%016llx N-Port Handle 0x%04x "
- "Port ID 0x%06x is conflicting",
+ lp->portid, lp->handle, nphdl);
+ lp->handle = nphdl;
+ change++;
+ }
+ lp->state = FC_PORTDB_STATE_VALID;
+ if (change) {
+ isp_async(isp, ISPASYNC_DEV_CHANGED, chan, lp);
+ lp->portid = lp->new_portid;
+ lp->prli_word3 = lp->new_prli_word3;
+ lp->new_prli_word3 = 0;
+ lp->new_portid = 0;
+ } else {
+ isp_prt(isp, ISP_LOGTINFO,
+ "Chan %d WWPN 0x%016llx PortID 0x%06x "
+ "handle 0x%x reentered",
chan, (unsigned long long) lp->port_wwn,
- lp->handle, lp->portid);
- if (isp->isp_dblev & (ISP_LOGTINFO|ISP_LOGWARN))
- isp_dump_portdb(isp, chan);
- isp_del_wwn_entry(isp, chan,
- lp->port_wwn, lp->handle, lp->portid);
+ lp->portid, lp->handle);
+ isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
}
- ISP_MEMZERO(lp, sizeof (fcportdb_t));
- take = i;
- }
-
- /* If valid record already exists -- we are done. */
- if (taken >= 0)
return;
+ }
/* Search for room to insert new record. */
- if (take < 0) {
- for (i = MAX_FC_TARG - 1; i >= 0; i--) {
- if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) {
- take = i;
- break;
- }
- }
+ for (i = 0; i < MAX_FC_TARG; i++) {
+ if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL)
+ break;
}
- if (take < 0) {
+ if (i >= MAX_FC_TARG) {
isp_prt(isp, ISP_LOGTINFO|ISP_LOGWARN,
- "Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x "
+ "Chan %d WWPN 0x%016llx PortID 0x%06x handle 0x%x "
"-- no room in port database",
- chan, (unsigned long long) ini, nphdl, s_id);
+ chan, (unsigned long long) ini, s_id, nphdl);
if (isp->isp_dblev & (ISP_LOGTINFO|ISP_LOGWARN))
isp_dump_portdb(isp, chan);
return;
}
/* Insert new record and mark it valid. */
- lp = &fcp->portdb[take];
+ lp = &fcp->portdb[i];
ISP_MEMZERO(lp, sizeof (fcportdb_t));
- lp->target_mode = 1;
lp->handle = nphdl;
lp->portid = s_id;
lp->port_wwn = ini;
- lp->prli_word3 = prli_params;
+ lp->prli_word3 = (prli_params != 0) ? prli_params : PRLI_WD3_INITIATOR_FUNCTION;
lp->state = FC_PORTDB_STATE_VALID;
- fcp->isp_tgt_map[nphdl] = take + 1;
isp_gen_role_str(buf, sizeof (buf), lp->prli_word3);
- isp_prt(isp, ISP_LOGTINFO, "Chan %d IID 0x%016llx N-Port Handle 0x%04x"
- " Port ID 0x%06x vtgt %d %s added", chan,
- (unsigned long long) ini, nphdl, s_id, take, buf);
-
- /* Notify above levels about new initiator arrival. */
- ISP_MEMZERO(&nt, sizeof (nt));
- nt.nt_hba = isp;
- nt.nt_wwn = ini;
- nt.nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
- nt.nt_sid = s_id;
- nt.nt_did = FCPARAM(isp, chan)->isp_portid;
- nt.nt_nphdl = nphdl;
- nt.nt_channel = chan;
- nt.nt_ncode = NT_ARRIVED;
- isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
+ isp_prt(isp, ISP_LOGTINFO, "Chan %d WWPN 0x%016llx "
+ "PortID 0x%06x handle 0x%x vtgt %d %s added", chan,
+ (unsigned long long) ini, s_id, nphdl, i, buf);
+
+ /* Notify above levels about new port arrival. */
+ isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
}
/*
@@ -2602,45 +2562,27 @@ void
isp_del_wwn_entry(ispsoftc_t *isp, int chan, uint64_t ini, uint16_t nphdl, uint32_t s_id)
{
fcparam *fcp;
- isp_notify_t nt;
fcportdb_t *lp;
if (nphdl >= MAX_NPORT_HANDLE) {
- isp_prt(isp, ISP_LOGWARN, "Chan %d IID 0x%016llx bad N-Port handle 0x%04x Port ID 0x%06x",
- chan, (unsigned long long) ini, nphdl, s_id);
+ isp_prt(isp, ISP_LOGWARN, "Chan %d WWPN 0x%016llx PortID 0x%06x bad handle 0x%x",
+ chan, (unsigned long long) ini, s_id, nphdl);
return;
}
fcp = FCPARAM(isp, chan);
- if (fcp->isp_tgt_map[nphdl] == 0) {
- lp = NULL;
- } else {
- lp = &fcp->portdb[fcp->isp_tgt_map[nphdl] - 1];
- if (lp->target_mode == 0) {
- lp = NULL;
- }
- }
- if (lp == NULL) {
- isp_prt(isp, ISP_LOGWARN, "Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x cannot be found to be deleted",
- chan, (unsigned long long) ini, nphdl, s_id);
+ if (isp_find_pdb_by_handle(isp, chan, nphdl, &lp) == 0) {
+ isp_prt(isp, ISP_LOGWARN, "Chan %d WWPN 0x%016llx PortID 0x%06x handle 0x%x cannot be found to be deleted",
+ chan, (unsigned long long) ini, s_id, nphdl);
isp_dump_portdb(isp, chan);
return;
}
- isp_prt(isp, ISP_LOGTINFO, "Chan %d IID 0x%016llx N-Port Handle 0x%04x Port ID 0x%06x vtgt %d deleted",
- chan, (unsigned long long) lp->port_wwn, nphdl, lp->portid, fcp->isp_tgt_map[nphdl] - 1);
- fcp->isp_tgt_map[nphdl] = 0;
- lp->state = FC_PORTDB_STATE_DEAD;
+ isp_prt(isp, ISP_LOGTINFO, "Chan %d WWPN 0x%016llx PortID 0x%06x handle 0x%x vtgt %d deleted",
+ chan, (unsigned long long) lp->port_wwn, lp->portid, nphdl, FC_PORTDB_TGT(isp, chan, lp));
+ lp->state = FC_PORTDB_STATE_NIL;
- ISP_MEMZERO(&nt, sizeof (nt));
- nt.nt_hba = isp;
- nt.nt_wwn = lp->port_wwn;
- nt.nt_tgt = FCPARAM(isp, chan)->isp_wwpn;
- nt.nt_sid = lp->portid;
- nt.nt_did = FCPARAM(isp, chan)->isp_portid;
- nt.nt_nphdl = nphdl;
- nt.nt_channel = chan;
- nt.nt_ncode = NT_DEPARTED;
- isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
+ /* Notify above levels about gone port. */
+ isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
}
void
@@ -2671,11 +2613,11 @@ isp_del_all_wwn_entries(ispsoftc_t *isp, int chan)
if (fcp == NULL) {
return;
}
- for (i = 0; i < MAX_NPORT_HANDLE; i++) {
- if (fcp->isp_tgt_map[i]) {
- fcportdb_t *lp = &fcp->portdb[fcp->isp_tgt_map[i] - 1];
+ for (i = 0; i < MAX_FC_TARG; i++) {
+ fcportdb_t *lp = &fcp->portdb[i];
+
+ if (lp->state != FC_PORTDB_STATE_NIL)
isp_del_wwn_entry(isp, chan, lp->port_wwn, lp->handle, lp->portid);
- }
}
}
@@ -2702,7 +2644,7 @@ isp_del_wwn_entries(ispsoftc_t *isp, isp_notify_t *mp)
* We need to find the actual entry so we can delete it.
*/
if (mp->nt_nphdl != NIL_HANDLE) {
- if (isp_find_pdb_by_loopid(isp, mp->nt_channel, mp->nt_nphdl, &lp)) {
+ if (isp_find_pdb_by_handle(isp, mp->nt_channel, mp->nt_nphdl, &lp)) {
isp_del_wwn_entry(isp, mp->nt_channel, lp->port_wwn, lp->handle, lp->portid);
return;
}
@@ -2719,8 +2661,8 @@ isp_del_wwn_entries(ispsoftc_t *isp, isp_notify_t *mp)
return;
}
}
- isp_prt(isp, ISP_LOGWARN, "Chan %d unable to find entry to delete N-port handle 0x%04x initiator WWN 0x%016llx Port ID 0x%06x",
- mp->nt_channel, mp->nt_nphdl, (unsigned long long) mp->nt_wwn, mp->nt_sid);
+ isp_prt(isp, ISP_LOGWARN, "Chan %d unable to find entry to delete WWPN 0x%016jx PortID 0x%06x handle 0x%x",
+ mp->nt_channel, mp->nt_wwn, mp->nt_sid, mp->nt_nphdl);
}
void
OpenPOWER on IntegriCloud