@@ -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;
}
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@gmail.com> --- drivers/scsi/ips.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)