scsi: lpfc: Fix dropped FLOGI during pt2pt discovery recovery
authorJames Smart <jsmart2021@gmail.com>
Mon, 1 Mar 2021 17:18:11 +0000 (09:18 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 4 Mar 2021 22:37:04 +0000 (17:37 -0500)
When connected in pt2pt mode, there is a scenario where the remote port
significantly delays sending a response to our FLOGI, but acts on the FLOGI
it sent us and proceeds to PLOGI/PRLI.  The FLOGI ends up timing out and
kicks off recovery logic. End result is a lot of unnecessary state changes
and lots of discovery messages being logged.

Fix by terminating the FLOGI and noop'ing its completion if we have already
accepted the remote ports FLOGI and are now processing PLOGI.

Link: https://lore.kernel.org/r/20210301171821.3427-13-jsmart2021@gmail.com
Co-developed-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_sli.c

index 6ba5fa08c47a0bb7131a4512ef03048617745a34..431c0d5376d9938fdaaa7bf7f4258c1b6f7c2415 100644 (file)
@@ -782,6 +782,7 @@ struct lpfc_hba {
 #define HBA_NEEDS_CFG_PORT     0x2000000 /* SLI3 - needs a CONFIG_PORT mbox */
 #define HBA_HBEAT_INP          0x4000000 /* mbox HBEAT is in progress */
 #define HBA_HBEAT_TMO          0x8000000 /* HBEAT initiated after timeout */
+#define HBA_FLOGI_OUTSTANDING  0x10000000 /* FLOGI is outstanding */
 
        uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
        struct lpfc_dmabuf slim2p;
index a0aad4896a459d2d150b1322ed7b83203e297f9d..43820ab8a6e8e2a5dde09e0f9d7051843c2848bf 100644 (file)
@@ -103,6 +103,8 @@ int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
 struct lpfc_nodelist *lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did);
 struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *);
 int  lpfc_nlp_put(struct lpfc_nodelist *);
+void lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+                         struct lpfc_iocbq *rspiocb);
 int  lpfc_nlp_not_used(struct lpfc_nodelist *ndlp);
 struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_vport *, uint32_t);
 void lpfc_disc_list_loopmap(struct lpfc_vport *);
index 3bd1482af72ffadb6c20120471644caee16a9f4d..0e92a0b61e7711c9c5c72d7337d8aedb0c89ee17 100644 (file)
@@ -1200,6 +1200,7 @@ flogifail:
                lpfc_issue_clear_la(phba, vport);
        }
 out:
+       phba->hba_flag &= ~HBA_FLOGI_OUTSTANDING;
        lpfc_els_free_iocb(phba, cmdiocb);
        lpfc_nlp_put(ndlp);
 }
@@ -1354,7 +1355,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                return 1;
        }
 
-       phba->hba_flag |= HBA_FLOGI_ISSUED;
+       phba->hba_flag |= (HBA_FLOGI_ISSUED | HBA_FLOGI_OUTSTANDING);
 
        /* Check for a deferred FLOGI ACC condition */
        if (phba->defer_flogi_acc_flag) {
@@ -1425,9 +1426,14 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
                icmd = &iocb->iocb;
                if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
                        ndlp = (struct lpfc_nodelist *)(iocb->context1);
-                       if (ndlp && (ndlp->nlp_DID == Fabric_DID))
+                       if (ndlp && ndlp->nlp_DID == Fabric_DID) {
+                               if ((phba->pport->fc_flag & FC_PT2PT) &&
+                                   !(phba->pport->fc_flag & FC_PT2PT_PLOGI))
+                                       iocb->fabric_iocb_cmpl =
+                                               lpfc_ignore_els_cmpl;
                                lpfc_sli_issue_abort_iotag(phba, pring, iocb,
                                                           NULL);
+                       }
                }
        }
        /* Make sure HBA is alive */
index 4918423960d6301879965b5549286e4b0e0d2c62..57e4aef8a9a317f2eae318c30160241b637567ba 100644 (file)
@@ -523,6 +523,16 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                /* rcv'ed PLOGI decides what our NPortId will be */
                vport->fc_myDID = icmd->un.rcvels.parmRo;
 
+               /* If there is an outstanding FLOGI, abort it now.
+                * The remote NPort is not going to ACC our FLOGI
+                * if its already issuing a PLOGI for pt2pt mode.
+                * This indicates our FLOGI was dropped; however, we
+                * must have ACCed the remote NPorts FLOGI to us
+                * to make it here.
+                */
+               if (phba->hba_flag & HBA_FLOGI_OUTSTANDING)
+                       lpfc_els_abort_flogi(phba);
+
                ed_tov = be32_to_cpu(sp->cmn.e_d_tov);
                if (sp->cmn.edtovResolution) {
                        /* E_D_TOV ticks are in nanoseconds */
index 99307bb7b62cefa472f4bb35ac72b1833fa7e202..56112c9fb6aa3da8ce89d3c85b65422b5e4c315b 100644 (file)
@@ -11591,7 +11591,7 @@ release_iocb:
  * which are aborted. The function frees memory resources used for
  * the aborted ELS commands.
  **/
-static void
+void
 lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                     struct lpfc_iocbq *rspiocb)
 {