| From 993a99cb607ffa3155bddc53b6a79c6979186002 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 4 Sep 2018 14:19:10 -0700 |
| Subject: scsi: qla2xxx: Fix deadlock between ATIO and HW lock |
| |
| From: Quinn Tran <quinn.tran@cavium.com> |
| |
| [ Upstream commit 1073daa470d906f1853ed4b828f16e2350a5875c ] |
| |
| Move ATIO queue processing out of hardware_lock to prevent deadlock. |
| |
| Fixes: 3bb67df5b5f8 ("qla2xxx: Check for online flag instead of active reset when transmitting responses") |
| Signed-off-by: Quinn Tran <quinn.tran@cavium.com> |
| Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/scsi/qla2xxx/qla_init.c | 17 +++--------- |
| drivers/scsi/qla2xxx/qla_isr.c | 48 +++++++++++++++------------------ |
| 2 files changed, 26 insertions(+), 39 deletions(-) |
| |
| diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c |
| index e5ecef94aebdb..733a55c09b1ca 100644 |
| --- a/drivers/scsi/qla2xxx/qla_init.c |
| +++ b/drivers/scsi/qla2xxx/qla_init.c |
| @@ -4869,19 +4869,10 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) |
| */ |
| if (qla_tgt_mode_enabled(vha) || |
| qla_dual_mode_enabled(vha)) { |
| - if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) { |
| - spin_lock_irqsave(&ha->tgt.atio_lock, |
| - flags); |
| - qlt_24xx_process_atio_queue(vha, 0); |
| - spin_unlock_irqrestore( |
| - &ha->tgt.atio_lock, flags); |
| - } else { |
| - spin_lock_irqsave(&ha->hardware_lock, |
| - flags); |
| - qlt_24xx_process_atio_queue(vha, 1); |
| - spin_unlock_irqrestore( |
| - &ha->hardware_lock, flags); |
| - } |
| + spin_lock_irqsave(&ha->tgt.atio_lock, flags); |
| + qlt_24xx_process_atio_queue(vha, 0); |
| + spin_unlock_irqrestore(&ha->tgt.atio_lock, |
| + flags); |
| } |
| } |
| } |
| diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c |
| index 88d8acf86a2a4..f559beda8d5ad 100644 |
| --- a/drivers/scsi/qla2xxx/qla_isr.c |
| +++ b/drivers/scsi/qla2xxx/qla_isr.c |
| @@ -3121,6 +3121,7 @@ qla24xx_intr_handler(int irq, void *dev_id) |
| uint16_t mb[8]; |
| struct rsp_que *rsp; |
| unsigned long flags; |
| + bool process_atio = false; |
| |
| rsp = (struct rsp_que *) dev_id; |
| if (!rsp) { |
| @@ -3181,22 +3182,13 @@ qla24xx_intr_handler(int irq, void *dev_id) |
| qla24xx_process_response_queue(vha, rsp); |
| break; |
| case INTR_ATIO_QUE_UPDATE_27XX: |
| - case INTR_ATIO_QUE_UPDATE:{ |
| - unsigned long flags2; |
| - spin_lock_irqsave(&ha->tgt.atio_lock, flags2); |
| - qlt_24xx_process_atio_queue(vha, 1); |
| - spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2); |
| + case INTR_ATIO_QUE_UPDATE: |
| + process_atio = true; |
| break; |
| - } |
| - case INTR_ATIO_RSP_QUE_UPDATE: { |
| - unsigned long flags2; |
| - spin_lock_irqsave(&ha->tgt.atio_lock, flags2); |
| - qlt_24xx_process_atio_queue(vha, 1); |
| - spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2); |
| - |
| + case INTR_ATIO_RSP_QUE_UPDATE: |
| + process_atio = true; |
| qla24xx_process_response_queue(vha, rsp); |
| break; |
| - } |
| default: |
| ql_dbg(ql_dbg_async, vha, 0x504f, |
| "Unrecognized interrupt type (%d).\n", stat * 0xff); |
| @@ -3210,6 +3202,12 @@ qla24xx_intr_handler(int irq, void *dev_id) |
| qla2x00_handle_mbx_completion(ha, status); |
| spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| |
| + if (process_atio) { |
| + spin_lock_irqsave(&ha->tgt.atio_lock, flags); |
| + qlt_24xx_process_atio_queue(vha, 0); |
| + spin_unlock_irqrestore(&ha->tgt.atio_lock, flags); |
| + } |
| + |
| return IRQ_HANDLED; |
| } |
| |
| @@ -3256,6 +3254,7 @@ qla24xx_msix_default(int irq, void *dev_id) |
| uint32_t hccr; |
| uint16_t mb[8]; |
| unsigned long flags; |
| + bool process_atio = false; |
| |
| rsp = (struct rsp_que *) dev_id; |
| if (!rsp) { |
| @@ -3312,22 +3311,13 @@ qla24xx_msix_default(int irq, void *dev_id) |
| qla24xx_process_response_queue(vha, rsp); |
| break; |
| case INTR_ATIO_QUE_UPDATE_27XX: |
| - case INTR_ATIO_QUE_UPDATE:{ |
| - unsigned long flags2; |
| - spin_lock_irqsave(&ha->tgt.atio_lock, flags2); |
| - qlt_24xx_process_atio_queue(vha, 1); |
| - spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2); |
| + case INTR_ATIO_QUE_UPDATE: |
| + process_atio = true; |
| break; |
| - } |
| - case INTR_ATIO_RSP_QUE_UPDATE: { |
| - unsigned long flags2; |
| - spin_lock_irqsave(&ha->tgt.atio_lock, flags2); |
| - qlt_24xx_process_atio_queue(vha, 1); |
| - spin_unlock_irqrestore(&ha->tgt.atio_lock, flags2); |
| - |
| + case INTR_ATIO_RSP_QUE_UPDATE: |
| + process_atio = true; |
| qla24xx_process_response_queue(vha, rsp); |
| break; |
| - } |
| default: |
| ql_dbg(ql_dbg_async, vha, 0x5051, |
| "Unrecognized interrupt type (%d).\n", stat & 0xff); |
| @@ -3338,6 +3328,12 @@ qla24xx_msix_default(int irq, void *dev_id) |
| qla2x00_handle_mbx_completion(ha, status); |
| spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| |
| + if (process_atio) { |
| + spin_lock_irqsave(&ha->tgt.atio_lock, flags); |
| + qlt_24xx_process_atio_queue(vha, 0); |
| + spin_unlock_irqrestore(&ha->tgt.atio_lock, flags); |
| + } |
| + |
| return IRQ_HANDLED; |
| } |
| |
| -- |
| 2.20.1 |
| |