Commit aba5a85c authored by Sreekanth Reddy's avatar Sreekanth Reddy Committed by Martin K. Petersen

scsi: mpt3sas: Fix possibility of using invalid Enclosure Handle for SAS device after host reset

Enclosure handles are not updated after host reset.  As a result, driver
device structure is holding previously assigned enclosure handle which
is different from the enclosure handle populated in the corresponding
device page.

Modified the driver to update devices enclosure handles after host reset
to current value by referring the enclosure handles from corresponding
device pages
Signed-off-by: default avatarSreekanth Reddy <Sreekanth.Reddy@broadcom.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 75888956
...@@ -5382,6 +5382,52 @@ _scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, ...@@ -5382,6 +5382,52 @@ _scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
return rc; return rc;
} }
/**
* _scsih_get_enclosure_logicalid_chassis_slot - get device's
* EnclosureLogicalID and ChassisSlot information.
* @ioc: per adapter object
* @sas_device_pg0: SAS device page0
* @sas_device: per sas device object
*
* Returns nothing.
*/
static void
_scsih_get_enclosure_logicalid_chassis_slot(struct MPT3SAS_ADAPTER *ioc,
Mpi2SasDevicePage0_t *sas_device_pg0, struct _sas_device *sas_device)
{
Mpi2ConfigReply_t mpi_reply;
Mpi2SasEnclosurePage0_t enclosure_pg0;
if (!sas_device_pg0 || !sas_device)
return;
sas_device->enclosure_handle =
le16_to_cpu(sas_device_pg0->EnclosureHandle);
sas_device->is_chassis_slot_valid = 0;
if (!le16_to_cpu(sas_device_pg0->EnclosureHandle))
return;
if (mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
&enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
le16_to_cpu(sas_device_pg0->EnclosureHandle))) {
pr_err(MPT3SAS_FMT
"Enclosure Pg0 read failed for handle(0x%04x)\n",
ioc->name, le16_to_cpu(sas_device_pg0->EnclosureHandle));
return;
}
sas_device->enclosure_logical_id =
le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
if (le16_to_cpu(enclosure_pg0.Flags) &
MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
sas_device->is_chassis_slot_valid = 1;
sas_device->chassis_slot = enclosure_pg0.ChassisSlot;
}
}
/** /**
* _scsih_check_device - checking device responsiveness * _scsih_check_device - checking device responsiveness
* @ioc: per adapter object * @ioc: per adapter object
...@@ -5398,7 +5444,6 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, ...@@ -5398,7 +5444,6 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
{ {
Mpi2ConfigReply_t mpi_reply; Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0; Mpi2SasDevicePage0_t sas_device_pg0;
Mpi2SasEnclosurePage0_t enclosure_pg0;
struct _sas_device *sas_device; struct _sas_device *sas_device;
u32 ioc_status; u32 ioc_status;
unsigned long flags; unsigned long flags;
...@@ -5407,7 +5452,6 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, ...@@ -5407,7 +5452,6 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
struct MPT3SAS_TARGET *sas_target_priv_data; struct MPT3SAS_TARGET *sas_target_priv_data;
u32 device_info; u32 device_info;
if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
return; return;
...@@ -5454,18 +5498,9 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, ...@@ -5454,18 +5498,9 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
sas_device->enclosure_level = 0; sas_device->enclosure_level = 0;
sas_device->connector_name[0] = '\0'; sas_device->connector_name[0] = '\0';
} }
sas_device->is_chassis_slot_valid = 0;
if (sas_device->enclosure_handle && _scsih_get_enclosure_logicalid_chassis_slot(ioc,
!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, &sas_device_pg0, sas_device);
&enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
sas_device->enclosure_handle))) {
if (le16_to_cpu(enclosure_pg0.Flags) &
MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
sas_device->is_chassis_slot_valid = 1;
sas_device->chassis_slot =
enclosure_pg0.ChassisSlot;
}
}
} }
/* check if device is present */ /* check if device is present */
...@@ -7088,10 +7123,8 @@ Mpi2SasDevicePage0_t *sas_device_pg0) ...@@ -7088,10 +7123,8 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
{ {
struct MPT3SAS_TARGET *sas_target_priv_data = NULL; struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
struct scsi_target *starget; struct scsi_target *starget;
struct _sas_device *sas_device; struct _sas_device *sas_device = NULL;
unsigned long flags; unsigned long flags;
Mpi2SasEnclosurePage0_t enclosure_pg0;
Mpi2ConfigReply_t mpi_reply;
spin_lock_irqsave(&ioc->sas_device_lock, flags); spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_for_each_entry(sas_device, &ioc->sas_device_list, list) { list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
...@@ -7131,18 +7164,8 @@ Mpi2SasDevicePage0_t *sas_device_pg0) ...@@ -7131,18 +7164,8 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
sas_device->connector_name[0] = '\0'; sas_device->connector_name[0] = '\0';
} }
sas_device->is_chassis_slot_valid = 0; _scsih_get_enclosure_logicalid_chassis_slot(ioc,
if (sas_device->enclosure_handle && sas_device_pg0, sas_device);
!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
&enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
sas_device->enclosure_handle))) {
if (le16_to_cpu(enclosure_pg0.Flags) &
MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
sas_device->is_chassis_slot_valid = 1;
sas_device->chassis_slot =
enclosure_pg0.ChassisSlot;
}
}
if (sas_device->handle == sas_device_pg0->DevHandle) if (sas_device->handle == sas_device_pg0->DevHandle)
goto out; goto out;
...@@ -7340,8 +7363,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) ...@@ -7340,8 +7363,7 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
/** /**
* _scsih_mark_responding_expander - mark a expander as responding * _scsih_mark_responding_expander - mark a expander as responding
* @ioc: per adapter object * @ioc: per adapter object
* @sas_address: sas address * @expander_pg0:SAS Expander Config Page0
* @handle:
* *
* After host reset, find out whether devices are still responding. * After host reset, find out whether devices are still responding.
* Used in _scsih_remove_unresponsive_expanders. * Used in _scsih_remove_unresponsive_expanders.
...@@ -7349,18 +7371,41 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) ...@@ -7349,18 +7371,41 @@ _scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
* Return nothing. * Return nothing.
*/ */
static void static void
_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc,
u16 handle) Mpi2ExpanderPage0_t *expander_pg0)
{ {
struct _sas_node *sas_expander; struct _sas_node *sas_expander = NULL;
unsigned long flags; unsigned long flags;
int i; int i, encl_pg0_rc = -1;
Mpi2ConfigReply_t mpi_reply;
Mpi2SasEnclosurePage0_t enclosure_pg0;
u16 handle = le16_to_cpu(expander_pg0->DevHandle);
u64 sas_address = le64_to_cpu(expander_pg0->SASAddress);
if (le16_to_cpu(expander_pg0->EnclosureHandle)) {
encl_pg0_rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
&enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
le16_to_cpu(expander_pg0->EnclosureHandle));
if (encl_pg0_rc)
pr_info(MPT3SAS_FMT
"Enclosure Pg0 read failed for handle(0x%04x)\n",
ioc->name,
le16_to_cpu(expander_pg0->EnclosureHandle));
}
spin_lock_irqsave(&ioc->sas_node_lock, flags); spin_lock_irqsave(&ioc->sas_node_lock, flags);
list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
if (sas_expander->sas_address != sas_address) if (sas_expander->sas_address != sas_address)
continue; continue;
sas_expander->responding = 1; sas_expander->responding = 1;
if (!encl_pg0_rc)
sas_expander->enclosure_logical_id =
le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
sas_expander->enclosure_handle =
le16_to_cpu(expander_pg0->EnclosureHandle);
if (sas_expander->handle == handle) if (sas_expander->handle == handle)
goto out; goto out;
pr_info("\texpander(0x%016llx): handle changed" \ pr_info("\texpander(0x%016llx): handle changed" \
...@@ -7413,7 +7458,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) ...@@ -7413,7 +7458,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n", pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n",
handle, handle,
(unsigned long long)sas_address); (unsigned long long)sas_address);
_scsih_mark_responding_expander(ioc, sas_address, handle); _scsih_mark_responding_expander(ioc, &expander_pg0);
} }
out: out:
......
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