From: Mikhail Malygin <m.malygin@xxxxxxxxx> 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.malygin@xxxxxxxxx> --- 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)