[SCSI] mpt2sas: Fix for dead lock occurring between host_lock and sas_device_lock
authornagalakshmi.nandigama@lsi.com <nagalakshmi.nandigama@lsi.com>
Wed, 19 Oct 2011 10:07:14 +0000 (15:37 +0530)
committerJames Bottomley <JBottomley@Parallels.com>
Sun, 30 Oct 2011 08:53:45 +0000 (12:53 +0400)
Fix for dead lock occurring between host_lock and sas_device_lock.

The deadlock is between two spin locks, between the shost->host_lock
and driver ioc->sas_device_lock.

The fix is to rearrange the code in the  FW/Driver device removal
handshake so the ioc->sas_device_lock is not occurring when the
shost->host_lock is taken.

[jejb: zero initialise sas_address to fix spurious compiler warning]
Signed-off-by: Nagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/mpt2sas/mpt2sas_scsih.c

index cd89f42..f9ce319 100644 (file)
@@ -3016,7 +3016,8 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        Mpi2SCSITaskManagementRequest_t *mpi_request;
        u16 smid;
        struct _sas_device *sas_device;
-       struct MPT2SAS_TARGET *sas_target_priv_data;
+       struct MPT2SAS_TARGET *sas_target_priv_data = NULL;
+       u64 sas_address = 0;
        unsigned long flags;
        struct _tr_list *delayed_tr;
        u32 ioc_state;
@@ -3049,13 +3050,17 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
             sas_device->starget->hostdata) {
                sas_target_priv_data = sas_device->starget->hostdata;
                sas_target_priv_data->deleted = 1;
-               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
-                   "setting delete flag: handle(0x%04x), "
-                   "sas_addr(0x%016llx)\n", ioc->name, handle,
-                   (unsigned long long) sas_device->sas_address));
+               sas_address = sas_device->sas_address;
        }
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
+       if (sas_target_priv_data) {
+               dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
+               "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
+                       (unsigned long long)sas_address));
+               _scsih_ublock_io_device(ioc, handle);
+       }
+
        smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
        if (!smid) {
                delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);