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.guang...@h3c.com>
Signed-off-by: Dick Kennedy <dick.kenn...@broadcom.com>
Signed-off-by: James Smart <jsmart2...@gmail.com>
---
Original patch sent by Zhangguanghui <zhang.guang...@h3c.com>
Modified slightly as merged and tested at Emulex.
---
 drivers/scsi/lpfc/lpfc_scsi.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 13e3e14b43f9..e4ec2b99b583 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -4848,20 +4848,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,
-- 
2.13.7

Reply via email to