scsi: qla2xxx: Fix deadlock between ATIO and HW lock
authorQuinn Tran <quinn.tran@cavium.com>
Tue, 4 Sep 2018 21:19:10 +0000 (14:19 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 12 Sep 2018 00:28:08 +0000 (20:28 -0400)
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>
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c

index f8f5518..c3c7ab6 100644 (file)
@@ -4859,19 +4859,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);
                        }
                }
        }
index 36cbb29..bc97e3a 100644 (file)
@@ -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;
 }