From: Mikhail Malygin <m.maly...@yadro.com>

The patch addresses issue causing recursive spinlock in qla_target.c.
qlt_handle_login takes vha->hw->tgt.sess_lock, then calls 
qlt_schedule_sess_for_deletion
where it tries to take spinlock again:

BUG: spinlock lockup suspected on CPU#0, swapper/0/0
 lock: 0xc00000c07aa8bec0, .magic: dead4ead, .owner: swapper/0/0, .owner_cpu: 0
CPU: 0 PID: 0 Comm: swapper/0 Tainted: G           OE   NX 
4.4.132-ttln.24-debug #1
Call Trace:
[c00000dfff6d7830] [c0000000008060c0] dump_stack+0xb0/0xf0 (unreliable)
[c00000dfff6d7870] [c0000000007ff6ec] spin_dump+0xa8/0xc4
[c00000dfff6d78e0] [c000000000128320] do_raw_spin_lock+0x140/0x1d0
[c00000dfff6d7920] [c0000000007f7354] _raw_spin_lock_irqsave+0x34/0x50
[c00000dfff6d7950] [d00000001edf3220] qlt_schedule_sess_for_deletion+0x90/0x250 
[qla2xxx]
[c00000dfff6d79c0] [d00000001edf6b08] 
qlt_find_sess_invalidate_other+0x1d8/0x230 [qla2xxx]
[c00000dfff6d7a70] [d00000001edf710c] qlt_handle_login+0x5ac/0x760 [qla2xxx]
[c00000dfff6d7b10] [d00000001edf7ccc] qlt_handle_imm_notify+0xa0c/0x10b0 
[qla2xxx]
[c00000dfff6d7c00] [d00000001edf85f0] qlt_24xx_atio_pkt+0x280/0x400 [qla2xxx]
[c00000dfff6d7ca0] [d00000001edfa9d8] qlt_24xx_process_atio_queue+0x368/0x7d0 
[qla2xxx]
[c00000dfff6d7d80] [d00000001edfb898] qla83xx_msix_atio_q+0x58/0x90 [qla2xxx]
[c00000dfff6d7dc0] [c000000000133cd0] __handle_irq_event_percpu+0xa0/0x2f0
[c00000dfff6d7e80] [c000000000133f5c] handle_irq_event_percpu+0x3c/0x90
[c00000dfff6d7ec0] [c000000000134018] handle_irq_event+0x68/0xb0
[c00000dfff6d7f00] [c000000000139278] handle_fasteoi_irq+0xf8/0x260
[c00000dfff6d7f40] [c000000000132e80] generic_handle_irq+0x50/0x80
[c00000dfff6d7f60] [c000000000014c44] __do_irq+0x84/0x1d0
[c00000dfff6d7f90] [c000000000027924] call_do_irq+0x14/0x24
[c000000000f13a20] [c000000000014e30] do_IRQ+0xa0/0x120
[c000000000f13a70] [c000000000002694] hardware_interrupt_common+0x114/0x180
--- interrupt: 501 at snooze_loop+0xc4/0x1a0
    LR = snooze_loop+0x16c/0x1a0
[c000000000f13d60] [c00000000063b41c] nap_loop+0x5c/0x120 (unreliable)
[c000000000f13da0] [c000000000637f9c] cpuidle_enter_state+0xbc/0x3d0
[c000000000f13e00] [c00000000011db10] call_cpuidle+0x50/0x80
[c000000000f13e20] [c00000000011e138] cpu_startup_entry+0x388/0x490
[c000000000f13ee0] [c00000000000c260] rest_init+0xb0/0xd0
[c000000000f13f00] [c000000000aa4070] start_kernel+0x55c/0x578
[c000000000f13f90] [c000000000008e6c] start_here_common+0x20/0xb4
nvme nvme0: I/O 782 QID 9 timeout, completion polled
nvme nvme0: I/O 99 QID 12 timeout, completion polled
nvme nvme0: I/O 925 QID 4 timeout, completio

Signed-off-by: Mikhail Malygin <m.maly...@yadro.com>
---
 drivers/scsi/qla2xxx/qla_target.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 025dc2d3f3de..35518a2a6890 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1227,11 +1227,9 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess)
        }
 }
 
-void qlt_schedule_sess_for_deletion(struct fc_port *sess)
+static void qlt_schedule_sess_for_deletion_locked(struct fc_port *sess)
 {
        struct qla_tgt *tgt = sess->tgt;
-       struct qla_hw_data *ha = sess->vha->hw;
-       unsigned long flags;
 
        if (sess->disc_state == DSC_DELETE_PEND)
                return;
@@ -1247,16 +1245,13 @@ void qlt_schedule_sess_for_deletion(struct fc_port 
*sess)
                        return;
        }
 
-       spin_lock_irqsave(&ha->tgt.sess_lock, flags);
        if (sess->deleted == QLA_SESS_DELETED)
                sess->logout_on_delete = 0;
 
        if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
-               spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
                return;
        }
        sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
-       spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
 
        sess->disc_state = DSC_DELETE_PEND;
 
@@ -1269,6 +1264,16 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
        WARN_ON(!queue_work(sess->vha->hw->wq, &sess->del_work));
 }
 
+void qlt_schedule_sess_for_deletion(struct fc_port *sess)
+{
+       struct qla_hw_data *ha = sess->vha->hw;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ha->tgt.sess_lock, flags);
+       qlt_schedule_sess_for_deletion_locked(sess);
+       spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+}
+
 static void qlt_clear_tgt_db(struct qla_tgt *tgt)
 {
        struct fc_port *sess;
@@ -4527,7 +4532,7 @@ qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, 
uint64_t wwn,
                                 * might have cleared it when requested this 
session
                                 * deletion, so don't touch it
                                 */
-                               qlt_schedule_sess_for_deletion(other_sess);
+                               
qlt_schedule_sess_for_deletion_locked(other_sess);
                        } else {
                                /*
                                 * Another wwn used to have our s_id/loop_id
@@ -4540,7 +4545,7 @@ qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, 
uint64_t wwn,
                                other_sess->keep_nport_handle = 1;
                                if (other_sess->disc_state != DSC_DELETED)
                                        *conflict_sess = other_sess;
-                               qlt_schedule_sess_for_deletion(other_sess);
+                               
qlt_schedule_sess_for_deletion_locked(other_sess);
                        }
                        continue;
                }
@@ -4554,7 +4559,7 @@ qlt_find_sess_invalidate_other(scsi_qla_host_t *vha, 
uint64_t wwn,
 
                        /* Same loop_id but different s_id
                         * Ok to kill and logout */
-                       qlt_schedule_sess_for_deletion(other_sess);
+                       qlt_schedule_sess_for_deletion_locked(other_sess);
                }
        }
 
-- 
2.15.1 (Apple Git-101)

Reply via email to