Skip to content

Commit

Permalink
scsi: mpt3sas: scan and add nvme device after controller reset
Browse files Browse the repository at this point in the history
After Controller reset, Scan and add nvme device back to the topology.

Signed-off-by: Chaitra P B <chaitra.basappa@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subramani@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Suganath Prabu Subramani authored and Martin K. Petersen committed Nov 3, 2017
1 parent d1b01d1 commit ec051e5
Showing 1 changed file with 190 additions and 4 deletions.
194 changes: 190 additions & 4 deletions drivers/scsi/mpt3sas/mpt3sas_scsih.c
Original file line number Diff line number Diff line change
Expand Up @@ -4886,6 +4886,7 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
char *desc_scsi_state = ioc->tmp_string;
u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
struct _sas_device *sas_device = NULL;
struct _pcie_device *pcie_device = NULL;
struct scsi_target *starget = scmd->device->sdev_target;
struct MPT3SAS_TARGET *priv_target = starget->hostdata;
char *device_str = NULL;
Expand Down Expand Up @@ -5018,6 +5019,28 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
device_str, (unsigned long long)priv_target->sas_address);
} else if (priv_target->flags & MPT_TARGET_FLAGS_PCIE_DEVICE) {
pcie_device = mpt3sas_get_pdev_from_target(ioc, priv_target);
if (pcie_device) {
pr_info(MPT3SAS_FMT "\twwid(0x%016llx), port(%d)\n",
ioc->name,
(unsigned long long)pcie_device->wwid,
pcie_device->port_num);
if (pcie_device->enclosure_handle != 0)
pr_info(MPT3SAS_FMT
"\tenclosure logical id(0x%016llx), "
"slot(%d)\n", ioc->name,
(unsigned long long)
pcie_device->enclosure_logical_id,
pcie_device->slot);
if (pcie_device->connector_name[0])
pr_info(MPT3SAS_FMT
"\tenclosure level(0x%04x),"
"connector name( %s)\n",
ioc->name, pcie_device->enclosure_level,
pcie_device->connector_name);
pcie_device_put(pcie_device);
}
} else {
sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target);
if (sas_device) {
Expand Down Expand Up @@ -5054,11 +5077,10 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
struct sense_info data;
_scsih_normalize_sense(scmd->sense_buffer, &data);
pr_warn(MPT3SAS_FMT
"\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
ioc->name, data.skey,
data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
"\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
ioc->name, data.skey,
data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
}

if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
response_info = le32_to_cpu(mpi_reply->ResponseInfo);
response_bytes = (u8 *)&response_info;
Expand Down Expand Up @@ -8557,6 +8579,130 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
ioc->name);
}

/**
* _scsih_mark_responding_pcie_device - mark a pcie_device as responding
* @ioc: per adapter object
* @pcie_device_pg0: PCIe Device page 0
*
* After host reset, find out whether devices are still responding.
* Used in _scsih_remove_unresponding_devices.
*
* Return nothing.
*/
static void
_scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc,
Mpi26PCIeDevicePage0_t *pcie_device_pg0)
{
struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
struct scsi_target *starget;
struct _pcie_device *pcie_device;
unsigned long flags;

spin_lock_irqsave(&ioc->pcie_device_lock, flags);
list_for_each_entry(pcie_device, &ioc->pcie_device_list, list) {
if ((pcie_device->wwid == pcie_device_pg0->WWID) &&
(pcie_device->slot == pcie_device_pg0->Slot)) {
pcie_device->responding = 1;
starget = pcie_device->starget;
if (starget && starget->hostdata) {
sas_target_priv_data = starget->hostdata;
sas_target_priv_data->tm_busy = 0;
sas_target_priv_data->deleted = 0;
} else
sas_target_priv_data = NULL;
if (starget) {
starget_printk(KERN_INFO, starget,
"handle(0x%04x), wwid(0x%016llx) ",
pcie_device->handle,
(unsigned long long)pcie_device->wwid);
if (pcie_device->enclosure_handle != 0)
starget_printk(KERN_INFO, starget,
"enclosure logical id(0x%016llx), "
"slot(%d)\n",
(unsigned long long)
pcie_device->enclosure_logical_id,
pcie_device->slot);
}

if (((le32_to_cpu(pcie_device_pg0->Flags)) &
MPI26_PCIEDEV0_FLAGS_ENCL_LEVEL_VALID) &&
(ioc->hba_mpi_version_belonged != MPI2_VERSION)) {
pcie_device->enclosure_level =
pcie_device_pg0->EnclosureLevel;
memcpy(&pcie_device->connector_name[0],
&pcie_device_pg0->ConnectorName[0], 4);
} else {
pcie_device->enclosure_level = 0;
pcie_device->connector_name[0] = '\0';
}

if (pcie_device->handle == pcie_device_pg0->DevHandle)
goto out;
pr_info(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
pcie_device->handle);
pcie_device->handle = pcie_device_pg0->DevHandle;
if (sas_target_priv_data)
sas_target_priv_data->handle =
pcie_device_pg0->DevHandle;
goto out;
}
}

out:
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
}

/**
* _scsih_search_responding_pcie_devices -
* @ioc: per adapter object
*
* After host reset, find out whether devices are still responding.
* If not remove.
*
* Return nothing.
*/
static void
_scsih_search_responding_pcie_devices(struct MPT3SAS_ADAPTER *ioc)
{
Mpi26PCIeDevicePage0_t pcie_device_pg0;
Mpi2ConfigReply_t mpi_reply;
u16 ioc_status;
u16 handle;
u32 device_info;

pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name);

if (list_empty(&ioc->pcie_device_list))
goto out;

handle = 0xFFFF;
while (!(mpt3sas_config_get_pcie_device_pg0(ioc, &mpi_reply,
&pcie_device_pg0, MPI26_PCIE_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT "\tbreak from %s: "
"ioc_status(0x%04x), loginfo(0x%08x)\n", ioc->name,
__func__, ioc_status,
le32_to_cpu(mpi_reply.IOCLogInfo));
break;
}
handle = le16_to_cpu(pcie_device_pg0.DevHandle);
device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo);
if (!(_scsih_is_nvme_device(device_info)))
continue;
pcie_device_pg0.WWID = le64_to_cpu(pcie_device_pg0.WWID),
pcie_device_pg0.Slot = le16_to_cpu(pcie_device_pg0.Slot);
pcie_device_pg0.Flags = le32_to_cpu(pcie_device_pg0.Flags);
pcie_device_pg0.DevHandle = handle;
_scsih_mark_responding_pcie_device(ioc, &pcie_device_pg0);
}
out:
pr_info(MPT3SAS_FMT "search for PCIe end-devices: complete\n",
ioc->name);
}

/**
* _scsih_mark_responding_raid_device - mark a raid_device as responding
* @ioc: per adapter object
Expand Down Expand Up @@ -8930,6 +9076,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
{
Mpi2ExpanderPage0_t expander_pg0;
Mpi2SasDevicePage0_t sas_device_pg0;
Mpi26PCIeDevicePage0_t pcie_device_pg0;
Mpi2RaidVolPage1_t volume_pg1;
Mpi2RaidVolPage0_t volume_pg0;
Mpi2RaidPhysDiskPage0_t pd_pg0;
Expand All @@ -8940,6 +9087,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
u16 handle, parent_handle;
u64 sas_address;
struct _sas_device *sas_device;
struct _pcie_device *pcie_device;
struct _sas_node *expander_device;
static struct _raid_device *raid_device;
u8 retry_count;
Expand Down Expand Up @@ -9165,7 +9313,44 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
}
pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n",
ioc->name);
pr_info(MPT3SAS_FMT "\tscan devices: pcie end devices start\n",
ioc->name);

/* pcie devices */
handle = 0xFFFF;
while (!(mpt3sas_config_get_pcie_device_pg0(ioc, &mpi_reply,
&pcie_device_pg0, MPI26_PCIE_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
handle))) {
ioc_status = le16_to_cpu(mpi_reply.IOCStatus)
& MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_info(MPT3SAS_FMT "\tbreak from pcie 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(pcie_device_pg0.DevHandle);
if (!(_scsih_is_nvme_device(
le32_to_cpu(pcie_device_pg0.DeviceInfo))))
continue;
pcie_device = mpt3sas_get_pdev_by_wwid(ioc,
le64_to_cpu(pcie_device_pg0.WWID));
if (pcie_device) {
pcie_device_put(pcie_device);
continue;
}
retry_count = 0;
parent_handle = le16_to_cpu(pcie_device_pg0.ParentDevHandle);
_scsih_pcie_add_device(ioc, handle);

pr_info(MPT3SAS_FMT "\tAFTER adding pcie end device: "
"handle (0x%04x), wwid(0x%016llx)\n", ioc->name,
handle,
(unsigned long long) le64_to_cpu(pcie_device_pg0.WWID));
}
pr_info(MPT3SAS_FMT "\tpcie devices: pcie end devices complete\n",
ioc->name);
pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name);
}
/**
Expand Down Expand Up @@ -9215,6 +9400,7 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
!ioc->sas_hba.num_phys)) {
_scsih_prep_device_scan(ioc);
_scsih_search_responding_sas_devices(ioc);
_scsih_search_responding_pcie_devices(ioc);
_scsih_search_responding_raid_devices(ioc);
_scsih_search_responding_expanders(ioc);
_scsih_error_recovery_delete_devices(ioc);
Expand Down

0 comments on commit ec051e5

Please sign in to comment.