[02/42] lpfc: Fix PLOGI failure with high remoteport count
diff mbox series

Message ID 20190814235712.4487-3-jsmart2021@gmail.com
State Accepted
Headers show
Series
  • lpfc: Update lpfc to revision 12.4.0.0
Related show

Commit Message

James Smart Aug. 14, 2019, 11:56 p.m. UTC
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>
---
 drivers/scsi/lpfc/lpfc_disc.h    |  1 +
 drivers/scsi/lpfc/lpfc_hbadisc.c |  8 ++++++--
 drivers/scsi/lpfc/lpfc_sli.c     | 12 ++++++++++++
 3 files changed, 19 insertions(+), 2 deletions(-)

Patch
diff mbox series

diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 1c89c9f314fa..49bb0b180b19 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -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 */
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 28ecaa7fc715..6360683417b8 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -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;
@@ -6200,8 +6206,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)) {
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index f9e6a135d656..504f56a99b20 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -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;
 				}
 			}