On 07/14/2017 03:22 PM, Suganath Prabu S wrote:
> After Controller reset, Scan and add nvme device back to the topology.
> 
> Signed-off-by: Chaitra P B <[email protected]>
> Signed-off-by: Suganath Prabu S <[email protected]>
> ---
>  drivers/scsi/mpt3sas/mpt3sas_scsih.c |  194 
> +++++++++++++++++++++++++++++++++-
>  1 files changed, 190 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
> b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
> index c5a131f..e3e803c 100644
> --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
> +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
> @@ -4869,6 +4869,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;
> @@ -5001,6 +5002,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) {
> @@ -5047,11 +5070,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;
> @@ -8512,6 +8534,130 @@ _scsih_search_responding_sas_devices(struct 
> MPT3SAS_ADAPTER *ioc)
>  }
>  
>  /**
> + * _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
>   * @wwid: world wide identifier for raid volume
> @@ -8863,6 +9009,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;
> @@ -8873,6 +9020,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;
> @@ -9098,7 +9246,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);
>  }
>  /**
> @@ -9148,6 +9333,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);
> 
Again; when using 'scan_start()/scan_finished()' callbacks this will
probably look a bit differently...

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Teamlead Storage & Networking
[email protected]                                   +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)

Reply via email to