Daniel Wagner 27ff64
From: James Smart <jsmart2021@gmail.com>
Daniel Wagner 27ff64
Date: Fri, 14 May 2021 12:55:53 -0700
Daniel Wagner 27ff64
Subject: scsi: lpfc: Fix Node recovery when driver is handling simultaneous
Daniel Wagner 27ff64
 PLOGIs
Michal Kubecek 9a3a83
Patch-mainline: v5.14-rc1
Daniel Wagner 27ff64
Git-commit: 4012baeab6ca22b7f7beb121b6d0da0a62942fdd
Daniel Wagner 27ff64
References: bsc#1186451
Daniel Wagner 27ff64
Daniel Wagner 27ff64
When lpfc is handling a solicited and unsolicited PLOGI with another
Daniel Wagner 27ff64
initiator, the remote initiator is never recovered. The node for the
Daniel Wagner 27ff64
initiator is erroneouosly removed and all resources released.
Daniel Wagner 27ff64
Daniel Wagner 27ff64
In lpfc_cmpl_els_plogi(), when lpfc_els_retry() returns a failure code, the
Daniel Wagner 27ff64
driver is calling the state machine with a device remove event because the
Daniel Wagner 27ff64
remote port is not currently registered with the SCSI or NVMe
Daniel Wagner 27ff64
transports. The issue is that on a PLOGI "collision" the driver correctly
Daniel Wagner 27ff64
aborts the solicited PLOGI and allows the unsolicited PLOGI to complete the
Daniel Wagner 27ff64
process, but this process is interrupted with a device_rm event.
Daniel Wagner 27ff64
Daniel Wagner 27ff64
Introduce logic in the PLOGI completion to capture the PLOGI collision
Daniel Wagner 27ff64
event and jump out of the routine.  This will avoid removal of the node.
Daniel Wagner 27ff64
If there is no collision, the normal node removal will occur.
Daniel Wagner 27ff64
Daniel Wagner 27ff64
Fixes: 	52edb2caf675 ("scsi: lpfc: Remove ndlp when a PLOGI/ADISC/PRLI/REG_RPI ultimately fails")
Daniel Wagner 27ff64
Cc: <stable@vger.kernel.org> # v5.11+
Daniel Wagner 27ff64
Link: https://lore.kernel.org/r/20210514195559.119853-6-jsmart2021@gmail.com
Daniel Wagner 27ff64
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Daniel Wagner 27ff64
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Daniel Wagner 27ff64
Signed-off-by: James Smart <jsmart2021@gmail.com>
Daniel Wagner 27ff64
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Daniel Wagner 27ff64
Acked-by: Daniel Wagner <dwagner@suse.de>
Daniel Wagner 27ff64
---
Daniel Wagner 27ff64
 drivers/scsi/lpfc/lpfc_els.c |   21 ++++++++++++++++++---
Daniel Wagner 27ff64
 1 file changed, 18 insertions(+), 3 deletions(-)
Daniel Wagner 27ff64
Daniel Wagner 27ff64
--- a/drivers/scsi/lpfc/lpfc_els.c
Daniel Wagner 27ff64
+++ b/drivers/scsi/lpfc/lpfc_els.c
Daniel Wagner 27ff64
@@ -2007,9 +2007,20 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phb
Daniel Wagner 27ff64
 			lpfc_disc_state_machine(vport, ndlp, cmdiocb,
Daniel Wagner 27ff64
 						NLP_EVT_CMPL_PLOGI);
Daniel Wagner 27ff64
 
Daniel Wagner 27ff64
-		/* As long as this node is not registered with the scsi or nvme
Daniel Wagner 27ff64
-		 * transport, it is no longer an active node.  Otherwise
Daniel Wagner 27ff64
-		 * devloss handles the final cleanup.
Daniel Wagner 27ff64
+		/* If a PLOGI collision occurred, the node needs to continue
Daniel Wagner 27ff64
+		 * with the reglogin process.
Daniel Wagner 27ff64
+		 */
Daniel Wagner 27ff64
+		spin_lock_irq(&ndlp->lock);
Daniel Wagner 27ff64
+		if ((ndlp->nlp_flag & (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI)) &&
Daniel Wagner 27ff64
+		    ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE) {
Daniel Wagner 27ff64
+			spin_unlock_irq(&ndlp->lock);
Daniel Wagner 27ff64
+			goto out;
Daniel Wagner 27ff64
+		}
Daniel Wagner 27ff64
+		spin_unlock_irq(&ndlp->lock);
Daniel Wagner 27ff64
+
Daniel Wagner 27ff64
+		/* No PLOGI collision and the node is not registered with the
Daniel Wagner 27ff64
+		 * scsi or nvme transport. It is no longer an active node. Just
Daniel Wagner 27ff64
+		 * start the device remove process.
Daniel Wagner 27ff64
 		 */
Daniel Wagner 27ff64
 		if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) {
Daniel Wagner 27ff64
 			spin_lock_irq(&ndlp->lock);
Daniel Wagner 27ff64
@@ -4629,6 +4640,10 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba,
Daniel Wagner 27ff64
 	    (vport && vport->port_type == LPFC_NPIV_PORT) &&
Daniel Wagner 27ff64
 	    ndlp->nlp_flag & NLP_RELEASE_RPI) {
Daniel Wagner 27ff64
 		lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
Daniel Wagner 27ff64
+		spin_lock_irq(&ndlp->lock);
Daniel Wagner 27ff64
+		ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
Daniel Wagner 27ff64
+		ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
Daniel Wagner 27ff64
+		spin_unlock_irq(&ndlp->lock);
Daniel Wagner 27ff64
 		lpfc_drop_node(vport, ndlp);
Daniel Wagner 27ff64
 	}
Daniel Wagner 27ff64