scsi: lpfc: Make fabric zone discovery more robust when handling unsolicited LOGO
authorJustin Tee <justin.tee@broadcom.com>
Wed, 12 Jul 2023 18:05:17 +0000 (11:05 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sun, 23 Jul 2023 20:17:07 +0000 (16:17 -0400)
This patch provides better target rport recovery when a target rport is
running in initiator mode to discover the fabric.  Such a target will issue
a LOGO before switching back to strict target mode and changes are made to
recover the login.  Log messages are also updated accordingly.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20230712180522.112722-8-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_nportdisc.c

index 474834f..baae1f8 100644 (file)
@@ -1557,7 +1557,8 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                ndlp->nlp_fc4_type |= NLP_FC4_FCP;
                        if (fc4_data_1 &  LPFC_FC4_TYPE_BITMASK)
                                ndlp->nlp_fc4_type |= NLP_FC4_NVME;
-                       lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                       lpfc_printf_vlog(vport, KERN_INFO,
+                                        LOG_DISCOVERY | LOG_NODE,
                                         "3064 Setting ndlp x%px, DID x%06x "
                                         "with FC4 x%08x, Data: x%08x x%08x "
                                         "%d\n",
@@ -1568,14 +1569,21 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE &&
                            ndlp->nlp_fc4_type) {
                                ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
-
-                               lpfc_nlp_set_state(vport, ndlp,
-                                                  NLP_STE_PRLI_ISSUE);
-                               lpfc_issue_els_prli(vport, ndlp, 0);
+                               /* This is a fabric topology so if discovery
+                                * started with an unsolicited PLOGI, don't
+                                * send a PRLI.  Targets don't issue PLOGI or
+                                * PRLI when acting as a target. Likely this is
+                                * an initiator function.
+                                */
+                               if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) {
+                                       lpfc_nlp_set_state(vport, ndlp,
+                                                          NLP_STE_PRLI_ISSUE);
+                                       lpfc_issue_els_prli(vport, ndlp, 0);
+                               }
                        } else if (!ndlp->nlp_fc4_type) {
                                /* If fc4 type is still unknown, then LOGO */
                                lpfc_printf_vlog(vport, KERN_INFO,
-                                                LOG_DISCOVERY,
+                                                LOG_DISCOVERY | LOG_NODE,
                                                 "6443 Sending LOGO ndlp x%px,"
                                                 "DID x%06x with fc4_type: "
                                                 "x%08x, state: %d\n",
index aa48153..f377574 100644 (file)
@@ -2376,10 +2376,10 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                /* PRLI failed */
                lpfc_printf_vlog(vport, mode, loglevel,
                                 "2754 PRLI failure DID:%06X Status:x%x/x%x, "
-                                "data: x%x x%x\n",
+                                "data: x%x x%x x%x\n",
                                 ndlp->nlp_DID, ulp_status,
                                 ulp_word4, ndlp->nlp_state,
-                                ndlp->fc4_prli_sent);
+                                ndlp->fc4_prli_sent, ndlp->nlp_flag);
 
                /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
                if (!lpfc_error_lost_link(vport, ulp_status, ulp_word4))
@@ -2390,14 +2390,16 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                 * mismatch typically caused by an RSCN. Skip any
                 * processing to allow recovery.
                 */
-               if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE &&
-                   ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) {
+               if ((ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE &&
+                    ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) ||
+                   (ndlp->nlp_state == NLP_STE_NPR_NODE &&
+                    ndlp->nlp_flag & NLP_DELAY_TMO)) {
                        lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
-                                        "2784 PRLI cmpl: state mismatch "
+                                        "2784 PRLI cmpl: Allow Node recovery "
                                         "DID x%06x nstate x%x nflag x%x\n",
                                         ndlp->nlp_DID, ndlp->nlp_state,
                                         ndlp->nlp_flag);
-                               goto out;
+                       goto out;
                }
 
                /*
index 6261560..8f64244 100644 (file)
@@ -879,23 +879,34 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        spin_unlock_irq(shost->host_lock);
                        lpfc_retry_pport_discovery(phba);
                }
-       } else if ((!(ndlp->nlp_type & NLP_FABRIC) &&
-               ((ndlp->nlp_type & NLP_FCP_TARGET) ||
-               (ndlp->nlp_type & NLP_NVME_TARGET) ||
-               (vport->fc_flag & FC_PT2PT))) ||
-               (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
-               /* Only try to re-login if this is NOT a Fabric Node
-                * AND the remote NPORT is a FCP/NVME Target or we
-                * are in pt2pt mode. NLP_STE_ADISC_ISSUE is a special
-                * case for LOGO as a response to ADISC behavior.
-                */
-               mod_timer(&ndlp->nlp_delayfunc,
-                         jiffies + msecs_to_jiffies(1000 * 1));
-               spin_lock_irq(&ndlp->lock);
-               ndlp->nlp_flag |= NLP_DELAY_TMO;
-               spin_unlock_irq(&ndlp->lock);
-
-               ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
+       } else {
+               lpfc_printf_vlog(vport, KERN_INFO,
+                                LOG_NODE | LOG_ELS | LOG_DISCOVERY,
+                                "3203 LOGO recover nport x%06x state x%x "
+                                "ntype x%x fc_flag x%x\n",
+                                ndlp->nlp_DID, ndlp->nlp_state,
+                                ndlp->nlp_type, vport->fc_flag);
+
+               /* Special cases for rports that recover post LOGO. */
+               if ((!(ndlp->nlp_type == NLP_FABRIC) &&
+                    (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET) ||
+                     vport->fc_flag & FC_PT2PT)) ||
+                   (ndlp->nlp_state >= NLP_STE_ADISC_ISSUE ||
+                    ndlp->nlp_state <= NLP_STE_PRLI_ISSUE)) {
+                       mod_timer(&ndlp->nlp_delayfunc,
+                                 jiffies + msecs_to_jiffies(1000 * 1));
+                       spin_lock_irq(&ndlp->lock);
+                       ndlp->nlp_flag |= NLP_DELAY_TMO;
+                       spin_unlock_irq(&ndlp->lock);
+                       ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
+                       lpfc_printf_vlog(vport, KERN_INFO,
+                                        LOG_NODE | LOG_ELS | LOG_DISCOVERY,
+                                        "3204 Start nlpdelay on DID x%06x "
+                                        "nflag x%x lastels x%x ref cnt %u",
+                                        ndlp->nlp_DID, ndlp->nlp_flag,
+                                        ndlp->nlp_last_elscmd,
+                                        kref_read(&ndlp->kref));
+               }
        }
 out:
        /* Unregister from backend, could have been skipped due to ADISC */
@@ -1854,7 +1865,6 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
        struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
        LPFC_MBOXQ_t      *mb;
        LPFC_MBOXQ_t      *nextmb;
-       struct lpfc_nodelist *ns_ndlp;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
@@ -1882,13 +1892,6 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
        }
        spin_unlock_irq(&phba->hbalock);
 
-       /* software abort if any GID_FT is outstanding */
-       if (vport->cfg_enable_fc4_type != LPFC_ENABLE_FCP) {
-               ns_ndlp = lpfc_findnode_did(vport, NameServer_DID);
-               if (ns_ndlp)
-                       lpfc_els_abort(phba, ns_ndlp);
-       }
-
        lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }