]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
scsi: lpfc: Fix PLOGI failure with high remoteport count
authorJames Smart <jsmart2021@gmail.com>
Wed, 14 Aug 2019 23:56:32 +0000 (16:56 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 20 Aug 2019 02:41:08 +0000 (22:41 -0400)
When connected to a high number of remote ports, the driver is encountering
PLOGI errors.  The errors are due to adapter detected failures indicating
illegal field values.

Turns out the driver was prematurely clearing an RPI bitmask before waiting
for an UNREG_RPI mailbox completion. This allowed the RPI to be reused
before it was actually available.

Fix by clearing RPI bitmask only after UNREG_RPI mailbox completion.

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_disc.h
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_sli.c

index 1c89c9f314fa491c915c3c15c1c20a13ab36b867..49bb0b180b19017ac27193eb254d0fc17db229d0 100644 (file)
@@ -157,6 +157,7 @@ struct lpfc_node_rrq {
 /* Defines for nlp_flag (uint32) */
 #define NLP_IGNR_REG_CMPL  0x00000001 /* Rcvd rscn before we cmpl reg login */
 #define NLP_REG_LOGIN_SEND 0x00000002   /* sent reglogin to adapter */
+#define NLP_RELEASE_RPI    0x00000004   /* Release RPI to free pool */
 #define NLP_SUPPRESS_RSP   0x00000010  /* Remote NPort supports suppress rsp */
 #define NLP_PLOGI_SND      0x00000020  /* sent PLOGI request for this entry */
 #define NLP_PRLI_SND       0x00000040  /* sent PRLI request for this entry */
index cf02c352b324272b753a88b95bad9625cc6e9e31..c413f8c51aa87999ff3cc7bc56fa7cf21ba1b93a 100644 (file)
@@ -4805,6 +4805,10 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                ndlp->nlp_defer_did = NLP_EVT_NOTHING_PENDING;
                lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
        } else {
+               if (ndlp->nlp_flag & NLP_RELEASE_RPI) {
+                       lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi);
+                       ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
+               }
                ndlp->nlp_flag &= ~NLP_UNREG_INP;
        }
 }
@@ -5104,6 +5108,8 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
        list_del_init(&ndlp->els_retry_evt.evt_listp);
        list_del_init(&ndlp->dev_loss_evt.evt_listp);
        lpfc_cleanup_vports_rrqs(vport, ndlp);
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               ndlp->nlp_flag |= NLP_RELEASE_RPI;
        lpfc_unreg_rpi(vport, ndlp);
 
        return 0;
@@ -6201,8 +6207,6 @@ lpfc_nlp_release(struct kref *kref)
        spin_lock_irqsave(&phba->ndlp_lock, flags);
        NLP_CLR_NODE_ACT(ndlp);
        spin_unlock_irqrestore(&phba->ndlp_lock, flags);
-       if (phba->sli_rev == LPFC_SLI_REV4)
-               lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
 
        /* free ndlp memory for final ndlp release */
        if (NLP_CHK_FREE_REQ(ndlp)) {
index 156224c14cc7df7d5cb1f7fe36e84ae26f365709..bb41affdb1ba1205de5389c81a8ca61f55907c54 100644 (file)
@@ -2507,6 +2507,11 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                ndlp->nlp_defer_did = NLP_EVT_NOTHING_PENDING;
                                lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
                        } else {
+                               if (ndlp->nlp_flag & NLP_RELEASE_RPI) {
+                                       lpfc_sli4_free_rpi(vport->phba,
+                                                          ndlp->nlp_rpi);
+                                       ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
+                               }
                                ndlp->nlp_flag &= ~NLP_UNREG_INP;
                        }
                        pmb->ctx_ndlp = NULL;
@@ -2582,6 +2587,13 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                                        lpfc_issue_els_plogi(
                                                vport, ndlp->nlp_DID, 0);
                                } else {
+                                       if (ndlp->nlp_flag & NLP_RELEASE_RPI) {
+                                               lpfc_sli4_free_rpi(
+                                                       vport->phba,
+                                                       ndlp->nlp_rpi);
+                                               ndlp->nlp_flag &=
+                                                       ~NLP_RELEASE_RPI;
+                                       }
                                        ndlp->nlp_flag &= ~NLP_UNREG_INP;
                                }
                        }