aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas
diff options
context:
space:
mode:
authornagalakshmi.nandigama@lsi.com <nagalakshmi.nandigama@lsi.com>2012-03-20 02:39:26 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-04-23 14:27:44 -0400
commit39af7a98946a73f2e4bfb35cfbca2114366d0c82 (patch)
treeed44b96ad6eea644f88f6838ee974edfa59f6ebf /drivers/scsi/mpt2sas
parent64bb81383afed5e87d54d8102baeebc9aeb97b8f (diff)
[SCSI] mpt2sas: Fix for hard drive going OFFLINE when hard reset issued and simultaneously another hard drive is hot unplugged
Following the host reset, the firmware discovery is reassigning another hard drive in the topology to the same device handle as that device is getting hot removed. Until the driver device removal routine is called, there will be two hard drive with the matching device handle in the internal device link list. In the device removal routine, a separate function which moves the device from BLOCKED into OFFLINE state. Since this routine is passed with the device handle passed as input parameter, the routine will be traversing the internal device link list searching for matching device handle. This results in two devices with matching device handle, therefore both devices goes OFFLINE. To fix this issue,the input parameter is changed from device handle to SAS address, therefore only the device that is hot unplugged will be placed in OFFLINE state. Signed-off-by: Nagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com> Cc: stable@vger.kernel.org Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/mpt2sas')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index d901d4bffeaa..f612d1dc7baf 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -2915,7 +2915,7 @@ _scsih_ublock_io_all_device(struct MPT2SAS_ADAPTER *ioc)
2915 * During device pull we need to appropiately set the sdev state. 2915 * During device pull we need to appropiately set the sdev state.
2916 */ 2916 */
2917static void 2917static void
2918_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) 2918_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address)
2919{ 2919{
2920 struct MPT2SAS_DEVICE *sas_device_priv_data; 2920 struct MPT2SAS_DEVICE *sas_device_priv_data;
2921 struct scsi_device *sdev; 2921 struct scsi_device *sdev;
@@ -2926,10 +2926,12 @@ _scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
2926 continue; 2926 continue;
2927 if (!sas_device_priv_data->block) 2927 if (!sas_device_priv_data->block)
2928 continue; 2928 continue;
2929 if (sas_device_priv_data->sas_target->handle == handle) { 2929 if (sas_device_priv_data->sas_target->sas_address ==
2930 sas_address) {
2930 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, 2931 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2931 MPT2SAS_INFO_FMT "SDEV_RUNNING: " 2932 MPT2SAS_INFO_FMT "SDEV_RUNNING: "
2932 "handle(0x%04x)\n", ioc->name, handle)); 2933 "sas address(0x%016llx)\n", ioc->name,
2934 (unsigned long long)sas_address));
2933 sas_device_priv_data->block = 0; 2935 sas_device_priv_data->block = 0;
2934 scsi_internal_device_unblock(sdev); 2936 scsi_internal_device_unblock(sdev);
2935 } 2937 }
@@ -3137,7 +3139,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle)
3137 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: " 3139 dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "setting delete flag: "
3138 "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle, 3140 "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle,
3139 (unsigned long long)sas_address)); 3141 (unsigned long long)sas_address));
3140 _scsih_ublock_io_device(ioc, handle); 3142 _scsih_ublock_io_device(ioc, sas_address);
3141 sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE; 3143 sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
3142 } 3144 }
3143 3145
@@ -5185,7 +5187,7 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
5185 return; 5187 return;
5186 } 5188 }
5187 spin_unlock_irqrestore(&ioc->sas_device_lock, flags); 5189 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5188 _scsih_ublock_io_device(ioc, handle); 5190 _scsih_ublock_io_device(ioc, sas_address);
5189 5191
5190} 5192}
5191 5193
@@ -5322,7 +5324,7 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc,
5322 if (sas_device->starget && sas_device->starget->hostdata) { 5324 if (sas_device->starget && sas_device->starget->hostdata) {
5323 sas_target_priv_data = sas_device->starget->hostdata; 5325 sas_target_priv_data = sas_device->starget->hostdata;
5324 sas_target_priv_data->deleted = 1; 5326 sas_target_priv_data->deleted = 1;
5325 _scsih_ublock_io_device(ioc, sas_device->handle); 5327 _scsih_ublock_io_device(ioc, sas_device->sas_address);
5326 sas_target_priv_data->handle = 5328 sas_target_priv_data->handle =
5327 MPT2SAS_INVALID_DEVICE_HANDLE; 5329 MPT2SAS_INVALID_DEVICE_HANDLE;
5328 } 5330 }
@@ -6998,8 +7000,8 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
6998 list_for_each_entry_safe(sas_device, sas_device_next, 7000 list_for_each_entry_safe(sas_device, sas_device_next,
6999 &ioc->sas_device_list, list) { 7001 &ioc->sas_device_list, list) {
7000 if (!sas_device->responding) 7002 if (!sas_device->responding)
7001 _scsih_device_remove_by_handle(ioc, 7003 mpt2sas_device_remove_by_sas_address(ioc,
7002 sas_device->handle); 7004 sas_device->sas_address);
7003 else 7005 else
7004 sas_device->responding = 0; 7006 sas_device->responding = 0;
7005 } 7007 }