scsi: mpt3sas: API 's to support NVMe drive addition to SML

Below Functions are added in various paths to support NVMe drive
addition.

_scsih_pcie_add_device
_scsih_pcie_device_add
_scsih_pcie_device_init_add
_scsih_check_pcie_access_status
_scsih_pcie_check_device

mpt3sas_get_pdev_by_handle

mpt3sas_config_get_pcie_device_pg0
mpt3sas_config_get_pcie_device_pg2

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>
This commit is contained in:
Suganath Prabu Subramani 2017-10-31 18:02:30 +05:30 коммит произвёл Martin K. Petersen
Родитель aff39e6121
Коммит c102e00cf4
3 изменённых файлов: 565 добавлений и 2 удалений

Просмотреть файл

@ -1464,6 +1464,10 @@ struct _sas_device *mpt3sas_get_sdev_by_addr(
struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
struct _sas_device *__mpt3sas_get_sdev_by_addr(
struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
struct _sas_device *mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
u16 handle);
struct _pcie_device *mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
u16 handle);
void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
struct _raid_device *
@ -1502,6 +1506,12 @@ int mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc,
int mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
u32 form, u32 handle);
int mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
u32 form, u32 handle);
int mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
u32 form, u32 handle);
int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
u16 sz);

Просмотреть файл

@ -150,6 +150,24 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid,
case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
desc = "driver_mapping";
break;
case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT:
desc = "sas_port";
break;
case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING:
desc = "ext_manufacturing";
break;
case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT:
desc = "pcie_io_unit";
break;
case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH:
desc = "pcie_switch";
break;
case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE:
desc = "pcie_device";
break;
case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK:
desc = "pcie_link";
break;
}
break;
}
@ -1052,6 +1070,88 @@ mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
return r;
}
/**
* mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
* @config_page: contents of the config page
* @form: GET_NEXT_HANDLE or HANDLE
* @handle: device handle
* Context: sleep.
*
* Returns 0 for success, non-zero for failure.
*/
int
mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
u32 form, u32 handle)
{
Mpi2ConfigRequest_t mpi_request;
int r;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
mpi_request.Header.PageNumber = 0;
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
if (r)
goto out;
mpi_request.PageAddress = cpu_to_le32(form | handle);
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
out:
return r;
}
/**
* mpt3sas_config_get_pcie_device_pg2 - obtain pcie device page 2
* @ioc: per adapter object
* @mpi_reply: reply mf payload returned from firmware
* @config_page: contents of the config page
* @form: GET_NEXT_HANDLE or HANDLE
* @handle: device handle
* Context: sleep.
*
* Returns 0 for success, non-zero for failure.
*/
int
mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
u32 form, u32 handle)
{
Mpi2ConfigRequest_t mpi_request;
int r;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
mpi_request.Header.PageVersion = MPI26_PCIEDEVICE2_PAGEVERSION;
mpi_request.Header.PageNumber = 2;
ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE);
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
if (r)
goto out;
mpi_request.PageAddress = cpu_to_le32(form | handle);
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
r = _config_request(ioc, &mpi_request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
out:
return r;
}
/**
* mpt3sas_config_get_number_hba_phys - obtain number of phys on the host
* @ioc: per adapter object

Просмотреть файл

@ -72,7 +72,7 @@ static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
struct _sas_device *sas_device);
static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
u8 retry_count, u8 is_pd);
static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle);
static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
/* global parameters */
@ -687,7 +687,7 @@ found_device:
* This searches for sas_device based on sas_address, then return sas_device
* object.
*/
static struct _sas_device *
struct _sas_device *
mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
struct _sas_device *sas_device;
@ -1033,6 +1033,55 @@ mpt3sas_get_pdev_by_idchannel(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
return pcie_device;
}
struct _pcie_device *
__mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
struct _pcie_device *pcie_device;
assert_spin_locked(&ioc->pcie_device_lock);
list_for_each_entry(pcie_device, &ioc->pcie_device_list, list)
if (pcie_device->handle == handle)
goto found_device;
list_for_each_entry(pcie_device, &ioc->pcie_device_init_list, list)
if (pcie_device->handle == handle)
goto found_device;
return NULL;
found_device:
pcie_device_get(pcie_device);
return pcie_device;
}
/**
* mpt3sas_get_pdev_by_handle - pcie device search
* @ioc: per adapter object
* @handle: Firmware device handle
*
* Context: This function will acquire ioc->pcie_device_lock and will release
* before returning the pcie_device object.
*
* This searches for pcie_device based on handle, then return pcie_device
* object.
*/
struct _pcie_device *
mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
struct _pcie_device *pcie_device;
unsigned long flags;
spin_lock_irqsave(&ioc->pcie_device_lock, flags);
pcie_device = __mpt3sas_get_pdev_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
return pcie_device;
}
/**
* _scsih_pcie_device_remove - remove pcie_device from list.
* @ioc: per adapter object
@ -1077,6 +1126,85 @@ _scsih_pcie_device_remove(struct MPT3SAS_ADAPTER *ioc,
pcie_device_put(pcie_device);
}
}
/**
* _scsih_pcie_device_add - add pcie_device object
* @ioc: per adapter object
* @pcie_device: pcie_device object
*
* This is added to the pcie_device_list link list.
*/
static void
_scsih_pcie_device_add(struct MPT3SAS_ADAPTER *ioc,
struct _pcie_device *pcie_device)
{
unsigned long flags;
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: handle (0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
pcie_device->handle, (unsigned long long)pcie_device->wwid));
if (pcie_device->enclosure_handle != 0)
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: enclosure logical id(0x%016llx), slot( %d)\n",
ioc->name, __func__,
(unsigned long long)pcie_device->enclosure_logical_id,
pcie_device->slot));
if (pcie_device->connector_name[0] != '\0')
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: enclosure level(0x%04x), connector name( %s)\n",
ioc->name, __func__, pcie_device->enclosure_level,
pcie_device->connector_name));
spin_lock_irqsave(&ioc->pcie_device_lock, flags);
pcie_device_get(pcie_device);
list_add_tail(&pcie_device->list, &ioc->pcie_device_list);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
if (scsi_add_device(ioc->shost, PCIE_CHANNEL, pcie_device->id, 0)) {
_scsih_pcie_device_remove(ioc, pcie_device);
} else if (!pcie_device->starget) {
if (!ioc->is_driver_loading) {
/*TODO-- Need to find out whether this condition will occur or not*/
clear_bit(pcie_device->handle, ioc->pend_os_device_add);
}
} else
clear_bit(pcie_device->handle, ioc->pend_os_device_add);
}
/*
* _scsih_pcie_device_init_add - insert pcie_device to the init list.
* @ioc: per adapter object
* @pcie_device: the pcie_device object
* Context: This function will acquire ioc->pcie_device_lock.
*
* Adding new object at driver load time to the ioc->pcie_device_init_list.
*/
static void
_scsih_pcie_device_init_add(struct MPT3SAS_ADAPTER *ioc,
struct _pcie_device *pcie_device)
{
unsigned long flags;
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: handle (0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
pcie_device->handle, (unsigned long long)pcie_device->wwid));
if (pcie_device->enclosure_handle != 0)
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: enclosure logical id(0x%016llx), slot( %d)\n",
ioc->name, __func__,
(unsigned long long)pcie_device->enclosure_logical_id,
pcie_device->slot));
if (pcie_device->connector_name[0] != '\0')
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: enclosure level(0x%04x), connector name( %s)\n",
ioc->name, __func__, pcie_device->enclosure_level,
pcie_device->connector_name));
spin_lock_irqsave(&ioc->pcie_device_lock, flags);
pcie_device_get(pcie_device);
list_add_tail(&pcie_device->list, &ioc->pcie_device_init_list);
_scsih_determine_boot_device(ioc, pcie_device, PCIE_CHANNEL);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
}
/**
* _scsih_raid_device_find_by_id - raid device search
* @ioc: per adapter object
@ -1287,6 +1415,23 @@ _scsih_is_end_device(u32 device_info)
return 0;
}
/**
* _scsih_is_nvme_device - determines if device is an nvme device
* @device_info: bitfield providing information about the device.
* Context: none
*
* Returns 1 if nvme device.
*/
static int
_scsih_is_nvme_device(u32 device_info)
{
if ((device_info & MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE)
== MPI26_PCIE_DEVINFO_NVME)
return 1;
else
return 0;
}
/**
* _scsih_scsi_lookup_get - returns scmd entry
* @ioc: per adapter object
@ -6335,6 +6480,314 @@ out:
}
/**
* _scsih_check_pcie_access_status - check access flags
* @ioc: per adapter object
* @wwid: wwid
* @handle: sas device handle
* @access_flags: errors returned during discovery of the device
*
* Return 0 for success, else failure
*/
static u8
_scsih_check_pcie_access_status(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
u16 handle, u8 access_status)
{
u8 rc = 1;
char *desc = NULL;
switch (access_status) {
case MPI26_PCIEDEV0_ASTATUS_NO_ERRORS:
case MPI26_PCIEDEV0_ASTATUS_NEEDS_INITIALIZATION:
rc = 0;
break;
case MPI26_PCIEDEV0_ASTATUS_CAPABILITY_FAILED:
desc = "PCIe device capability failed";
break;
case MPI26_PCIEDEV0_ASTATUS_DEVICE_BLOCKED:
desc = "PCIe device blocked";
break;
case MPI26_PCIEDEV0_ASTATUS_MEMORY_SPACE_ACCESS_FAILED:
desc = "PCIe device mem space access failed";
break;
case MPI26_PCIEDEV0_ASTATUS_UNSUPPORTED_DEVICE:
desc = "PCIe device unsupported";
break;
case MPI26_PCIEDEV0_ASTATUS_MSIX_REQUIRED:
desc = "PCIe device MSIx Required";
break;
case MPI26_PCIEDEV0_ASTATUS_INIT_FAIL_MAX:
desc = "PCIe device init fail max";
break;
case MPI26_PCIEDEV0_ASTATUS_UNKNOWN:
desc = "PCIe device status unknown";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_READY_TIMEOUT:
desc = "nvme ready timeout";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_DEVCFG_UNSUPPORTED:
desc = "nvme device configuration unsupported";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_IDENTIFY_FAILED:
desc = "nvme identify failed";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_QCONFIG_FAILED:
desc = "nvme qconfig failed";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_QCREATION_FAILED:
desc = "nvme qcreation failed";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_EVENTCFG_FAILED:
desc = "nvme eventcfg failed";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_GET_FEATURE_STAT_FAILED:
desc = "nvme get feature stat failed";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_IDLE_TIMEOUT:
desc = "nvme idle timeout";
break;
case MPI26_PCIEDEV0_ASTATUS_NVME_FAILURE_STATUS:
desc = "nvme failure status";
break;
default:
pr_err(MPT3SAS_FMT
" NVMe discovery error(0x%02x): wwid(0x%016llx),"
"handle(0x%04x)\n", ioc->name, access_status,
(unsigned long long)wwid, handle);
return rc;
}
if (!rc)
return rc;
pr_info(MPT3SAS_FMT
"NVMe discovery error(%s): wwid(0x%016llx), handle(0x%04x)\n",
ioc->name, desc,
(unsigned long long)wwid, handle);
return rc;
}
/**
* _scsih_pcie_check_device - checking device responsiveness
* @ioc: per adapter object
* @handle: attached device handle
*
* Returns nothing.
*/
static void
_scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
Mpi2ConfigReply_t mpi_reply;
Mpi26PCIeDevicePage0_t pcie_device_pg0;
u32 ioc_status;
struct _pcie_device *pcie_device;
u64 wwid;
unsigned long flags;
struct scsi_target *starget;
struct MPT3SAS_TARGET *sas_target_priv_data;
u32 device_info;
if ((mpt3sas_config_get_pcie_device_pg0(ioc, &mpi_reply,
&pcie_device_pg0, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, handle)))
return;
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
return;
/* check if this is end device */
device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo);
if (!(_scsih_is_nvme_device(device_info)))
return;
wwid = le64_to_cpu(pcie_device_pg0.WWID);
spin_lock_irqsave(&ioc->pcie_device_lock, flags);
pcie_device = __mpt3sas_get_pdev_by_wwid(ioc, wwid);
if (!pcie_device) {
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
return;
}
if (unlikely(pcie_device->handle != handle)) {
starget = pcie_device->starget;
sas_target_priv_data = starget->hostdata;
starget_printk(KERN_INFO, starget,
"handle changed from(0x%04x) to (0x%04x)!!!\n",
pcie_device->handle, handle);
sas_target_priv_data->handle = handle;
pcie_device->handle = handle;
if (le32_to_cpu(pcie_device_pg0.Flags) &
MPI26_PCIEDEV0_FLAGS_ENCL_LEVEL_VALID) {
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';
}
}
/* check if device is present */
if (!(le32_to_cpu(pcie_device_pg0.Flags) &
MPI26_PCIEDEV0_FLAGS_DEVICE_PRESENT)) {
pr_info(MPT3SAS_FMT
"device is not present handle(0x%04x), flags!!!\n",
ioc->name, handle);
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
pcie_device_put(pcie_device);
return;
}
/* check if there were any issues with discovery */
if (_scsih_check_pcie_access_status(ioc, wwid, handle,
pcie_device_pg0.AccessStatus)) {
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
pcie_device_put(pcie_device);
return;
}
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
pcie_device_put(pcie_device);
_scsih_ublock_io_device(ioc, wwid);
return;
}
/**
* _scsih_pcie_add_device - creating pcie device object
* @ioc: per adapter object
* @handle: pcie device handle
*
* Creating end device object, stored in ioc->pcie_device_list.
*
* Return 1 means queue the event later, 0 means complete the event
*/
static int
_scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
Mpi26PCIeDevicePage0_t pcie_device_pg0;
Mpi26PCIeDevicePage2_t pcie_device_pg2;
Mpi2ConfigReply_t mpi_reply;
Mpi2SasEnclosurePage0_t enclosure_pg0;
struct _pcie_device *pcie_device;
u32 pcie_device_type;
u32 ioc_status;
u64 wwid;
if ((mpt3sas_config_get_pcie_device_pg0(ioc, &mpi_reply,
&pcie_device_pg0, MPI26_PCIE_DEVICE_PGAD_FORM_HANDLE, handle))) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
return 0;
}
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_err(MPT3SAS_FMT
"failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
return 0;
}
set_bit(handle, ioc->pend_os_device_add);
wwid = le64_to_cpu(pcie_device_pg0.WWID);
/* check if device is present */
if (!(le32_to_cpu(pcie_device_pg0.Flags) &
MPI26_PCIEDEV0_FLAGS_DEVICE_PRESENT)) {
pr_err(MPT3SAS_FMT
"device is not present handle(0x04%x)!!!\n",
ioc->name, handle);
return 0;
}
/* check if there were any issues with discovery */
if (_scsih_check_pcie_access_status(ioc, wwid, handle,
pcie_device_pg0.AccessStatus))
return 0;
if (!(_scsih_is_nvme_device(le32_to_cpu(pcie_device_pg0.DeviceInfo))))
return 0;
pcie_device = mpt3sas_get_pdev_by_wwid(ioc, wwid);
if (pcie_device) {
clear_bit(handle, ioc->pend_os_device_add);
pcie_device_put(pcie_device);
return 0;
}
pcie_device = kzalloc(sizeof(struct _pcie_device), GFP_KERNEL);
if (!pcie_device) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
return 0;
}
kref_init(&pcie_device->refcount);
pcie_device->id = ioc->pcie_target_id++;
pcie_device->channel = PCIE_CHANNEL;
pcie_device->handle = handle;
pcie_device->device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo);
pcie_device->wwid = wwid;
pcie_device->port_num = pcie_device_pg0.PortNum;
pcie_device->fast_path = (le32_to_cpu(pcie_device_pg0.Flags) &
MPI26_PCIEDEV0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
pcie_device_type = pcie_device->device_info &
MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE;
pcie_device->enclosure_handle =
le16_to_cpu(pcie_device_pg0.EnclosureHandle);
if (pcie_device->enclosure_handle != 0)
pcie_device->slot = le16_to_cpu(pcie_device_pg0.Slot);
if (le16_to_cpu(pcie_device_pg0.Flags) &
MPI26_PCIEDEV0_FLAGS_ENCL_LEVEL_VALID) {
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';
}
/* get enclosure_logical_id */
if (pcie_device->enclosure_handle &&
!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
&enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
pcie_device->enclosure_handle)))
pcie_device->enclosure_logical_id =
le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
/* TODO -- Add device name once FW supports it */
if (mpt3sas_config_get_pcie_device_pg2(ioc, &mpi_reply,
&pcie_device_pg2, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
kfree(pcie_device);
return 0;
}
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
kfree(pcie_device);
return 0;
}
pcie_device->nvme_mdts =
le32_to_cpu(pcie_device_pg2.MaximumDataTransferSize);
if (ioc->wait_for_discovery_to_complete)
_scsih_pcie_device_init_add(ioc, pcie_device);
else
_scsih_pcie_device_add(ioc, pcie_device);
pcie_device_put(pcie_device);
return 0;
}
/**
* _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
* event