From 364398324c901bc834f762eb5443d2e5a1d2a0db Mon Sep 17 00:00:00 2001 From: "gurinder.shergill@hp.com" Date: Tue, 23 Apr 2013 10:13:17 -0700 Subject: [SCSI] qla2xxx: Fix for locking issue between driver ISR and mailbox routines The driver uses ha->mbx_cmd_flags variable to pass information between its ISR and mailbox routines, however, it does so without the protection of any locks. Under certain conditions, this can lead to multiple mailbox command completions being signaled, which, in turn, leads to a false mailbox timeout error for the subsequently issued mailbox command. The issue occurs frequently but intermittenly with the Qlogic 8GFC mezz card during card initialization, resulting in card initialization failure. Signed-off-by: Gurinder (Sunny) Shergill Acked-by: Saurav Kashyap Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_nx.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers/scsi/qla2xxx/qla_nx.c') diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 10754f518303..cce0cd0d7ec4 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2074,9 +2074,6 @@ qla82xx_intr_handler(int irq, void *dev_id) } WRT_REG_DWORD(®->host_int, 0); } - spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (!ha->flags.msi_enabled) - qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); #ifdef QL_DEBUG_LEVEL_17 if (!irq && ha->flags.eeh_busy) @@ -2085,11 +2082,12 @@ qla82xx_intr_handler(int irq, void *dev_id) status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat); #endif - if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && - (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - complete(&ha->mbx_intr_comp); - } + qla2x00_handle_mbx_completion(ha, status); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (!ha->flags.msi_enabled) + qla82xx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff); + return IRQ_HANDLED; } @@ -2149,8 +2147,6 @@ qla82xx_msix_default(int irq, void *dev_id) WRT_REG_DWORD(®->host_int, 0); } while (0); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - #ifdef QL_DEBUG_LEVEL_17 if (!irq && ha->flags.eeh_busy) ql_log(ql_log_warn, vha, 0x5044, @@ -2158,11 +2154,9 @@ qla82xx_msix_default(int irq, void *dev_id) status, ha->mbx_cmd_flags, ha->flags.mbox_int, stat); #endif - if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && - (status & MBX_INTERRUPT) && ha->flags.mbox_int) { - set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); - complete(&ha->mbx_intr_comp); - } + qla2x00_handle_mbx_completion(ha, status); + spin_unlock_irqrestore(&ha->hardware_lock, flags); + return IRQ_HANDLED; } @@ -3345,7 +3339,7 @@ void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) ha->flags.mbox_busy = 0; ql_log(ql_log_warn, vha, 0x6010, "Doing premature completion of mbx command.\n"); - if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) + if (test_and_clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) complete(&ha->mbx_intr_comp); } } -- cgit v1.2.3