mptfusion: Added sysfs expander manufacture information at the time of expander add.
Subsystems (2)
PATCH 2/5 mptfusion: Added sysfs expander manufacture information at the time of expander add.
Added new function mptsas_exp_manufacture_info, which will obtain the REPORT_MANUFACTURING, and fill the details into the sas_expander_device object when the expander port is created.
Signed-off-by Kashyap Desai <[email protected]>
---
drivers/message/fusion/mptsas.c +186 -0
@@ -2686,6 +2686,187 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,return error; } +struct rep_manu_request { +u8 smp_frame_type; +u8 function; +u8 reserved; +u8 request_length; +}; + +struct rep_manu_reply { +u8 smp_frame_type;/* 0x41 */ +u8 function;/* 0x01 */ +u8 function_result; +u8 response_length; +u16 expander_change_count; +u8 reserved0[2 ]; +u8 sas_format:1 ; +u8 reserved1:7 ; +u8 reserved2[3 ]; +u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN ]; +u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN ]; +u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN ]; +u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN ]; +u16 component_id; +u8 component_revision_id; +u8 reserved3; +u8 vendor_specific[8 ]; +}; + +/** +* mptsas_exp_repmanufacture_info - +* @ioc: per adapter object +* @sas_address: expander sas address +* @edev: the sas_expander_device object +* +* Fills in the sas_expander_device object when SMP port is created. +* +* Returns 0 for success, non-zero for failure. +*/ +static int +mptsas_exp_repmanufacture_info (MPT_ADAPTER *ioc, +u64 sas_address,struct sas_expander_device *edev) +{ +MPT_FRAME_HDR *mf; +SmpPassthroughRequest_t *smpreq; +SmpPassthroughReply_t *smprep; +struct rep_manu_reply *manufacture_reply; +struct rep_manu_request *manufacture_request; +int ret; +int flagsLength; +unsigned long timeleft; +char *psge; +unsigned long flags; +void *data_out =NULL ; +dma_addr_t data_out_dma =0 ; +u32 sz; + +spin_lock_irqsave (&ioc->taskmgmt_lock, flags); +if (ioc->ioc_reset_in_progress) { +spin_unlock_irqrestore (&ioc->taskmgmt_lock, flags); +printk (MYIOC_s_INFO_FMT"%s: host reset in progress!\n" , + __func__, ioc->name); +return -EFAULT ; + } +spin_unlock_irqrestore (&ioc->taskmgmt_lock, flags); + + ret =mutex_lock_interruptible (&ioc->sas_mgmt.mutex); +if (ret) + goto out; + + mf =mpt_get_msg_frame (mptsasMgmtCtx, ioc); +if (!mf) { + ret = -ENOMEM ; + goto out_unlock; + } + + smpreq = (SmpPassthroughRequest_t *)mf; +memset (smpreq,0 ,sizeof (*smpreq)); + + sz =sizeof (struct rep_manu_request ) +sizeof (struct rep_manu_reply ); + + data_out =pci_alloc_consistent (ioc->pcidev, sz, &data_out_dma); +if (!data_out) { +printk (KERN_ERR "Memory allocation failure at %s:%d/%s()!\n" , + __FILE__, __LINE__, __func__); + ret = -ENOMEM ; + goto put_mf; + } + + manufacture_request = data_out; + manufacture_request->smp_frame_type =0x40 ; + manufacture_request->function =1 ; + manufacture_request->reserved =0 ; + manufacture_request->request_length =0 ; + + smpreq->Function =MPI_FUNCTION_SMP_PASSTHROUGH ; + smpreq->PhysicalPort =0xFF ; + *((u64 *)&smpreq->SASAddress) =cpu_to_le64 (sas_address); + smpreq->RequestDataLength =sizeof (struct rep_manu_request ); + + psge = (char *) + (((int *) mf) + (offsetof(SmpPassthroughRequest_t , SGL) /4 )); + + flagsLength =MPI_SGE_FLAGS_SIMPLE_ELEMENT | +MPI_SGE_FLAGS_SYSTEM_ADDRESS | +MPI_SGE_FLAGS_HOST_TO_IOC | +MPI_SGE_FLAGS_END_OF_BUFFER ; + flagsLength = flagsLength <<MPI_SGE_FLAGS_SHIFT ; + flagsLength |=sizeof (struct rep_manu_request ); + + ioc->add_sge (psge, flagsLength, data_out_dma); + psge += ioc->SGE_size; + + flagsLength =MPI_SGE_FLAGS_SIMPLE_ELEMENT | +MPI_SGE_FLAGS_SYSTEM_ADDRESS | +MPI_SGE_FLAGS_IOC_TO_HOST | +MPI_SGE_FLAGS_END_OF_BUFFER ; + flagsLength = flagsLength <<MPI_SGE_FLAGS_SHIFT ; + flagsLength |=sizeof (struct rep_manu_reply ); + ioc->add_sge (psge, flagsLength, data_out_dma + +sizeof (struct rep_manu_request )); + + INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status) +mpt_put_msg_frame (mptsasMgmtCtx, ioc, mf); + + timeleft =wait_for_completion_timeout (&ioc->sas_mgmt.done,10 *HZ ); +if (!(ioc->sas_mgmt.status &MPT_MGMT_STATUS_COMMAND_GOOD )) { + ret = -ETIME ; +mpt_free_msg_frame (ioc, mf); + mf =NULL ; +if (ioc->sas_mgmt.status &MPT_MGMT_STATUS_DID_IOCRESET ) + goto out_free; +if (!timeleft) +mpt_HardResetHandler (ioc,CAN_SLEEP ); + goto out_free; + } + + mf =NULL ; + +if (ioc->sas_mgmt.status &MPT_MGMT_STATUS_RF_VALID ) { +u8 *tmp; + + smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply; +if (le16_to_cpu (smprep->ResponseDataLength) != +sizeof (struct rep_manu_reply )) + goto out_free; + + manufacture_reply = data_out +sizeof (struct rep_manu_request ); +strncpy (edev->vendor_id, manufacture_reply->vendor_id, +SAS_EXPANDER_VENDOR_ID_LEN ); +strncpy (edev->product_id, manufacture_reply->product_id, +SAS_EXPANDER_PRODUCT_ID_LEN ); +strncpy (edev->product_rev, manufacture_reply->product_rev, +SAS_EXPANDER_PRODUCT_REV_LEN ); + edev->level = manufacture_reply->sas_format; +if (manufacture_reply->sas_format) { +strncpy (edev->component_vendor_id, + manufacture_reply->component_vendor_id, +SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN ); + tmp = (u8 *)&manufacture_reply->component_id; + edev->component_id = tmp[0 ] <<8 | tmp[1 ]; + edev->component_revision_id = + manufacture_reply->component_revision_id; + } + }else { +printk (MYIOC_s_ERR_FMT +"%s: smp passthru reply failed to be returned\n" , + ioc->name, __func__); + ret = -ENXIO ; + } +out_free: +if (data_out_dma) +pci_free_consistent (ioc->pcidev, sz, data_out, data_out_dma); +put_mf: +if (mf) +mpt_free_msg_frame (ioc, mf); +out_unlock: + CLEAR_MGMT_STATUS(ioc->sas_mgmt.status) +mutex_unlock (&ioc->sas_mgmt.mutex); +out: +return ret; + } +static void mptsas_parse_device_info (struct sas_identify *identify,struct mptsas_devinfo *device_info)
@@ -2967,6 +3148,11 @@ static int mptsas_probe_one_phy(struct device *dev, goto out; }mptsas_set_rphy (ioc, phy_info, rphy); +if (identify.device_type ==SAS_EDGE_EXPANDER_DEVICE || + identify.device_type ==SAS_FANOUT_EXPANDER_DEVICE ) +mptsas_exp_repmanufacture_info (ioc, + identify.sas_address, +rphy_to_expander_device (rphy)); } out: