]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: qla2xxx: Fix discovery issues in FC-AL topology
authorArun Easi <aeasi@marvell.com>
Wed, 13 Jul 2022 05:20:42 +0000 (22:20 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Aug 2022 12:24:17 +0000 (14:24 +0200)
commit d23de7c0ffa145d703e3355458596e7edbbe1614 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@cybernetics.com/
Link: https://lore.kernel.org/r/20220713052045.10683-8-njavali@marvell.com
Cc: stable@vger.kernel.org
Reported-by: Tony Battersby <tonyb@cybernetics.com>
Tested-by: Tony Battersby <tonyb@cybernetics.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c

index 2f6afdbd2dfa84c403a9d5a7009802eae0930c11..2a6d613a76cf3b794fd98757b48defe926f8c777 100644 (file)
@@ -433,7 +433,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 *,
index 218eeb439b8435cd803f55708f7bd08ce7883976..de217037aaa74a874a9b0839a9c7d8069a6426d1 100644 (file)
@@ -5510,6 +5510,22 @@ static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha)
        return QLA_FUNCTION_FAILED;
 }
 
+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.
@@ -5561,6 +5577,19 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
                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);
                }
index 5f2594d3d4f9a964c001a31c9fc7afecfaed25f6..96303aefb897bb58853f7e56f65984e760e319fc 100644 (file)
@@ -3062,7 +3062,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
  *     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;
@@ -3102,6 +3103,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
 
                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);