Author: mav
Date: Mon Nov 30 21:40:20 2015
New Revision: 291514
URL: https://svnweb.freebsd.org/changeset/base/291514

Log:
  MFC r291080: Another round of port scanner rewrite.
  
  This change simplifies and unifies port adding/updating for loop and
  fabric scanners.  It also fixes problems with scanning restarts due to
  concurrent port databases changes.  It also fixes many cosmetic issues.

Modified:
  stable/10/sys/dev/isp/isp.c
  stable/10/sys/dev/isp/isp_freebsd.c
  stable/10/sys/dev/isp/isp_library.c
  stable/10/sys/dev/isp/isp_library.h
  stable/10/sys/dev/isp/ispmbox.h
  stable/10/sys/dev/isp/ispvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/isp/isp.c
==============================================================================
--- stable/10/sys/dev/isp/isp.c Mon Nov 30 21:39:33 2015        (r291513)
+++ stable/10/sys/dev/isp/isp.c Mon Nov 30 21:40:20 2015        (r291514)
@@ -68,9 +68,7 @@ __FBSDID("$FreeBSD$");
 /*
  * Local static data
  */
-static const char fconf[] = "Chan %d PortDB[%d] changed:\n current 
=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n database=(0x%x@0x%06x 0x%08x%08x 
0x%08x%08x)";
 static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ 
idx %d (next %d) nlooked %d";
-static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x LoopID 
0x%x Connection '%s'";
 static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
 static const char lipd[] = "Chan %d LIP destroyed %d active commands";
 static const char sacq[] = "unable to acquire scratch area";
@@ -108,7 +106,8 @@ static void isp_scsi_init(ispsoftc_t *);
 static void isp_scsi_channel_init(ispsoftc_t *, int);
 static void isp_fibre_init(ispsoftc_t *);
 static void isp_fibre_init_2400(ispsoftc_t *);
-static void isp_mark_portdb(ispsoftc_t *, int, int);
+static void isp_clear_portdb(ispsoftc_t *, int);
+static void isp_mark_portdb(ispsoftc_t *, int);
 static int isp_plogx(ispsoftc_t *, int, uint16_t, uint32_t, int, int);
 static int isp_port_login(ispsoftc_t *, uint16_t, uint32_t);
 static int isp_port_logout(ispsoftc_t *, uint16_t, uint32_t);
@@ -2283,7 +2282,7 @@ isp_fibre_init_2400(ispsoftc_t *isp)
 }
 
 static void
-isp_mark_portdb(ispsoftc_t *isp, int chan, int disposition)
+isp_clear_portdb(ispsoftc_t *isp, int chan)
 {
        fcparam *fcp = FCPARAM(isp, chan);
        fcportdb_t *lp;
@@ -2292,30 +2291,41 @@ isp_mark_portdb(ispsoftc_t *isp, int cha
        for (i = 0; i < MAX_FC_TARG; i++) {
                lp = &fcp->portdb[i];
                switch (lp->state) {
-               case FC_PORTDB_STATE_PROBATIONAL:
                case FC_PORTDB_STATE_DEAD:
                case FC_PORTDB_STATE_CHANGED:
-               case FC_PORTDB_STATE_PENDING_VALID:
                case FC_PORTDB_STATE_VALID:
-                       if (disposition > 0)
-                               lp->state = FC_PORTDB_STATE_PROBATIONAL;
-                       else {
-                               lp->state = FC_PORTDB_STATE_NIL;
-                               isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
-                       }
-                       break;
-               case FC_PORTDB_STATE_ZOMBIE:
+                       lp->state = FC_PORTDB_STATE_NIL;
+                       isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
                        break;
                case FC_PORTDB_STATE_NIL:
                case FC_PORTDB_STATE_NEW:
-               default:
-                       ISP_MEMZERO(lp, sizeof(*lp));
                        lp->state = FC_PORTDB_STATE_NIL;
                        break;
+               case FC_PORTDB_STATE_ZOMBIE:
+                       break;
+               default:
+                       panic("Don't know how to clear state %d\n", lp->state);
                }
        }
 }
 
+static void
+isp_mark_portdb(ispsoftc_t *isp, int chan)
+{
+       fcparam *fcp = FCPARAM(isp, chan);
+       fcportdb_t *lp;
+       int i;
+
+       for (i = 0; i < MAX_FC_TARG; i++) {
+               lp = &fcp->portdb[i];
+               if (lp->state == FC_PORTDB_STATE_NIL)
+                       continue;
+               if ((lp->portid & 0xfffc00) == 0xfffc00)
+                       continue;
+               fcp->portdb[i].probational = 1;
+       }
+}
+
 /*
  * Perform an IOCB PLOGI or LOGO via EXECUTE IOCB A64 for 24XX cards
  * or via FABRIC LOGIN/FABRIC LOGOUT for other cards.
@@ -2333,6 +2343,9 @@ isp_plogx(ispsoftc_t *isp, int chan, uin
        const char *msg;
        char buf[64];
 
+       isp_prt(isp, ISP_LOG_SANCFG, "Chan %d PLOGX %s PortID 0x%06x nphdl 
0x%x",
+           chan, (flags & PLOGX_FLG_CMD_MASK) == PLOGX_FLG_CMD_PLOGI ?
+           "Login":"Logout", portid, handle);
        if (!IS_24XX(isp)) {
                int action = flags & PLOGX_FLG_CMD_MASK;
                if (action == PLOGX_FLG_CMD_PLOGI) {
@@ -2766,7 +2779,7 @@ static int
 isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
 {
        mbreg_t mbs;
-       int r;
+       int i, r;
        uint16_t nphdl;
        fcparam *fcp;
        isp_pdb_t pdb;
@@ -2774,8 +2787,8 @@ isp_fclink_test(ispsoftc_t *isp, int cha
 
        fcp = FCPARAM(isp, chan);
 
-       /* Mark port database entries for following scan. */
-       isp_mark_portdb(isp, chan, 1);
+       /* Mark port database entries probational for following scan. */
+       isp_mark_portdb(isp, chan);
 
        if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
                return (0);
@@ -2818,12 +2831,6 @@ isp_fclink_test(ispsoftc_t *isp, int cha
                return (-1);
        }
 
-       if (ISP_CAP_2KLOGIN(isp)) {
-               fcp->isp_loopid = mbs.param[1];
-       } else {
-               fcp->isp_loopid = mbs.param[1] & 0xff;
-       }
-
        if (IS_2100(isp)) {
                /*
                 * Don't bother with fabric if we are using really old
@@ -2842,30 +2849,17 @@ isp_fclink_test(ispsoftc_t *isp, int cha
        }
        fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
 
-       /*
-        * Check to make sure we got a valid loopid
-        * The 24XX seems to mess this up for multiple channels.
-        */
-       if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_NL_PORT) {
+       if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
+               fcp->isp_loopid = mbs.param[1] & 0xff;
+       } else if (fcp->isp_topo != TOPO_F_PORT) {
                uint8_t alpa = fcp->isp_portid;
 
-               if (alpa == 0) {
-                       /* "Cannot Happen" */
-                       isp_prt(isp, ISP_LOGWARN, "Zero AL_PA for Loop 
Topology?");
-               } else {
-                       int i;
-                       for (i = 0; alpa_map[i]; i++) {
-                               if (alpa_map[i] == alpa) {
-                                       break;
-                               }
-                       }
-                       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, i, alpa_map[i], fcp->isp_loopid, 
alpa);
-                               fcp->isp_loopid = i;
-                       }
+               for (i = 0; alpa_map[i]; i++) {
+                       if (alpa_map[i] == alpa)
+                               break;
                }
+               if (alpa_map[i])
+                       fcp->isp_loopid = i;
        }
 
        if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
@@ -2899,6 +2893,7 @@ isp_fclink_test(ispsoftc_t *isp, int cha
        }
 
 not_on_fabric:
+       /* Get link speed. */
        fcp->isp_gbspeed = 1;
        if (IS_23XX(isp) || IS_24XX(isp)) {
                MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
@@ -2906,27 +2901,29 @@ not_on_fabric:
                /* mbs.param[2] undefined if we're just getting rate */
                isp_mboxcmd(isp, &mbs);
                if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
-                       if (mbs.param[1] == MBGSD_EIGHTGB) {
-                               isp_prt(isp, ISP_LOGINFO, "Chan %d 8Gb link 
speed", chan);
+                       if (mbs.param[1] == MBGSD_10GB)
+                               fcp->isp_gbspeed = 10;
+                       else if (mbs.param[1] == MBGSD_16GB)
+                               fcp->isp_gbspeed = 16;
+                       else if (mbs.param[1] == MBGSD_8GB)
                                fcp->isp_gbspeed = 8;
-                       } else if (mbs.param[1] == MBGSD_FOURGB) {
-                               isp_prt(isp, ISP_LOGINFO, "Chan %d 4Gb link 
speed", chan);
+                       else if (mbs.param[1] == MBGSD_4GB)
                                fcp->isp_gbspeed = 4;
-                       } else if (mbs.param[1] == MBGSD_TWOGB) {
-                               isp_prt(isp, ISP_LOGINFO, "Chan %d 2Gb link 
speed", chan);
+                       else if (mbs.param[1] == MBGSD_2GB)
                                fcp->isp_gbspeed = 2;
-                       } else if (mbs.param[1] == MBGSD_ONEGB) {
-                               isp_prt(isp, ISP_LOGINFO, "Chan %d 1Gb link 
speed", chan);
+                       else if (mbs.param[1] == MBGSD_1GB)
                                fcp->isp_gbspeed = 1;
-                       }
                }
        }
 
        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|ISP_LOGCONFIG,
+           "Chan %d WWPN %016jx WWNN %016jx",
+           chan, (uintmax_t)fcp->isp_wwpn, (uintmax_t)fcp->isp_wwnn);
+       isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
+           "Chan %d %dGb %s PortID 0x%06x LoopID 0x%02x",
+           chan, fcp->isp_gbspeed, isp_fc_toponame(fcp), fcp->isp_portid,
+           fcp->isp_loopid);
        isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
        return (0);
 }
@@ -2963,13 +2960,11 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
        for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
                lp = &fcp->portdb[dbidx];
 
-               if (lp->state == FC_PORTDB_STATE_NIL ||
-                   lp->state == FC_PORTDB_STATE_VALID) {
+               if (lp->state == FC_PORTDB_STATE_NIL)
                        continue;
-               }
-
+               if (lp->probational && lp->state != FC_PORTDB_STATE_ZOMBIE)
+                       lp->state = FC_PORTDB_STATE_DEAD;
                switch (lp->state) {
-               case FC_PORTDB_STATE_PROBATIONAL:
                case FC_PORTDB_STATE_DEAD:
                        lp->state = FC_PORTDB_STATE_NIL;
                        isp_async(isp, ISPASYNC_DEV_GONE, chan, lp);
@@ -2979,36 +2974,23 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
                                    PLOGX_FLG_CMD_LOGO |
                                    PLOGX_FLG_IMPLICIT |
                                    PLOGX_FLG_FREE_NPHDL, 0);
-                       } else {
-                               lp->autologin = 0;
                        }
-                       lp->new_prli_word3 = 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:
-                       lp->portid = lp->new_portid;
-                       lp->prli_word3 = lp->new_prli_word3;
                        lp->state = FC_PORTDB_STATE_VALID;
                        isp_async(isp, ISPASYNC_DEV_ARRIVED, chan, lp);
-                       lp->new_prli_word3 = 0;
-                       lp->new_portid = 0;
                        break;
                case FC_PORTDB_STATE_CHANGED:
                        lp->state = FC_PORTDB_STATE_VALID;
                        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;
                        break;
-               case FC_PORTDB_STATE_PENDING_VALID:
-                       lp->portid = lp->new_portid;
-                       lp->prli_word3 = lp->new_prli_word3;
-                       lp->state = FC_PORTDB_STATE_VALID;
+               case FC_PORTDB_STATE_VALID:
                        isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
                        break;
                case FC_PORTDB_STATE_ZOMBIE:
@@ -3032,15 +3014,78 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
        return (0);
 }
 
+static void
+isp_pdb_add_update(ispsoftc_t *isp, int chan, isp_pdb_t *pdb)
+{
+       fcportdb_t *lp;
+       uint64_t wwnn, wwpn;
+
+       MAKE_WWN_FROM_NODE_NAME(wwnn, pdb->nodename);
+       MAKE_WWN_FROM_NODE_NAME(wwpn, pdb->portname);
+
+       /* Search port database for the same WWPN. */
+       if (isp_find_pdb_by_wwpn(isp, chan, wwpn, &lp)) {
+               if (!lp->probational) {
+                       isp_prt(isp, ISP_LOGERR,
+                           "Chan %d Port 0x%06x@0x%04x [%d] is not probational 
(0x%x)",
+                           chan, lp->portid, lp->handle,
+                           FC_PORTDB_TGT(isp, chan, lp), lp->state);
+                       isp_dump_portdb(isp, chan);
+                       return;
+               }
+               lp->probational = 0;
+               lp->node_wwn = wwnn;
+
+               /* Old device, nothing new. */
+               if (lp->portid == pdb->portid &&
+                   lp->handle == pdb->handle &&
+                   lp->prli_word3 == pdb->prli_word3) {
+                       if (lp->state != FC_PORTDB_STATE_NEW)
+                               lp->state = FC_PORTDB_STATE_VALID;
+                       isp_prt(isp, ISP_LOG_SANCFG,
+                           "Chan %d Port 0x%06x@0x%04x is valid",
+                           chan, pdb->portid, pdb->handle);
+                       return;
+               }
+
+               /* Something has changed. */
+               lp->state = FC_PORTDB_STATE_CHANGED;
+               lp->handle = pdb->handle;
+               lp->new_portid = pdb->portid;
+               lp->new_prli_word3 = pdb->prli_word3;
+               isp_prt(isp, ISP_LOG_SANCFG,
+                   "Chan %d Port 0x%06x@0x%04x is changed",
+                   chan, pdb->portid, pdb->handle);
+               return;
+       }
+
+       /* It seems like a new port. Find an empty slot for it. */
+       if (!isp_find_pdb_empty(isp, chan, &lp)) {
+               isp_prt(isp, ISP_LOGERR, "Chan %d out of portdb entries", chan);
+               return;
+       }
+
+       ISP_MEMZERO(lp, sizeof (fcportdb_t));
+       lp->autologin = 1;
+       lp->probational = 0;
+       lp->state = FC_PORTDB_STATE_NEW;
+       lp->portid = lp->new_portid = pdb->portid;
+       lp->prli_word3 = lp->new_prli_word3 = pdb->prli_word3;
+       lp->handle = pdb->handle;
+       lp->port_wwn = wwpn;
+       lp->node_wwn = wwnn;
+       isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Port 0x%06x@0x%04x is new",
+           chan, pdb->portid, pdb->handle);
+}
+
 /*
  * Scan local loop for devices.
  */
 static int
 isp_scan_loop(ispsoftc_t *isp, int chan)
 {
-       fcportdb_t *lp, tmp;
        fcparam *fcp = FCPARAM(isp, chan);
-       int i, idx, lim, r;
+       int idx, lim, r;
        isp_pdb_t pdb;
        uint16_t handles[LOCAL_LOOP_LIM];
        uint16_t handle;
@@ -3052,8 +3097,7 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
                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) {
+       if (TOPO_IS_FABRIC(fcp->isp_topo)) {
                isp_prt(isp, ISP_LOG_SANCFG,
                    "Chan %d FC loop scan done (no loop)", chan);
                fcp->isp_loopstate = LOOP_LSCAN_DONE;
@@ -3066,7 +3110,6 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
        if (r != 0) {
                isp_prt(isp, ISP_LOG_SANCFG,
                    "Chan %d Getting list of handles failed with %x", chan, r);
-fail:
                isp_prt(isp, ISP_LOG_SANCFG,
                    "Chan %d FC loop scan done (bad)", chan);
                return (-1);
@@ -3113,6 +3156,8 @@ abort:
                 * Get the port database entity for this index.
                 */
                r = isp_getpdb(isp, chan, handle, &pdb, 1);
+               if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
+                       goto abort;
                if (r != 0) {
                        isp_prt(isp, ISP_LOGDEBUG1,
                            "Chan %d FC Scan Loop handle %d returned %x",
@@ -3122,145 +3167,7 @@ abort:
                        continue;
                }
 
-               if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
-                       goto abort;
-
-               /*
-                * 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 this, but
-                * now we just punt.
-                */
-               if (IS_2100(isp) && pdb.handle != handle) {
-                       isp_prt(isp, ISP_LOGWARN,
-                           "Chan %d getpdb() returned wrong handle %x != %x",
-                           chan, pdb.handle, handle);
-                       goto fail;
-               }
-
-               /*
-                * Save the pertinent info locally.
-                */
-               MAKE_WWN_FROM_NODE_NAME(tmp.node_wwn, pdb.nodename);
-               MAKE_WWN_FROM_NODE_NAME(tmp.port_wwn, pdb.portname);
-               tmp.prli_word3 = pdb.prli_word3;
-               tmp.portid = pdb.portid;
-               tmp.handle = pdb.handle;
-
-               /*
-                * Check to make sure it's still a valid entry. The 24XX seems
-                * to return a portid but not a WWPN/WWNN or role for devices
-                * which shift on a loop.
-                */
-               if (tmp.node_wwn == 0 || tmp.port_wwn == 0 || tmp.portid == 0) {
-                       int a, b, c;
-                       isp_prt(isp, ISP_LOGWARN,
-                           "Chan %d bad pdb (WWNN %016jx, WWPN %016jx, PortID 
%06x, W3 0x%x, H 0x%x) @ handle 0x%x",
-                           chan, tmp.node_wwn, tmp.port_wwn, tmp.portid, 
tmp.prli_word3, tmp.handle, handle);
-                       a = (tmp.node_wwn == 0);
-                       b = (tmp.port_wwn == 0);
-                       c = (tmp.portid == 0);
-                       if (a == 0 && b == 0) {
-                               tmp.node_wwn =
-                                   isp_get_wwn(isp, chan, handle, 1);
-                               tmp.port_wwn =
-                                   isp_get_wwn(isp, chan, handle, 0);
-                               if (tmp.node_wwn && tmp.port_wwn) {
-                                       isp_prt(isp, ISP_LOGWARN, "DODGED!");
-                                       goto cont;
-                               }
-                       }
-                       isp_dump_portdb(isp, chan);
-                       continue;
-               }
-  cont:
-
-               /*
-                * Now search the entire port database
-                * for the same Port WWN.
-                */
-               if (isp_find_pdb_by_wwn(isp, chan, tmp.port_wwn, &lp)) {
-                       /*
-                        * Okay- we've found a non-nil entry that matches.
-                        * Check to make sure it's probational or a zombie.
-                        */
-                       if (lp->state != FC_PORTDB_STATE_PROBATIONAL &&
-                           lp->state != FC_PORTDB_STATE_ZOMBIE &&
-                           lp->state != FC_PORTDB_STATE_VALID) {
-                               isp_prt(isp, ISP_LOGERR,
-                                   "Chan %d [%d] not probational/zombie 
(0x%x)",
-                                   chan, FC_PORTDB_TGT(isp, chan, lp), 
lp->state);
-                               isp_dump_portdb(isp, chan);
-                               goto fail;
-                       }
-
-                       /*
-                        * Mark the device as something the f/w logs into
-                        * automatically.
-                        */
-                       lp->autologin = 1;
-                       lp->node_wwn = tmp.node_wwn;
-
-                       /*
-                        * 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 && lp->prli_word3 == tmp.prli_word3) {
-                               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 now 
pending valid",
-                                   chan, tmp.portid, tmp.handle);
-                               continue;
-                       }
-
-                       /*
-                        * We can wipe out the old handle value
-                        * here because it's no longer valid.
-                        */
-                       lp->handle = tmp.handle;
-
-                       /*
-                        * 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);
-                       lp->state = FC_PORTDB_STATE_CHANGED;
-                       lp->new_portid = tmp.portid;
-                       lp->new_prli_word3 = tmp.prli_word3;
-                       continue;
-               }
-
-               /*
-                * Ah. A new device entry. Find an empty slot
-                * for it and save info for later disposition.
-                */
-               for (i = 0; i < MAX_FC_TARG; i++) {
-                       if (fcp->portdb[i].state == FC_PORTDB_STATE_NIL) {
-                               break;
-                       }
-               }
-               if (i == MAX_FC_TARG) {
-                       isp_prt(isp, ISP_LOGERR,
-                           "Chan %d out of portdb entries", chan);
-                       continue;
-               }
-               lp = &fcp->portdb[i];
-
-               ISP_MEMZERO(lp, sizeof (fcportdb_t));
-               lp->autologin = 1;
-               lp->state = FC_PORTDB_STATE_NEW;
-               lp->new_portid = tmp.portid;
-               lp->new_prli_word3 = tmp.prli_word3;
-               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 a new entry",
-                   chan, tmp.portid, tmp.handle);
+               isp_pdb_add_update(isp, chan, &pdb);
        }
        if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
                goto abort;
@@ -3359,10 +3266,6 @@ isp_gid_ft_ct_passthru(ispsoftc_t *isp, 
 
        isp_prt(isp, ISP_LOGDEBUG0, "Chan %d scanning fabric (GID_FT) via CT", 
chan);
 
-       if (!IS_24XX(isp)) {
-               return (1);
-       }
-
        /*
         * Build a Passthrough IOCB in memory.
         */
@@ -3445,6 +3348,7 @@ static int
 isp_scan_fabric(ispsoftc_t *isp, int chan)
 {
        fcparam *fcp = FCPARAM(isp, chan);
+       fcportdb_t *lp;
        uint32_t portid;
        uint16_t nphdl;
        isp_pdb_t pdb;
@@ -3458,7 +3362,7 @@ isp_scan_fabric(ispsoftc_t *isp, int cha
                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) {
+       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);
@@ -3495,16 +3399,13 @@ abort:
                goto fail;
        }
 
-       if (IS_24XX(isp)) {
+       /* Get list of port IDs from SNS. */
+       if (IS_24XX(isp))
                r = isp_gid_ft_ct_passthru(isp, chan);
-       } else {
+       else
                r = isp_gid_ft_sns(isp, chan);
-       }
-
-       if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+       if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
                goto abort;
-       }
-
        if (r > 0) {
                fcp->isp_loopstate = LOOP_FSCAN_DONE;
                FC_SCRATCH_RELEASE(isp, chan);
@@ -3519,9 +3420,8 @@ abort:
        rs0 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+IGPOFF);
        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) {
+       if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
                goto abort;
-       }
        if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) {
                int level;
                if (rs1->snscb_cthdr.ct_reason == 9 && 
rs1->snscb_cthdr.ct_explanation == 7) {
@@ -3538,21 +3438,11 @@ abort:
                return (0);
        }
 
-       /*
-        * Go through the list and remove duplicate port ids.
-        */
-
-       portlim = 0;
-       portidx = 0;
+       /* Check our buffer was big enough to get the full list. */
        for (portidx = 0; portidx < NGENT-1; portidx++) {
-               if (rs1->snscb_ports[portidx].control & 0x80) {
+               if (rs1->snscb_ports[portidx].control & 0x80)
                        break;
-               }
        }
-
-       /*
-        * If we're not at the last entry, our list wasn't big enough.
-        */
        if ((rs1->snscb_ports[portidx].control & 0x80) == 0) {
                isp_prt(isp, ISP_LOGWARN,
                    "fabric too big for scratch area: increase ISP_FC_SCRLEN");
@@ -3561,6 +3451,7 @@ abort:
        isp_prt(isp, ISP_LOG_SANCFG,
            "Chan %d Got %d ports back from name server", chan, portlim);
 
+       /* Go through the list and remove duplicate port ids. */
        for (portidx = 0; portidx < portlim; portidx++) {
                int npidx;
 
@@ -3603,55 +3494,34 @@ abort:
         */
 
        for (portidx = 0; portidx < portlim; portidx++) {
-               fcportdb_t *lp;
-               uint64_t wwnn, wwpn;
-               int dbidx, nr;
-
-               portid =
-                   ((rs1->snscb_ports[portidx].portid[0]) << 16) |
-                   ((rs1->snscb_ports[portidx].portid[1]) << 8) |
-                   ((rs1->snscb_ports[portidx].portid[2]));
-
+               portid = ((rs1->snscb_ports[portidx].portid[0]) << 16) |
+                        ((rs1->snscb_ports[portidx].portid[1]) << 8) |
+                        ((rs1->snscb_ports[portidx].portid[2]));
+               isp_prt(isp, ISP_LOG_SANCFG,
+                   "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, portidx);
                        continue;
                }
-
                if (portid == fcp->isp_portid) {
                        isp_prt(isp, ISP_LOG_SANCFG,
                            "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);
-
-               /*
-                * We now search our Port Database for any
-                * 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];
-
-                       if (lp->state != FC_PORTDB_STATE_PROBATIONAL) {
-                               continue;
-                       }
-                       if (lp->portid == portid) {
-                               break;
+               /* Now search the entire port database for the same portid. */
+               if (isp_find_pdb_by_portid(isp, chan, portid, &lp)) {
+                       if (!lp->probational) {
+                               isp_prt(isp, ISP_LOGERR,
+                                   "Chan %d Port 0x%06x@0x%04x [%d] is not 
probational (0x%x)",
+                                   chan, lp->portid, lp->handle,
+                                   FC_PORTDB_TGT(isp, chan, lp), lp->state);
+                               FC_SCRATCH_RELEASE(isp, chan);
+                               isp_dump_portdb(isp, chan);
+                               goto fail;
                        }
-               }
-
-               /*
-                * We found a probational entry with this Port ID.
-                */
-               if (dbidx < MAX_FC_TARG) {
-                       int handle_changed = 0;
-
-                       lp = &fcp->portdb[dbidx];
 
                        /*
                         * See if we're still logged into it.
@@ -3667,241 +3537,38 @@ abort:
                         * and leave the new portid and role in the
                         * database entry for somebody further along to
                         * decide what to do (policy choice).
-                        *
                         */
-
                        r = isp_getpdb(isp, chan, lp->handle, &pdb, 0);
-                       if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+                       if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
                                goto abort;
-                       }
                        if (r != 0) {
-                               lp->new_portid = portid;
                                lp->state = FC_PORTDB_STATE_DEAD;
-                               isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric 
PortID 0x%06x handle 0x%x is dead (%d)", chan, portid, lp->handle, r);
-                               continue;
-                       }
-
-
-                       /*
-                        * Check to make sure that handle, portid, WWPN and
-                        * WWNN agree. If they don't, then the association
-                        * between this PortID and the stated handle has been
-                        * broken by the firmware.
-                        */
-                       MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
-                       MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
-                       if (pdb.handle != lp->handle ||
-                           pdb.portid != portid ||
-                           wwpn != lp->port_wwn ||
-                           (lp->node_wwn != 0 && wwnn != lp->node_wwn)) {
                                isp_prt(isp, ISP_LOG_SANCFG,
-                                   fconf, chan, dbidx, pdb.handle, pdb.portid,
-                                   (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
-                                   (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
-                                   lp->handle, portid,
-                                   (uint32_t) (lp->node_wwn >> 32),
-                                   (uint32_t) lp->node_wwn,
-                                   (uint32_t) (lp->port_wwn >> 32),
-                                   (uint32_t) lp->port_wwn);
-                               /*
-                                * Try to re-login to this device using a
-                                * new handle. If that fails, mark it dead.
-                                *
-                                * isp_login_device will check for handle and
-                                * portid consistency after re-login.
-                                *
-                                */
-                               if ((fcp->role & ISP_ROLE_INITIATOR) == 0 ||
-                                   isp_login_device(isp, chan, portid, &pdb,
-                                    &FCPARAM(isp, 0)->isp_lasthdl)) {
-                                       lp->new_portid = portid;
-                                       lp->state = FC_PORTDB_STATE_DEAD;
-                                       if (fcp->isp_loopstate <
-                                           LOOP_SCANNING_FABRIC) {
-                                               goto abort;
-                                       }
-                                       continue;
-                               }
-                               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);
-                               if (wwpn != lp->port_wwn ||
-                                   (lp->node_wwn != 0 && wwnn != 
lp->node_wwn)) {
-                                       isp_prt(isp, ISP_LOGWARN, "changed WWN"
-                                           " after relogin");
-                                       lp->new_portid = portid;
-                                       lp->state = FC_PORTDB_STATE_DEAD;
-                                       continue;
-                               }
-
-                               lp->handle = pdb.handle;
-                               handle_changed++;
+                                   "Chan %d Port 0x%06x handle 0x%x is dead 
(%d)",
+                                   chan, portid, lp->handle, r);
+                               goto relogin;
                        }
 
-                       nr = pdb.prli_word3;
-
-                       /*
-                        * Check to see whether the portid and roles have
-                        * stayed the same. If they have stayed the same,
-                        * we believe that this is the same device and it
-                        * hasn't become disconnected and reconnected, so
-                        * mark it as pending valid.
-                        *
-                        * If they aren't the same, mark the device as a
-                        * changed device and save the new port id and role
-                        * and let somebody else decide.
-                        */
-
-                       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);
-                               lp->state = FC_PORTDB_STATE_CHANGED;
-                       } else {
-                               isp_prt(isp, ISP_LOG_SANCFG,
-                                   "Chan %d Fabric port 0x%06x now pending 
valid",
-                                   chan, portid);
-                               lp->state = FC_PORTDB_STATE_PENDING_VALID;
-                       }
+                       isp_pdb_add_update(isp, chan, &pdb);
                        continue;
                }
 
+relogin:
                if ((fcp->role & ISP_ROLE_INITIATOR) == 0)
                        continue;
 
-               /*
-                * Ah- a new entry. Search the database again for all non-NIL
-                * 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.
-                */
-
-               dbidx = MAX_FC_TARG;
-               for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
-                       if (lp->state == FC_PORTDB_STATE_NIL) {
-                               if (dbidx == MAX_FC_TARG) {
-                                       dbidx = lp - fcp->portdb;
-                               }
-                               continue;
-                       }
-                       if (lp->state == FC_PORTDB_STATE_ZOMBIE) {
-                               continue;
-                       }
-                       if (lp->portid == portid) {
-                               break;
-                       }
-               }
-
-               if (lp < &fcp->portdb[MAX_FC_TARG]) {
-                       isp_prt(isp, ISP_LOGWARN, "Chan %d PortID 0x%06x "
-                           "already at %d handle %d state %d",
-                           chan, portid, dbidx, lp->handle, lp->state);
-                       continue;
-               }
-
-               /*
-                * We should have the index of the first free entry seen.
-                */
-               if (dbidx == MAX_FC_TARG) {
-                       isp_prt(isp, ISP_LOGERR,
-                           "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.
-                *
-                * isp_login_device will check for handle and
-                * portid consistency after login.
-                */
                if (isp_login_device(isp, chan, portid, &pdb,
                    &FCPARAM(isp, 0)->isp_lasthdl)) {
-                       if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+                       if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC)
                                goto abort;
-                       }
-                       continue;
-               }
-               if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
-                       goto abort;
-               }
-
-               nphdl = pdb.handle;
-               MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
-               MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
-               nr = pdb.prli_word3;
-
-               /*
-                * And go through the database *one* more time to make sure
-                * that we do not make more than one entry that has the same
-                * WWNN/WWPN duple
-                */
-               for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
-                       if ((fcp->portdb[dbidx].node_wwn == wwnn ||
-                            fcp->portdb[dbidx].node_wwn == 0) &&
-                           fcp->portdb[dbidx].port_wwn == wwpn) {
-                               break;
-                       }
-               }
-
-               if (dbidx == MAX_FC_TARG) {
-                       ISP_MEMZERO(lp, sizeof (fcportdb_t));
-                       lp->handle = nphdl;
-                       lp->node_wwn = wwnn;
-                       lp->port_wwn = wwpn;
-                       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);
                        continue;
                }
 
-               if (fcp->portdb[dbidx].state != FC_PORTDB_STATE_ZOMBIE) {
-                       isp_prt(isp, ISP_LOGWARN,
-                           "Chan %d PortID 0x%x 0x%08x%08x/0x%08x%08x %ld "
-                           "already at idx %d, state 0x%x", chan, portid,
-                           (uint32_t) (wwnn >> 32), (uint32_t) wwnn,
-                           (uint32_t) (wwpn >> 32), (uint32_t) wwpn,
-                           (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 = nphdl;
-               lp->node_wwn = wwnn;
-               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);
-                       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);
-                       lp->state = FC_PORTDB_STATE_PENDING_VALID;
-               }
+               isp_pdb_add_update(isp, chan, &pdb);
        }
 
-       if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+       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 fabric scan done", chan);
@@ -3925,27 +3592,26 @@ isp_login_device(ispsoftc_t *isp, int ch
 
        handle = isp_next_handle(isp, ohp);
        for (i = 0; i < lim; i++) {
-               /*
-                * See if we're still logged into something with
-                * this handle and that something agrees with this
-                * port id.
-                */
+               if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
+                       return (-1);
+
+               /* Check if this handle is free. */
                r = isp_getpdb(isp, chan, handle, p, 0);
-               if (r == 0 && p->portid != portid) {
-                       (void) isp_plogx(isp, chan, handle, portid, 
PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1);
-               } else if (r == 0) {
+               if (r == 0) {
+                       if (p->portid != portid) {
+                               /* This handle is busy, try next one. */
+                               handle = isp_next_handle(isp, ohp);
+                               continue;
+                       }
                        break;
                }
-               if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
+               if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC)
                        return (-1);
-               }
+
                /*
                 * Now try and log into the device
                 */
                r = isp_plogx(isp, chan, handle, portid, PLOGX_FLG_CMD_PLOGI, 
1);
-               if (FCPARAM(isp, chan)->isp_loopstate != LOOP_SCANNING_FABRIC) {
-                       return (-1);
-               }
                if (r == 0) {
                        break;
                } else if ((r & 0xffff) == MBOX_PORT_ID_USED) {
@@ -3957,13 +3623,9 @@ isp_login_device(ispsoftc_t *isp, int ch
                        if (isp_plogx(isp, chan, r >> 16, portid, 
PLOGX_FLG_CMD_LOGO | PLOGX_FLG_IMPLICIT | PLOGX_FLG_FREE_NPHDL, 1)) {
                                isp_prt(isp, ISP_LOGERR, "baw... logout of %x 
failed", r >> 16);
                        }
-                       if (FCPARAM(isp, chan)->isp_loopstate != 
LOOP_SCANNING_FABRIC) {
+                       if (FCPARAM(isp, chan)->isp_loopstate != 
LOOP_SCANNING_FABRIC)
                                return (-1);
-                       }
                        r = isp_plogx(isp, chan, handle, portid, 
PLOGX_FLG_CMD_PLOGI, 1);
-                       if (FCPARAM(isp, chan)->isp_loopstate != 
LOOP_SCANNING_FABRIC) {
-                               return (-1);
-                       }
                        if (r != 0)
                                i = lim;
                        break;
@@ -3988,9 +3650,6 @@ isp_login_device(ispsoftc_t *isp, int ch
         * is and that we also have the role it plays
         */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to