Daniel Wagner 39e524
From: Arun Easi <aeasi@marvell.com>
Daniel Wagner 39e524
Date: Wed, 15 Jun 2022 22:35:04 -0700
Daniel Wagner 39e524
Subject: scsi: qla2xxx: Fix losing target when it reappears during delete
Denis Kirjanov 718367
Patch-mainline: v5.20-rc1
Daniel Wagner 39e524
Git-commit: 118b0c863c8f5629cc5271fc24d72d926e0715d9
Daniel Wagner 39e524
References: bsc#1201958
Daniel Wagner 39e524
Daniel Wagner 39e524
FC target disappeared during port perturbation tests due to a race that
Daniel Wagner 39e524
tramples target state.  Fix the issue by adding state checks before
Daniel Wagner 39e524
proceeding.
Daniel Wagner 39e524
Daniel Wagner 39e524
Link: https://lore.kernel.org/r/20220616053508.27186-8-njavali@marvell.com
Daniel Wagner 39e524
Fixes: 44c57f205876 ("scsi: qla2xxx: Changes to support FCP2 Target")
Daniel Wagner 39e524
Cc: stable@vger.kernel.org
Daniel Wagner 39e524
Signed-off-by: Arun Easi <aeasi@marvell.com>
Daniel Wagner 39e524
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Daniel Wagner 39e524
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Daniel Wagner 39e524
Acked-by: Daniel Wagner <dwagner@suse.de>
Daniel Wagner 39e524
---
Daniel Wagner 39e524
 drivers/scsi/qla2xxx/qla_attr.c |   24 +++++++++++++++++-------
Daniel Wagner 39e524
 1 file changed, 17 insertions(+), 7 deletions(-)
Daniel Wagner 39e524
Daniel Wagner 39e524
--- a/drivers/scsi/qla2xxx/qla_attr.c
Daniel Wagner 39e524
+++ b/drivers/scsi/qla2xxx/qla_attr.c
Daniel Wagner 39e524
@@ -2710,17 +2710,24 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rp
Daniel Wagner 39e524
 	if (!fcport)
Daniel Wagner 39e524
 		return;
Daniel Wagner 39e524
 
Daniel Wagner 39e524
-	/* Now that the rport has been deleted, set the fcport state to
Daniel Wagner 39e524
-	   FCS_DEVICE_DEAD */
Daniel Wagner 39e524
-	qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD);
Daniel Wagner 39e524
+
Daniel Wagner 39e524
+	/*
Daniel Wagner 39e524
+	 * Now that the rport has been deleted, set the fcport state to
Daniel Wagner 39e524
+	 * FCS_DEVICE_DEAD, if the fcport is still lost.
Daniel Wagner 39e524
+	 */
Daniel Wagner 39e524
+	if (fcport->scan_state != QLA_FCPORT_FOUND)
Daniel Wagner 39e524
+		qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD);
Daniel Wagner 39e524
 
Daniel Wagner 39e524
 	/*
Daniel Wagner 39e524
 	 * Transport has effectively 'deleted' the rport, clear
Daniel Wagner 39e524
 	 * all local references.
Daniel Wagner 39e524
 	 */
Daniel Wagner 39e524
 	spin_lock_irqsave(host->host_lock, flags);
Daniel Wagner 39e524
-	fcport->rport = fcport->drport = NULL;
Daniel Wagner 39e524
-	*((fc_port_t **)rport->dd_data) = NULL;
Daniel Wagner 39e524
+	/* Confirm port has not reappeared before clearing pointers. */
Daniel Wagner 39e524
+	if (rport->port_state != FC_PORTSTATE_ONLINE) {
Daniel Wagner 39e524
+		fcport->rport = fcport->drport = NULL;
Daniel Wagner 39e524
+		*((fc_port_t **)rport->dd_data) = NULL;
Daniel Wagner 39e524
+	}
Daniel Wagner 39e524
 	spin_unlock_irqrestore(host->host_lock, flags);
Daniel Wagner 39e524
 
Daniel Wagner 39e524
 	if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
Daniel Wagner 39e524
@@ -2753,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rpo
Daniel Wagner 39e524
 	/*
Daniel Wagner 39e524
 	 * At this point all fcport's software-states are cleared.  Perform any
Daniel Wagner 39e524
 	 * final cleanup of firmware resources (PCBs and XCBs).
Daniel Wagner 39e524
+	 *
Daniel Wagner 39e524
+	 * Attempt to cleanup only lost devices.
Daniel Wagner 39e524
 	 */
Daniel Wagner 39e524
 	if (fcport->loop_id != FC_NO_LOOP_ID) {
Daniel Wagner 39e524
-		if (IS_FWI2_CAPABLE(fcport->vha->hw)) {
Daniel Wagner 39e524
+		if (IS_FWI2_CAPABLE(fcport->vha->hw) &&
Daniel Wagner 39e524
+		    fcport->scan_state != QLA_FCPORT_FOUND) {
Daniel Wagner 39e524
 			if (fcport->loop_id != FC_NO_LOOP_ID)
Daniel Wagner 39e524
 				fcport->logout_on_delete = 1;
Daniel Wagner 39e524
 
Daniel Wagner 39e524
@@ -2765,7 +2775,7 @@ qla2x00_terminate_rport_io(struct fc_rpo
Daniel Wagner 39e524
 				       __LINE__);
Daniel Wagner 39e524
 				qlt_schedule_sess_for_deletion(fcport);
Daniel Wagner 39e524
 			}
Daniel Wagner 39e524
-		} else {
Daniel Wagner 39e524
+		} else if (!IS_FWI2_CAPABLE(fcport->vha->hw)) {
Daniel Wagner 39e524
 			qla2x00_port_logout(fcport->vha, fcport);
Daniel Wagner 39e524
 		}
Daniel Wagner 39e524
 	}