scsi: qla2xxx: set UNLOADING before waiting for session deletion
authorMartin Wilck <mwilck@suse.com>
Tue, 21 Apr 2020 20:46:20 +0000 (22:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 6 May 2020 06:15:11 +0000 (08:15 +0200)
commit 856e152a3c08bf7987cbd41900741d83d9cddc8e upstream.

The purpose of the UNLOADING flag is to avoid port login procedures to
continue when a controller is in the process of shutting down.  It makes
sense to set this flag before starting session teardown.

Furthermore, use atomic test_and_set_bit() to avoid the shutdown being run
multiple times in parallel. In qla2x00_disable_board_on_pci_error(), the
test for UNLOADING is postponed until after the check for an already
disabled PCI board.

Link: https://lore.kernel.org/r/20200421204621.19228-2-mwilck@suse.com
Fixes: 45235022da99 ("scsi: qla2xxx: Fix driver unload by shutting down chip")
Reviewed-by: Arun Easi <aeasi@marvell.com>
Reviewed-by: Daniel Wagner <dwagner@suse.de>
Reviewed-by: Roman Bolshakov <r.bolshakov@yadro.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/qla2xxx/qla_os.c

index 06037e3..7c588c5 100644 (file)
@@ -3700,6 +3700,13 @@ qla2x00_remove_one(struct pci_dev *pdev)
        }
        qla2x00_wait_for_hba_ready(base_vha);
 
+       /*
+        * if UNLOADING flag is already set, then continue unload,
+        * where it was set first.
+        */
+       if (test_and_set_bit(UNLOADING, &base_vha->dpc_flags))
+               return;
+
        if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
            IS_QLA28XX(ha)) {
                if (ha->flags.fw_started)
@@ -3718,15 +3725,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
 
        qla2x00_wait_for_sess_deletion(base_vha);
 
-       /*
-        * if UNLOAD flag is already set, then continue unload,
-        * where it was set first.
-        */
-       if (test_bit(UNLOADING, &base_vha->dpc_flags))
-               return;
-
-       set_bit(UNLOADING, &base_vha->dpc_flags);
-
        qla_nvme_delete(base_vha);
 
        dma_free_coherent(&ha->pdev->dev,
@@ -6053,13 +6051,6 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
        struct pci_dev *pdev = ha->pdev;
        scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 
-       /*
-        * if UNLOAD flag is already set, then continue unload,
-        * where it was set first.
-        */
-       if (test_bit(UNLOADING, &base_vha->dpc_flags))
-               return;
-
        ql_log(ql_log_warn, base_vha, 0x015b,
            "Disabling adapter.\n");
 
@@ -6070,9 +6061,14 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
                return;
        }
 
-       qla2x00_wait_for_sess_deletion(base_vha);
+       /*
+        * if UNLOADING flag is already set, then continue unload,
+        * where it was set first.
+        */
+       if (test_and_set_bit(UNLOADING, &base_vha->dpc_flags))
+               return;
 
-       set_bit(UNLOADING, &base_vha->dpc_flags);
+       qla2x00_wait_for_sess_deletion(base_vha);
 
        qla2x00_delete_all_vps(ha, base_vha);