]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: qla2xxx: Wait for io return on terminate rport
authorQuinn Tran <qutran@marvell.com>
Fri, 28 Apr 2023 07:53:38 +0000 (00:53 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 23 Jul 2023 11:49:48 +0000 (13:49 +0200)
commit fc0cba0c7be8261a1625098bd1d695077ec621c9 upstream.

System crash due to use after free.
Current code allows terminate_rport_io to exit before making
sure all IOs has returned. For FCP-2 device, IO's can hang
on in HW because driver has not tear down the session in FW at
first sign of cable pull. When dev_loss_tmo timer pops,
terminate_rport_io is called and upper layer is about to
free various resources. Terminate_rport_io trigger qla to do
the final cleanup, but the cleanup might not be fast enough where it
leave qla still holding on to the same resource.

Wait for IO's to return to upper layer before resources are freed.

Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230428075339.32551-7-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/qla2xxx/qla_attr.c

index b67ad30d56e6f6dd888a20640cb091387c83db32..64734d6e8ccb135cb6b8ab33914579f8a77d484c 100644 (file)
@@ -2750,6 +2750,7 @@ static void
 qla2x00_terminate_rport_io(struct fc_rport *rport)
 {
        fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+       scsi_qla_host_t *vha;
 
        if (!fcport)
                return;
@@ -2759,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
 
        if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
                return;
+       vha = fcport->vha;
 
        if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
                qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
+               qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
+                       0, WAIT_TARGET);
                return;
        }
        /*
@@ -2786,6 +2790,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
                        qla2x00_port_logout(fcport->vha, fcport);
                }
        }
+
+       /* check for any straggling io left behind */
+       if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) {
+               ql_log(ql_log_warn, vha, 0x300b,
+                      "IO not return.  Resetting. \n");
+               set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+               qla2xxx_wake_dpc(vha);
+               qla2x00_wait_for_chip_reset(vha);
+       }
 }
 
 static int