[SCSI] lpfc 8.3.39: Fixed pt2pt and loop discovery problems on topology changes.
authorJames Smart <james.smart@emulex.com>
Thu, 18 Apr 2013 00:15:19 +0000 (20:15 -0400)
committerJames Bottomley <JBottomley@Parallels.com>
Thu, 2 May 2013 19:43:15 +0000 (12:43 -0700)
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_sli.c

index c586db2..4c9f94b 100644 (file)
@@ -673,6 +673,7 @@ struct lpfc_hba {
        uint32_t lmt;
 
        uint32_t fc_topology;   /* link topology, from LINK INIT */
+       uint32_t fc_topology_changed;   /* link topology, from LINK INIT */
 
        struct lpfc_stats fc_stat;
 
index 9290713..ad5b0f9 100644 (file)
@@ -2801,6 +2801,8 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
                lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
                        "3054 lpfc_topology changed from %d to %d\n",
                        prev_val, val);
+               if (prev_val != val && phba->sli_rev == LPFC_SLI_REV4)
+                       phba->fc_topology_changed = 1;
                err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
                if (err) {
                        phba->cfg_topology = prev_val;
index 7ea0d35..67cd88a 100644 (file)
@@ -29,6 +29,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport_fc.h>
 
+
 #include "lpfc_hw4.h"
 #include "lpfc_hw.h"
 #include "lpfc_sli.h"
@@ -308,16 +309,20 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
                /* Xmit ELS command <elsCmd> to remote NPORT <did> */
                lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                                 "0116 Xmit ELS command x%x to remote "
-                                "NPORT x%x I/O tag: x%x, port state: x%x\n",
+                                "NPORT x%x I/O tag: x%x, port state:x%x"
+                                " fc_flag:x%x\n",
                                 elscmd, did, elsiocb->iotag,
-                                vport->port_state);
+                                vport->port_state,
+                                vport->fc_flag);
        } else {
                /* Xmit ELS response <elsCmd> to remote NPORT <did> */
                lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                                 "0117 Xmit ELS response x%x to remote "
-                                "NPORT x%x I/O tag: x%x, size: x%x\n",
+                                "NPORT x%x I/O tag: x%x, size: x%x "
+                                "port_state x%x fc_flag x%x\n",
                                 elscmd, ndlp->nlp_DID, elsiocb->iotag,
-                                cmdSize);
+                                cmdSize, vport->port_state,
+                                vport->fc_flag);
        }
        return elsiocb;
 
@@ -909,6 +914,23 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        spin_lock_irq(shost->host_lock);
        vport->fc_flag |= FC_PT2PT;
        spin_unlock_irq(shost->host_lock);
+       /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */
+       if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) {
+               lpfc_unregister_fcf_prep(phba);
+
+               /* The FC_VFI_REGISTERED flag will get clear in the cmpl
+                * handler for unreg_vfi, but if we don't force the
+                * FC_VFI_REGISTERED flag then the reg_vfi mailbox could be
+                * built with the update bit set instead of just the vp bit to
+                * change the Nport ID.  We need to have the vp set and the
+                * Upd cleared on topology changes.
+                */
+               spin_lock_irq(shost->host_lock);
+               vport->fc_flag &= ~FC_VFI_REGISTERED;
+               spin_unlock_irq(shost->host_lock);
+               phba->fc_topology_changed = 0;
+               lpfc_issue_reg_vfi(vport);
+       }
 
        /* Start discovery - this should just do CLEAR_LA */
        lpfc_disc_start(vport);
@@ -1030,9 +1052,19 @@ stop_rr_fcf_flogi:
                        vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
                if ((phba->sli_rev == LPFC_SLI_REV4) &&
                    (!(vport->fc_flag & FC_VFI_REGISTERED) ||
-                    (vport->fc_prevDID != vport->fc_myDID))) {
-                       if (vport->fc_flag & FC_VFI_REGISTERED)
-                               lpfc_sli4_unreg_all_rpis(vport);
+                    (vport->fc_prevDID != vport->fc_myDID) ||
+                       phba->fc_topology_changed)) {
+                       if (vport->fc_flag & FC_VFI_REGISTERED) {
+                               if (phba->fc_topology_changed) {
+                                       lpfc_unregister_fcf_prep(phba);
+                                       spin_lock_irq(shost->host_lock);
+                                       vport->fc_flag &= ~FC_VFI_REGISTERED;
+                                       spin_unlock_irq(shost->host_lock);
+                                       phba->fc_topology_changed = 0;
+                               } else {
+                                       lpfc_sli4_unreg_all_rpis(vport);
+                               }
+                       }
                        lpfc_issue_reg_vfi(vport);
                        lpfc_nlp_put(ndlp);
                        goto out;
@@ -1055,9 +1087,10 @@ stop_rr_fcf_flogi:
        /* FLOGI completes successfully */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "0101 FLOGI completes successfully "
-                        "Data: x%x x%x x%x x%x\n",
+                        "Data: x%x x%x x%x x%x x%x x%x\n",
                         irsp->un.ulpWord[4], sp->cmn.e_d_tov,
-                        sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
+                        sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution,
+                        vport->port_state, vport->fc_flag);
 
        if (vport->port_state == LPFC_FLOGI) {
                /*
@@ -5047,6 +5080,8 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        struct ls_rjt stat;
        uint32_t cmd, did;
        int rc;
+       uint32_t fc_flag = 0;
+       uint32_t port_state = 0;
 
        cmd = *lp++;
        sp = (struct serv_parm *) lp;
@@ -5113,16 +5148,25 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                         * will be.
                         */
                        vport->fc_myDID = PT2PT_LocalID;
-               }
+               } else
+                       vport->fc_myDID = PT2PT_RemoteID;
 
                /*
                 * The vport state should go to LPFC_FLOGI only
                 * AFTER we issue a FLOGI, not receive one.
                 */
                spin_lock_irq(shost->host_lock);
+               fc_flag = vport->fc_flag;
+               port_state = vport->port_state;
                vport->fc_flag |= FC_PT2PT;
                vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+               vport->port_state = LPFC_FLOGI;
                spin_unlock_irq(shost->host_lock);
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                "3311 Rcv Flogi PS x%x new PS x%x "
+                                "fc_flag x%x new fc_flag x%x\n",
+                                port_state, vport->port_state,
+                                fc_flag, vport->fc_flag);
 
                /*
                 * We temporarily set fc_myDID to make it look like we are
@@ -6613,7 +6657,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
        /* ELS command <elsCmd> received from NPORT <did> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "0112 ELS command x%x received from NPORT x%x "
-                        "Data: x%x\n", cmd, did, vport->port_state);
+                        "Data: x%x x%x x%x x%x\n",
+                       cmd, did, vport->port_state, vport->fc_flag,
+                       vport->fc_myDID, vport->fc_prevDID);
        switch (cmd) {
        case ELS_CMD_PLOGI:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -6622,6 +6668,19 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 
                phba->fc_stat.elsRcvPLOGI++;
                ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
+               if (phba->sli_rev == LPFC_SLI_REV4 &&
+                   (phba->pport->fc_flag & FC_PT2PT)) {
+                       vport->fc_prevDID = vport->fc_myDID;
+                       /* Our DID needs to be updated before registering
+                        * the vfi. This is done in lpfc_rcv_plogi but
+                        * that is called after the reg_vfi.
+                        */
+                       vport->fc_myDID = elsiocb->iocb.un.rcvels.parmRo;
+                       lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                                        "3312 Remote port assigned DID x%x "
+                                        "%x\n", vport->fc_myDID,
+                                        vport->fc_prevDID);
+               }
 
                lpfc_send_els_event(vport, ndlp, payload);
 
@@ -6631,6 +6690,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        rjt_exp = LSEXP_NOTHING_MORE;
                        break;
                }
+               shost = lpfc_shost_from_vport(vport);
                if (vport->port_state < LPFC_DISC_AUTH) {
                        if (!(phba->pport->fc_flag & FC_PT2PT) ||
                                (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
@@ -6642,9 +6702,18 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                         * another NPort and the other side has initiated
                         * the PLOGI before responding to our FLOGI.
                         */
+                       if (phba->sli_rev == LPFC_SLI_REV4 &&
+                           (phba->fc_topology_changed ||
+                            vport->fc_myDID != vport->fc_prevDID)) {
+                               lpfc_unregister_fcf_prep(phba);
+                               spin_lock_irq(shost->host_lock);
+                               vport->fc_flag &= ~FC_VFI_REGISTERED;
+                               spin_unlock_irq(shost->host_lock);
+                               phba->fc_topology_changed = 0;
+                               lpfc_issue_reg_vfi(vport);
+                       }
                }
 
-               shost = lpfc_shost_from_vport(vport);
                spin_lock_irq(shost->host_lock);
                ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
                spin_unlock_irq(shost->host_lock);
index 62deb31..3081db7 100644 (file)
@@ -1436,7 +1436,8 @@ lpfc_register_fcf(struct lpfc_hba *phba)
        if (phba->fcf.fcf_flag & FCF_REGISTERED) {
                phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE);
                phba->hba_flag &= ~FCF_TS_INPROG;
-               if (phba->pport->port_state != LPFC_FLOGI) {
+               if (phba->pport->port_state != LPFC_FLOGI &&
+                   phba->pport->fc_flag & FC_FABRIC) {
                        phba->hba_flag |= FCF_RR_INPROG;
                        spin_unlock_irq(&phba->hbalock);
                        lpfc_initial_flogi(phba->pport);
@@ -2906,9 +2907,14 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                goto out_free_mem;
        }
 
-       /* If the VFI is already registered, there is nothing else to do */
+       /* If the VFI is already registered, there is nothing else to do
+        * Unless this was a VFI update and we are in PT2PT mode, then
+        * we should drop through to set the port state to ready.
+        */
        if (vport->fc_flag & FC_VFI_REGISTERED)
-               goto out_free_mem;
+               if (!(phba->sli_rev == LPFC_SLI_REV4 &&
+                     vport->fc_flag & FC_PT2PT))
+                       goto out_free_mem;
 
        /* The VPI is implicitly registered when the VFI is registered */
        spin_lock_irq(shost->host_lock);
@@ -2925,6 +2931,13 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                goto out_free_mem;
        }
 
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+                        "3313 cmpl reg vfi  port_state:%x fc_flag:%x myDid:%x "
+                        "alpacnt:%d LinkState:%x topology:%x\n",
+                        vport->port_state, vport->fc_flag, vport->fc_myDID,
+                        vport->phba->alpa_map[0],
+                        phba->link_state, phba->fc_topology);
+
        if (vport->port_state == LPFC_FABRIC_CFG_LINK) {
                /*
                 * For private loop or for NPort pt2pt,
@@ -2937,7 +2950,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                        /* Use loop map to make discovery list */
                        lpfc_disc_list_loopmap(vport);
                        /* Start discovery */
-                       lpfc_disc_start(vport);
+                       if (vport->fc_flag & FC_PT2PT)
+                               vport->port_state = LPFC_VPORT_READY;
+                       else
+                               lpfc_disc_start(vport);
                } else {
                        lpfc_start_fdiscs(phba);
                        lpfc_do_scr_ns_plogi(phba, vport);
@@ -3019,6 +3035,15 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                break;
        }
 
+       if (phba->fc_topology &&
+           phba->fc_topology != bf_get(lpfc_mbx_read_top_topology, la)) {
+               lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                               "3314 Toplogy changed was 0x%x is 0x%x\n",
+                               phba->fc_topology,
+                               bf_get(lpfc_mbx_read_top_topology, la));
+               phba->fc_topology_changed = 1;
+       }
+
        phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la);
        phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
 
@@ -4961,8 +4986,12 @@ lpfc_disc_start(struct lpfc_vport *vport)
        uint32_t clear_la_pending;
        int did_changed;
 
-       if (!lpfc_is_link_up(phba))
+       if (!lpfc_is_link_up(phba)) {
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+                                "3315 Link is not up %x\n",
+                                phba->link_state);
                return;
+       }
 
        if (phba->link_state == LPFC_CLEAR_LA)
                clear_la_pending = 1;
@@ -5868,7 +5897,7 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
        struct lpfc_vport **vports;
        struct lpfc_nodelist *ndlp;
        struct Scsi_Host *shost;
-       int i, rc;
+       int i = 0, rc;
 
        /* Unregister RPIs */
        if (lpfc_fcf_inuse(phba))
@@ -5896,6 +5925,20 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba)
                        spin_unlock_irq(shost->host_lock);
                }
        lpfc_destroy_vport_work_array(phba, vports);
+       if (i == 0 && (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED))) {
+               ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
+               if (ndlp)
+                       lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
+               lpfc_cleanup_pending_mbox(phba->pport);
+               if (phba->sli_rev == LPFC_SLI_REV4)
+                       lpfc_sli4_unreg_all_rpis(phba->pport);
+               lpfc_mbx_unreg_vpi(phba->pport);
+               shost = lpfc_shost_from_vport(phba->pport);
+               spin_lock_irq(shost->host_lock);
+               phba->pport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
+               phba->pport->vpi_state &= ~LPFC_VPI_REGISTERED;
+               spin_unlock_irq(shost->host_lock);
+       }
 
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_all_cmd(phba);
index a7a9fa4..41363db 100644 (file)
@@ -2149,18 +2149,21 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
 
        /* Only FC supports upd bit */
        if ((phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) &&
-           (vport->fc_flag & FC_VFI_REGISTERED)) {
+           (vport->fc_flag & FC_VFI_REGISTERED) &&
+           (!phba->fc_topology_changed)) {
                bf_set(lpfc_reg_vfi_vp, reg_vfi, 0);
                bf_set(lpfc_reg_vfi_upd, reg_vfi, 1);
        }
        lpfc_printf_vlog(vport, KERN_INFO, LOG_MBOX,
                        "3134 Register VFI, mydid:x%x, fcfi:%d, "
-                       " vfi:%d, vpi:%d, fc_pname:%x%x\n",
+                       " vfi:%d, vpi:%d, fc_pname:%x%x fc_flag:x%x"
+                       " port_state:x%x topology chg:%d\n",
                        vport->fc_myDID,
                        phba->fcf.fcfi,
                        phba->sli4_hba.vfi_ids[vport->vfi],
                        phba->vpi_ids[vport->vpi],
-                       reg_vfi->wwn[0], reg_vfi->wwn[1]);
+                       reg_vfi->wwn[0], reg_vfi->wwn[1], vport->fc_flag,
+                       vport->port_state, phba->fc_topology_changed);
 }
 
 /**
index 41e833e..31e9b92 100644 (file)
@@ -332,9 +332,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 
        /* PLOGI chkparm OK */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
-                        "0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
+                        "0114 PLOGI chkparm OK Data: x%x x%x x%x "
+                        "x%x x%x x%x\n",
                         ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
-                        ndlp->nlp_rpi);
+                        ndlp->nlp_rpi, vport->port_state,
+                        vport->fc_flag);
 
        if (vport->cfg_fcp_class == 2 && sp->cls2.classValid)
                ndlp->nlp_fcp_info |= CLASS2;
index 89a3a40..3e02d44 100644 (file)
@@ -2342,7 +2342,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
                /* Mailbox cmd <cmd> Cmpl <cmpl> */
                lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI,
                                "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p "
-                               "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n",
+                               "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x "
+                               "x%x x%x x%x\n",
                                pmb->vport ? pmb->vport->vpi : 0,
                                pmbox->mbxCommand,
                                lpfc_sli_config_mbox_subsys_get(phba, pmb),
@@ -2356,7 +2357,10 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba)
                                pmbox->un.varWords[4],
                                pmbox->un.varWords[5],
                                pmbox->un.varWords[6],
-                               pmbox->un.varWords[7]);
+                               pmbox->un.varWords[7],
+                               pmbox->un.varWords[8],
+                               pmbox->un.varWords[9],
+                               pmbox->un.varWords[10]);
 
                if (pmb->mbox_cmpl)
                        pmb->mbox_cmpl(phba,pmb);