[PATCH 5.4 249/389] scsi: qla2xxx: Fix discovery issues in FC-AL topology

From: Greg Kroah-Hartman
Date: Tue Aug 23 2022 - 07:43:06 EST


From: Arun Easi <aeasi@xxxxxxxxxxx>

commit 47ccb113cead905bdc236571bf8ac6fed90321b3 upstream.

A direct attach tape device, when gets swapped with another, was not
discovered. Fix this by looking at loop map and reinitialize link if there
are devices present.

Link: https://lore.kernel.org/linux-scsi/baef87c3-5dad-3b47-44c1-6914bfc90108@xxxxxxxxxxxxxxx/
Link: https://lore.kernel.org/r/20220713052045.10683-8-njavali@xxxxxxxxxxx
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Tony Battersby <tonyb@xxxxxxxxxxxxxxx>
Tested-by: Tony Battersby <tonyb@xxxxxxxxxxxxxxx>
Reviewed-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx>
Signed-off-by: Arun Easi <aeasi@xxxxxxxxxxx>
Signed-off-by: Nilesh Javali <njavali@xxxxxxxxxxx>
Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/scsi/qla2xxx/qla_gbl.h | 3 ++-
drivers/scsi/qla2xxx/qla_init.c | 29 +++++++++++++++++++++++++++++
drivers/scsi/qla2xxx/qla_mbx.c | 5 ++++-
3 files changed, 35 insertions(+), 2 deletions(-)

--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -397,7 +397,8 @@ extern int
qla2x00_get_resource_cnts(scsi_qla_host_t *);

extern int
-qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
+qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map,
+ u8 *num_entries);

extern int
qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -5068,6 +5068,22 @@ qla2x00_configure_loop(scsi_qla_host_t *
return (rval);
}

+static void
+qla_reinitialize_link(scsi_qla_host_t *vha)
+{
+ int rval;
+
+ atomic_set(&vha->loop_state, LOOP_DOWN);
+ atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
+ rval = qla2x00_full_login_lip(vha);
+ if (rval == QLA_SUCCESS) {
+ ql_dbg(ql_dbg_disc, vha, 0xd050, "Link reinitialized\n");
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0xd051,
+ "Link reinitialization failed (%d)\n", rval);
+ }
+}
+
/*
* qla2x00_configure_local_loop
* Updates Fibre Channel Device Database with local loop devices.
@@ -5132,6 +5148,19 @@ skip_login:
spin_unlock_irqrestore(&vha->work_lock, flags);

if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
+ u8 loop_map_entries = 0;
+ int rc;
+
+ rc = qla2x00_get_fcal_position_map(vha, NULL,
+ &loop_map_entries);
+ if (rc == QLA_SUCCESS && loop_map_entries > 1) {
+ /*
+ * There are devices that are still not logged
+ * in. Reinitialize to give them a chance.
+ */
+ qla_reinitialize_link(vha);
+ return QLA_FUNCTION_FAILED;
+ }
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
}
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2928,7 +2928,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_
* Kernel context.
*/
int
-qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
+qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map,
+ u8 *num_entries)
{
int rval;
mbx_cmd_t mc;
@@ -2968,6 +2969,8 @@ qla2x00_get_fcal_position_map(scsi_qla_h

if (pos_map)
memcpy(pos_map, pmap, FCAL_MAP_SIZE);
+ if (num_entries)
+ *num_entries = pmap[0];
}
dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);