Commit 6241f22c authored by Sreekanth Reddy's avatar Sreekanth Reddy Committed by James Bottomley

[SCSI] mpt2sas: Fix for device scan following host reset could get stuck in a infinite loop

Modified device scan routine so each configuration page read breaks from the
while loop when the ioc_status is not equal to MPI2_IOCSTATUS_SUCCESS.

[jejb: checkpatch fixes]
Signed-off-by: default avatarSreekanth Reddy <Sreekanth.Reddy@lsi.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent ca6832e9
...@@ -7097,12 +7097,15 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7097,12 +7097,15 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
struct _sas_device *sas_device; struct _sas_device *sas_device;
struct _sas_node *expander_device; struct _sas_node *expander_device;
static struct _raid_device *raid_device; static struct _raid_device *raid_device;
u8 retry_count;
unsigned long flags; unsigned long flags;
printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name); printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
_scsih_sas_host_refresh(ioc); _scsih_sas_host_refresh(ioc);
printk(MPT2SAS_INFO_FMT "\tscan devices: expanders start\n",
ioc->name);
/* expanders */ /* expanders */
handle = 0xFFFF; handle = 0xFFFF;
while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
...@@ -7111,6 +7114,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7111,6 +7114,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK; MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break; break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
printk(MPT2SAS_INFO_FMT "\tbreak from expander scan: "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, ioc_status,
le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
handle = le16_to_cpu(expander_pg0.DevHandle); handle = le16_to_cpu(expander_pg0.DevHandle);
spin_lock_irqsave(&ioc->sas_node_lock, flags); spin_lock_irqsave(&ioc->sas_node_lock, flags);
expander_device = mpt2sas_scsih_expander_find_by_sas_address( expander_device = mpt2sas_scsih_expander_find_by_sas_address(
...@@ -7119,13 +7129,26 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7119,13 +7129,26 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
if (expander_device) if (expander_device)
_scsih_refresh_expander_links(ioc, expander_device, _scsih_refresh_expander_links(ioc, expander_device,
handle); handle);
else else {
printk(MPT2SAS_INFO_FMT "\tBEFORE adding expander: "
"handle (0x%04x), sas_addr(0x%016llx)\n",
ioc->name, handle, (unsigned long long)
le64_to_cpu(expander_pg0.SASAddress));
_scsih_expander_add(ioc, handle); _scsih_expander_add(ioc, handle);
printk(MPT2SAS_INFO_FMT "\tAFTER adding expander: "
"handle (0x%04x), sas_addr(0x%016llx)\n",
ioc->name, handle, (unsigned long long)
le64_to_cpu(expander_pg0.SASAddress));
} }
}
printk(MPT2SAS_INFO_FMT "\tscan devices: expanders complete\n",
ioc->name);
if (!ioc->ir_firmware) if (!ioc->ir_firmware)
goto skip_to_sas; goto skip_to_sas;
printk(MPT2SAS_INFO_FMT "\tscan devices phys disk start\n", ioc->name);
/* phys disk */ /* phys disk */
phys_disk_num = 0xFF; phys_disk_num = 0xFF;
while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
...@@ -7135,6 +7158,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7135,6 +7158,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK; MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break; break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan:"
"ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, ioc_status,
le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
phys_disk_num = pd_pg0.PhysDiskNum; phys_disk_num = pd_pg0.PhysDiskNum;
handle = le16_to_cpu(pd_pg0.DevHandle); handle = le16_to_cpu(pd_pg0.DevHandle);
spin_lock_irqsave(&ioc->sas_device_lock, flags); spin_lock_irqsave(&ioc->sas_device_lock, flags);
...@@ -7146,17 +7176,46 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7146,17 +7176,46 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
&sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
handle) != 0) handle) != 0)
continue; continue;
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, ioc_status,
le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
if (!_scsih_get_sas_address(ioc, parent_handle, if (!_scsih_get_sas_address(ioc, parent_handle,
&sas_address)) { &sas_address)) {
printk(MPT2SAS_INFO_FMT "\tBEFORE adding phys disk: "
" handle (0x%04x), sas_addr(0x%016llx)\n",
ioc->name, handle, (unsigned long long)
le64_to_cpu(sas_device_pg0.SASAddress));
mpt2sas_transport_update_links(ioc, sas_address, mpt2sas_transport_update_links(ioc, sas_address,
handle, sas_device_pg0.PhyNum, handle, sas_device_pg0.PhyNum,
MPI2_SAS_NEG_LINK_RATE_1_5); MPI2_SAS_NEG_LINK_RATE_1_5);
set_bit(handle, ioc->pd_handles); set_bit(handle, ioc->pd_handles);
_scsih_add_device(ioc, handle, 0, 1); retry_count = 0;
/* This will retry adding the end device.
* _scsih_add_device() will decide on retries and
* return "1" when it should be retried
*/
while (_scsih_add_device(ioc, handle, retry_count++,
1)) {
ssleep(1);
}
printk(MPT2SAS_INFO_FMT "\tAFTER adding phys disk: "
" handle (0x%04x), sas_addr(0x%016llx)\n",
ioc->name, handle, (unsigned long long)
le64_to_cpu(sas_device_pg0.SASAddress));
} }
} }
printk(MPT2SAS_INFO_FMT "\tscan devices: phys disk complete\n",
ioc->name);
printk(MPT2SAS_INFO_FMT "\tscan devices: volumes start\n", ioc->name);
/* volumes */ /* volumes */
handle = 0xFFFF; handle = 0xFFFF;
while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
...@@ -7165,6 +7224,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7165,6 +7224,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK; MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break; break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, ioc_status,
le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
handle = le16_to_cpu(volume_pg1.DevHandle); handle = le16_to_cpu(volume_pg1.DevHandle);
spin_lock_irqsave(&ioc->raid_device_lock, flags); spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_wwid(ioc, raid_device = _scsih_raid_device_find_by_wwid(ioc,
...@@ -7176,18 +7242,38 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7176,18 +7242,38 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
&volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
sizeof(Mpi2RaidVolPage0_t))) sizeof(Mpi2RaidVolPage0_t)))
continue; continue;
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
"ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, ioc_status,
le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) { volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t)); memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED; element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
element.VolDevHandle = volume_pg1.DevHandle; element.VolDevHandle = volume_pg1.DevHandle;
printk(MPT2SAS_INFO_FMT "\tBEFORE adding volume: "
" handle (0x%04x)\n", ioc->name,
volume_pg1.DevHandle);
_scsih_sas_volume_add(ioc, &element); _scsih_sas_volume_add(ioc, &element);
printk(MPT2SAS_INFO_FMT "\tAFTER adding volume: "
" handle (0x%04x)\n", ioc->name,
volume_pg1.DevHandle);
} }
} }
printk(MPT2SAS_INFO_FMT "\tscan devices: volumes complete\n",
ioc->name);
skip_to_sas: skip_to_sas:
printk(MPT2SAS_INFO_FMT "\tscan devices: end devices start\n",
ioc->name);
/* sas devices */ /* sas devices */
handle = 0xFFFF; handle = 0xFFFF;
while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
...@@ -7197,6 +7283,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7197,6 +7283,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK; MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
break; break;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
printk(MPT2SAS_INFO_FMT "\tbreak from end device scan:"
" ioc_status(0x%04x), loginfo(0x%08x)\n",
ioc->name, ioc_status,
le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
handle = le16_to_cpu(sas_device_pg0.DevHandle); handle = le16_to_cpu(sas_device_pg0.DevHandle);
if (!(_scsih_is_end_device( if (!(_scsih_is_end_device(
le32_to_cpu(sas_device_pg0.DeviceInfo)))) le32_to_cpu(sas_device_pg0.DeviceInfo))))
...@@ -7209,12 +7302,31 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) ...@@ -7209,12 +7302,31 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
continue; continue;
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: "
"handle (0x%04x), sas_addr(0x%016llx)\n",
ioc->name, handle, (unsigned long long)
le64_to_cpu(sas_device_pg0.SASAddress));
mpt2sas_transport_update_links(ioc, sas_address, handle, mpt2sas_transport_update_links(ioc, sas_address, handle,
sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
_scsih_add_device(ioc, handle, 0, 0); retry_count = 0;
/* This will retry adding the end device.
* _scsih_add_device() will decide on retries and
* return "1" when it should be retried
*/
while (_scsih_add_device(ioc, handle, retry_count++,
0)) {
ssleep(1);
}
printk(MPT2SAS_INFO_FMT "\tAFTER adding end device: "
"handle (0x%04x), sas_addr(0x%016llx)\n",
ioc->name, handle, (unsigned long long)
le64_to_cpu(sas_device_pg0.SASAddress));
} }
} }
printk(MPT2SAS_INFO_FMT "\tscan devices: end devices complete\n",
ioc->name);
printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name); printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
} }
...@@ -8076,8 +8188,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -8076,8 +8188,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (max_sectors != 0xFFFF) { if (max_sectors != 0xFFFF) {
if (max_sectors < 64) { if (max_sectors < 64) {
shost->max_sectors = 64; shost->max_sectors = 64;
printk(MPT2SAS_WARN_FMT "Invalid value %d passed "\ printk(MPT2SAS_WARN_FMT "Invalid value %d passed "
"for max_sectors, range is 64 to 32767. Assigning "\ "for max_sectors, range is 64 to 32767. Assigning "
"value of 64.\n", ioc->name, max_sectors); "value of 64.\n", ioc->name, max_sectors);
} else if (max_sectors > 32767) { } else if (max_sectors > 32767) {
shost->max_sectors = 32767; shost->max_sectors = 32767;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment