]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: lpfc: Fix hardlockup in lpfc_abort_handler
authorJames Smart <jsmart2021@gmail.com>
Fri, 18 Oct 2019 21:18:22 +0000 (14:18 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 Jan 2020 18:16:44 +0000 (19:16 +0100)
[ Upstream commit 91a52b617cdb8bf6d298892101c061d438b84a19 ]

In lpfc_abort_handler, the lock acquire order is hbalock (irqsave),
buf_lock (irq) and ring_lock (irq).  The issue is that in two places the
locks are released out of order - the buf_lock and the hbalock - resulting
in the cpu preemption/lock flags getting restored out of order and
deadlocking the cpu.

Fix the unlock order by fully releasing the hbalocks as well.

CC: Zhangguanghui <zhang.guanghui@h3c.com>
Link: https://lore.kernel.org/r/20191018211832.7917-7-jsmart2021@gmail.com
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/lpfc/lpfc_scsi.c

index ad8ef67a1db3489e88d9959dcfa5c0a4f81c638c..aa82d538a18a48488b21681c977905f5b3bf944a 100644 (file)
@@ -4846,20 +4846,21 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
                ret_val = __lpfc_sli_issue_iocb(phba, LPFC_FCP_RING,
                                                abtsiocb, 0);
        }
-       /* no longer need the lock after this point */
-       spin_unlock_irqrestore(&phba->hbalock, flags);
 
        if (ret_val == IOCB_ERROR) {
                /* Indicate the IO is not being aborted by the driver. */
                iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
                lpfc_cmd->waitq = NULL;
                spin_unlock(&lpfc_cmd->buf_lock);
+               spin_unlock_irqrestore(&phba->hbalock, flags);
                lpfc_sli_release_iocbq(phba, abtsiocb);
                ret = FAILED;
                goto out;
        }
 
+       /* no longer need the lock after this point */
        spin_unlock(&lpfc_cmd->buf_lock);
+       spin_unlock_irqrestore(&phba->hbalock, flags);
 
        if (phba->cfg_poll & DISABLE_FCP_RING_INT)
                lpfc_sli_handle_fast_ring_event(phba,