Daniel Wagner ba9ca1
From: Arun Easi <aeasi@marvell.com>
Daniel Wagner ba9ca1
Date: Tue, 12 Jul 2022 22:20:42 -0700
Daniel Wagner ba9ca1
Subject: scsi: qla2xxx: Fix discovery issues in FC-AL topology
Denis Kirjanov 718367
Patch-mainline: v5.20-rc1
Daniel Wagner ba9ca1
Git-commit: 47ccb113cead905bdc236571bf8ac6fed90321b3
Daniel Wagner ba9ca1
References: bsc#1201651
Daniel Wagner ba9ca1
Daniel Wagner ba9ca1
A direct attach tape device, when gets swapped with another, was not
Daniel Wagner ba9ca1
discovered. Fix this by looking at loop map and reinitialize link if there
Daniel Wagner ba9ca1
are devices present.
Daniel Wagner ba9ca1
Daniel Wagner ba9ca1
Link: https://lore.kernel.org/linux-scsi/baef87c3-5dad-3b47-44c1-6914bfc90108@cybernetics.com/
Daniel Wagner ba9ca1
Link: https://lore.kernel.org/r/20220713052045.10683-8-njavali@marvell.com
Daniel Wagner ba9ca1
Cc: stable@vger.kernel.org
Daniel Wagner ba9ca1
Reported-by: Tony Battersby <tonyb@cybernetics.com>
Daniel Wagner ba9ca1
Tested-by: Tony Battersby <tonyb@cybernetics.com>
Daniel Wagner ba9ca1
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Daniel Wagner ba9ca1
Signed-off-by: Arun Easi <aeasi@marvell.com>
Daniel Wagner ba9ca1
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Daniel Wagner ba9ca1
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Daniel Wagner ba9ca1
Acked-by: Daniel Wagner <dwagner@suse.de>
Daniel Wagner ba9ca1
---
Daniel Wagner ba9ca1
 drivers/scsi/qla2xxx/qla_gbl.h  |    3 ++-
Daniel Wagner ba9ca1
 drivers/scsi/qla2xxx/qla_init.c |   29 +++++++++++++++++++++++++++++
Daniel Wagner ba9ca1
 drivers/scsi/qla2xxx/qla_mbx.c  |    5 ++++-
Daniel Wagner ba9ca1
 3 files changed, 35 insertions(+), 2 deletions(-)
Daniel Wagner ba9ca1
Daniel Wagner ba9ca1
--- a/drivers/scsi/qla2xxx/qla_gbl.h
Daniel Wagner ba9ca1
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
Daniel Wagner ba9ca1
@@ -437,7 +437,8 @@ extern int
Daniel Wagner ba9ca1
 qla2x00_get_resource_cnts(scsi_qla_host_t *);
Daniel Wagner ba9ca1
 
Daniel Wagner ba9ca1
 extern int
Daniel Wagner ba9ca1
-qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
Daniel Wagner ba9ca1
+qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map,
Daniel Wagner ba9ca1
+		u8 *num_entries);
Daniel Wagner ba9ca1
 
Daniel Wagner ba9ca1
 extern int
Daniel Wagner ba9ca1
 qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
Daniel Wagner ba9ca1
--- a/drivers/scsi/qla2xxx/qla_init.c
Daniel Wagner ba9ca1
+++ b/drivers/scsi/qla2xxx/qla_init.c
Daniel Wagner ba9ca1
@@ -5495,6 +5495,22 @@ static int qla2x00_configure_n2n_loop(sc
Daniel Wagner ba9ca1
 	return QLA_FUNCTION_FAILED;
Daniel Wagner ba9ca1
 }
Daniel Wagner ba9ca1
 
Daniel Wagner ba9ca1
+static void
Daniel Wagner ba9ca1
+qla_reinitialize_link(scsi_qla_host_t *vha)
Daniel Wagner ba9ca1
+{
Daniel Wagner ba9ca1
+	int rval;
Daniel Wagner ba9ca1
+
Daniel Wagner ba9ca1
+	atomic_set(&vha->loop_state, LOOP_DOWN);
Daniel Wagner ba9ca1
+	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
Daniel Wagner ba9ca1
+	rval = qla2x00_full_login_lip(vha);
Daniel Wagner ba9ca1
+	if (rval == QLA_SUCCESS) {
Daniel Wagner ba9ca1
+		ql_dbg(ql_dbg_disc, vha, 0xd050, "Link reinitialized\n");
Daniel Wagner ba9ca1
+	} else {
Daniel Wagner ba9ca1
+		ql_dbg(ql_dbg_disc, vha, 0xd051,
Daniel Wagner ba9ca1
+			"Link reinitialization failed (%d)\n", rval);
Daniel Wagner ba9ca1
+	}
Daniel Wagner ba9ca1
+}
Daniel Wagner ba9ca1
+
Daniel Wagner ba9ca1
 /*
Daniel Wagner ba9ca1
  * qla2x00_configure_local_loop
Daniel Wagner ba9ca1
  *	Updates Fibre Channel Device Database with local loop devices.
Daniel Wagner ba9ca1
@@ -5546,6 +5562,19 @@ qla2x00_configure_local_loop(scsi_qla_ho
Daniel Wagner ba9ca1
 		spin_unlock_irqrestore(&vha->work_lock, flags);
Daniel Wagner ba9ca1
 
Daniel Wagner ba9ca1
 		if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
Daniel Wagner ba9ca1
+			u8 loop_map_entries = 0;
Daniel Wagner ba9ca1
+			int rc;
Daniel Wagner ba9ca1
+
Daniel Wagner ba9ca1
+			rc = qla2x00_get_fcal_position_map(vha, NULL,
Daniel Wagner ba9ca1
+						&loop_map_entries);
Daniel Wagner ba9ca1
+			if (rc == QLA_SUCCESS && loop_map_entries > 1) {
Daniel Wagner ba9ca1
+				/*
Daniel Wagner ba9ca1
+				 * There are devices that are still not logged
Daniel Wagner ba9ca1
+				 * in. Reinitialize to give them a chance.
Daniel Wagner ba9ca1
+				 */
Daniel Wagner ba9ca1
+				qla_reinitialize_link(vha);
Daniel Wagner ba9ca1
+				return QLA_FUNCTION_FAILED;
Daniel Wagner ba9ca1
+			}
Daniel Wagner ba9ca1
 			set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
Daniel Wagner ba9ca1
 			set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
Daniel Wagner ba9ca1
 		}
Daniel Wagner ba9ca1
--- a/drivers/scsi/qla2xxx/qla_mbx.c
Daniel Wagner ba9ca1
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
Daniel Wagner ba9ca1
@@ -3069,7 +3069,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_
Daniel Wagner ba9ca1
  *	Kernel context.
Daniel Wagner ba9ca1
  */
Daniel Wagner ba9ca1
 int
Daniel Wagner ba9ca1
-qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
Daniel Wagner ba9ca1
+qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map,
Daniel Wagner ba9ca1
+		u8 *num_entries)
Daniel Wagner ba9ca1
 {
Daniel Wagner ba9ca1
 	int rval;
Daniel Wagner ba9ca1
 	mbx_cmd_t mc;
Daniel Wagner ba9ca1
@@ -3109,6 +3110,8 @@ qla2x00_get_fcal_position_map(scsi_qla_h
Daniel Wagner ba9ca1
 
Daniel Wagner ba9ca1
 		if (pos_map)
Daniel Wagner ba9ca1
 			memcpy(pos_map, pmap, FCAL_MAP_SIZE);
Daniel Wagner ba9ca1
+		if (num_entries)
Daniel Wagner ba9ca1
+			*num_entries = pmap[0];
Daniel Wagner ba9ca1
 	}
Daniel Wagner ba9ca1
 	dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
Daniel Wagner ba9ca1