Hard interrupt do_ipsintr() could introduce double locks on host->host_lock. <Deadlock #1> ips_eh_abort() --> spin_loc(host->host_lock) <interrupt> --> do_ipsintr() --> spin_lock(host->host_lock) This flaw was found by an experimental static analysis tool I am developing for irq-related deadlock. To prevent the potential deadlock, the patch use spin_lock_irqsave() on host->host_lock. Signed-off-by: Chengfeng Ye <dg573847474@xxxxxxxxx> --- drivers/scsi/ips.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index bb206509265e..3caab8233d68 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -776,6 +776,8 @@ int ips_eh_abort(struct scsi_cmnd *SC) { ips_ha_t *ha; ips_copp_wait_item_t *item; + unsigned long flags; + int ret; struct Scsi_Host *host; @@ -793,7 +795,7 @@ int ips_eh_abort(struct scsi_cmnd *SC) if (!ha->active) return (FAILED); - spin_lock(host->host_lock); + spin_lock_irqsave(host->host_lock, flags); /* See if the command is on the copp queue */ item = ha->copp_waitlist.head; @@ -814,7 +816,7 @@ int ips_eh_abort(struct scsi_cmnd *SC) ret = (FAILED); } - spin_unlock(host->host_lock); + spin_unlock_irqrestore(host->host_lock, flags); return ret; } -- 2.17.1