]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: qla2xxx: Flush mailbox commands on chip reset
authorQuinn Tran <qutran@marvell.com>
Mon, 21 Aug 2023 13:00:38 +0000 (18:30 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 19 Sep 2023 10:27:55 +0000 (12:27 +0200)
commit 6d0b65569c0a10b27c49bacd8d25bcd406003533 upstream.

Fix race condition between Interrupt thread and Chip reset thread in trying
to flush the same mailbox. With the race condition, the "ha->mbx_intr_comp"
will get an extra complete() call. The extra complete call create erroneous
mailbox timeout condition when the next mailbox is sent where the mailbox
call does not wait for interrupt to arrive. Instead, it advances without
waiting.

Add lock protection around the check for mailbox completion.

Cc: stable@vger.kernel.org
Fixes: b2000805a975 ("scsi: qla2xxx: Flush mailbox commands on chip reset")
Signed-off-by: Quinn Tran <quinn.tran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://lore.kernel.org/r/20230821130045.34850-3-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_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c

index 84929c0e7eb63df3d0c93e55c51e3470faa11c01..eb67059b67375b63fafaebb27834f3b5e7b5fbbc 100644 (file)
@@ -4367,7 +4367,6 @@ struct qla_hw_data {
        uint8_t         aen_mbx_count;
        atomic_t        num_pend_mbx_stage1;
        atomic_t        num_pend_mbx_stage2;
-       atomic_t        num_pend_mbx_stage3;
        uint16_t        frame_payload_size;
 
        uint32_t        login_retry_count;
index 5d2eef8ce0ae2e44355572301f51af281094b123..db5484ef656c04960de4ea6122b5a34740b03ede 100644 (file)
@@ -7444,14 +7444,15 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
        }
 
        /* purge MBox commands */
-       if (atomic_read(&ha->num_pend_mbx_stage3)) {
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) {
                clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
                complete(&ha->mbx_intr_comp);
        }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        i = 0;
-       while (atomic_read(&ha->num_pend_mbx_stage3) ||
-           atomic_read(&ha->num_pend_mbx_stage2) ||
+       while (atomic_read(&ha->num_pend_mbx_stage2) ||
            atomic_read(&ha->num_pend_mbx_stage1)) {
                msleep(20);
                i++;
index 3c2ee21195edb197d6f1bb2dd6cccfff65aa4bc2..f794f4363a38cff2a9a613964b47c92a0b93d37e 100644 (file)
@@ -273,7 +273,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
                wait_time = jiffies;
-               atomic_inc(&ha->num_pend_mbx_stage3);
                if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
                    mcp->tov * HZ)) {
                        ql_dbg(ql_dbg_mbx, vha, 0x117a,
@@ -290,7 +289,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                                spin_unlock_irqrestore(&ha->hardware_lock,
                                    flags);
                                atomic_dec(&ha->num_pend_mbx_stage2);
-                               atomic_dec(&ha->num_pend_mbx_stage3);
                                rval = QLA_ABORTED;
                                goto premature_exit;
                        }
@@ -302,11 +300,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                        ha->flags.mbox_busy = 0;
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
                        atomic_dec(&ha->num_pend_mbx_stage2);
-                       atomic_dec(&ha->num_pend_mbx_stage3);
                        rval = QLA_ABORTED;
                        goto premature_exit;
                }
-               atomic_dec(&ha->num_pend_mbx_stage3);
 
                if (time_after(jiffies, wait_time + 5 * HZ))
                        ql_log(ql_log_warn, vha, 0x1015, "cmd=0x%x, waited %d msecs\n",
index e75e5eddfe1c00518e30d08d500d5647b4bda720..a1b31382c19da6c61cafd644fa88494d38f8a825 100644 (file)
@@ -3000,7 +3000,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->max_exchg = FW_MAX_EXCHANGES_CNT;
        atomic_set(&ha->num_pend_mbx_stage1, 0);
        atomic_set(&ha->num_pend_mbx_stage2, 0);
-       atomic_set(&ha->num_pend_mbx_stage3, 0);
        atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD);
        ha->last_zio_threshold = DEFAULT_ZIO_THRESHOLD;
        INIT_LIST_HEAD(&ha->tmf_pending);