diff options
| author | Kashyap, Desai <kashyap.desai@lsi.com> | 2009-12-16 08:31:58 -0500 |
|---|---|---|
| committer | James Bottomley <James.Bottomley@suse.de> | 2010-01-18 11:48:11 -0500 |
| commit | e0f553ab58f478321717100e44b28f765bd2a045 (patch) | |
| tree | 31e7c71f99046804d0c7c39779f1fd0315d3c145 | |
| parent | 65f89c2396aa113a06fe7e2f6ba46f0712cb4806 (diff) | |
[SCSI] 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 <kashyap.desai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
| -rw-r--r-- | drivers/message/fusion/mptsas.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 83873e3d0ce7..1b7f550daebc 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
| @@ -2686,6 +2686,187 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, | |||
| 2686 | return error; | 2686 | return error; |
| 2687 | } | 2687 | } |
| 2688 | 2688 | ||
| 2689 | struct rep_manu_request{ | ||
| 2690 | u8 smp_frame_type; | ||
| 2691 | u8 function; | ||
| 2692 | u8 reserved; | ||
| 2693 | u8 request_length; | ||
| 2694 | }; | ||
| 2695 | |||
| 2696 | struct rep_manu_reply{ | ||
| 2697 | u8 smp_frame_type; /* 0x41 */ | ||
| 2698 | u8 function; /* 0x01 */ | ||
| 2699 | u8 function_result; | ||
| 2700 | u8 response_length; | ||
| 2701 | u16 expander_change_count; | ||
| 2702 | u8 reserved0[2]; | ||
| 2703 | u8 sas_format:1; | ||
| 2704 | u8 reserved1:7; | ||
| 2705 | u8 reserved2[3]; | ||
| 2706 | u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN]; | ||
| 2707 | u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN]; | ||
| 2708 | u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN]; | ||
| 2709 | u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN]; | ||
| 2710 | u16 component_id; | ||
| 2711 | u8 component_revision_id; | ||
| 2712 | u8 reserved3; | ||
| 2713 | u8 vendor_specific[8]; | ||
| 2714 | }; | ||
| 2715 | |||
| 2716 | /** | ||
| 2717 | * mptsas_exp_repmanufacture_info - | ||
| 2718 | * @ioc: per adapter object | ||
| 2719 | * @sas_address: expander sas address | ||
| 2720 | * @edev: the sas_expander_device object | ||
| 2721 | * | ||
| 2722 | * Fills in the sas_expander_device object when SMP port is created. | ||
| 2723 | * | ||
| 2724 | * Returns 0 for success, non-zero for failure. | ||
| 2725 | */ | ||
| 2726 | static int | ||
| 2727 | mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc, | ||
| 2728 | u64 sas_address, struct sas_expander_device *edev) | ||
| 2729 | { | ||
| 2730 | MPT_FRAME_HDR *mf; | ||
| 2731 | SmpPassthroughRequest_t *smpreq; | ||
| 2732 | SmpPassthroughReply_t *smprep; | ||
| 2733 | struct rep_manu_reply *manufacture_reply; | ||
| 2734 | struct rep_manu_request *manufacture_request; | ||
| 2735 | int ret; | ||
| 2736 | int flagsLength; | ||
| 2737 | unsigned long timeleft; | ||
| 2738 | char *psge; | ||
| 2739 | unsigned long flags; | ||
| 2740 | void *data_out = NULL; | ||
| 2741 | dma_addr_t data_out_dma = 0; | ||
| 2742 | u32 sz; | ||
| 2743 | |||
| 2744 | spin_lock_irqsave(&ioc->taskmgmt_lock, flags); | ||
| 2745 | if (ioc->ioc_reset_in_progress) { | ||
| 2746 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 2747 | printk(MYIOC_s_INFO_FMT "%s: host reset in progress!\n", | ||
| 2748 | __func__, ioc->name); | ||
| 2749 | return -EFAULT; | ||
| 2750 | } | ||
| 2751 | spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); | ||
| 2752 | |||
| 2753 | ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex); | ||
| 2754 | if (ret) | ||
| 2755 | goto out; | ||
| 2756 | |||
| 2757 | mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc); | ||
| 2758 | if (!mf) { | ||
| 2759 | ret = -ENOMEM; | ||
| 2760 | goto out_unlock; | ||
| 2761 | } | ||
| 2762 | |||
| 2763 | smpreq = (SmpPassthroughRequest_t *)mf; | ||
| 2764 | memset(smpreq, 0, sizeof(*smpreq)); | ||
| 2765 | |||
| 2766 | sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply); | ||
| 2767 | |||
| 2768 | data_out = pci_alloc_consistent(ioc->pcidev, sz, &data_out_dma); | ||
| 2769 | if (!data_out) { | ||
| 2770 | printk(KERN_ERR "Memory allocation failure at %s:%d/%s()!\n", | ||
| 2771 | __FILE__, __LINE__, __func__); | ||
| 2772 | ret = -ENOMEM; | ||
| 2773 | goto put_mf; | ||
| 2774 | } | ||
| 2775 | |||
| 2776 | manufacture_request = data_out; | ||
| 2777 | manufacture_request->smp_frame_type = 0x40; | ||
| 2778 | manufacture_request->function = 1; | ||
| 2779 | manufacture_request->reserved = 0; | ||
| 2780 | manufacture_request->request_length = 0; | ||
| 2781 | |||
| 2782 | smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH; | ||
| 2783 | smpreq->PhysicalPort = 0xFF; | ||
| 2784 | *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address); | ||
| 2785 | smpreq->RequestDataLength = sizeof(struct rep_manu_request); | ||
| 2786 | |||
| 2787 | psge = (char *) | ||
| 2788 | (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4)); | ||
| 2789 | |||
| 2790 | flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 2791 | MPI_SGE_FLAGS_SYSTEM_ADDRESS | | ||
| 2792 | MPI_SGE_FLAGS_HOST_TO_IOC | | ||
| 2793 | MPI_SGE_FLAGS_END_OF_BUFFER; | ||
| 2794 | flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT; | ||
| 2795 | flagsLength |= sizeof(struct rep_manu_request); | ||
| 2796 | |||
| 2797 | ioc->add_sge(psge, flagsLength, data_out_dma); | ||
| 2798 | psge += ioc->SGE_size; | ||
| 2799 | |||
| 2800 | flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT | | ||
| 2801 | MPI_SGE_FLAGS_SYSTEM_ADDRESS | | ||
| 2802 | MPI_SGE_FLAGS_IOC_TO_HOST | | ||
| 2803 | MPI_SGE_FLAGS_END_OF_BUFFER; | ||
| 2804 | flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT; | ||
| 2805 | flagsLength |= sizeof(struct rep_manu_reply); | ||
| 2806 | ioc->add_sge(psge, flagsLength, data_out_dma + | ||
| 2807 | sizeof(struct rep_manu_request)); | ||
| 2808 | |||
| 2809 | INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status) | ||
| 2810 | mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf); | ||
| 2811 | |||
| 2812 | timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ); | ||
| 2813 | if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
| 2814 | ret = -ETIME; | ||
| 2815 | mpt_free_msg_frame(ioc, mf); | ||
| 2816 | mf = NULL; | ||
| 2817 | if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
| 2818 | goto out_free; | ||
| 2819 | if (!timeleft) | ||
| 2820 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
| 2821 | goto out_free; | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | mf = NULL; | ||
| 2825 | |||
| 2826 | if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) { | ||
| 2827 | u8 *tmp; | ||
| 2828 | |||
| 2829 | smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply; | ||
| 2830 | if (le16_to_cpu(smprep->ResponseDataLength) != | ||
| 2831 | sizeof(struct rep_manu_reply)) | ||
| 2832 | goto out_free; | ||
| 2833 | |||
| 2834 | manufacture_reply = data_out + sizeof(struct rep_manu_request); | ||
| 2835 | strncpy(edev->vendor_id, manufacture_reply->vendor_id, | ||
| 2836 | SAS_EXPANDER_VENDOR_ID_LEN); | ||
| 2837 | strncpy(edev->product_id, manufacture_reply->product_id, | ||
| 2838 | SAS_EXPANDER_PRODUCT_ID_LEN); | ||
| 2839 | strncpy(edev->product_rev, manufacture_reply->product_rev, | ||
| 2840 | SAS_EXPANDER_PRODUCT_REV_LEN); | ||
| 2841 | edev->level = manufacture_reply->sas_format; | ||
| 2842 | if (manufacture_reply->sas_format) { | ||
| 2843 | strncpy(edev->component_vendor_id, | ||
| 2844 | manufacture_reply->component_vendor_id, | ||
| 2845 | SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); | ||
| 2846 | tmp = (u8 *)&manufacture_reply->component_id; | ||
| 2847 | edev->component_id = tmp[0] << 8 | tmp[1]; | ||
| 2848 | edev->component_revision_id = | ||
| 2849 | manufacture_reply->component_revision_id; | ||
| 2850 | } | ||
| 2851 | } else { | ||
| 2852 | printk(MYIOC_s_ERR_FMT | ||
| 2853 | "%s: smp passthru reply failed to be returned\n", | ||
| 2854 | ioc->name, __func__); | ||
| 2855 | ret = -ENXIO; | ||
| 2856 | } | ||
| 2857 | out_free: | ||
| 2858 | if (data_out_dma) | ||
| 2859 | pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma); | ||
| 2860 | put_mf: | ||
| 2861 | if (mf) | ||
| 2862 | mpt_free_msg_frame(ioc, mf); | ||
| 2863 | out_unlock: | ||
| 2864 | CLEAR_MGMT_STATUS(ioc->sas_mgmt.status) | ||
| 2865 | mutex_unlock(&ioc->sas_mgmt.mutex); | ||
| 2866 | out: | ||
| 2867 | return ret; | ||
| 2868 | } | ||
| 2869 | |||
| 2689 | static void | 2870 | static void |
| 2690 | mptsas_parse_device_info(struct sas_identify *identify, | 2871 | mptsas_parse_device_info(struct sas_identify *identify, |
| 2691 | struct mptsas_devinfo *device_info) | 2872 | struct mptsas_devinfo *device_info) |
| @@ -2967,6 +3148,11 @@ static int mptsas_probe_one_phy(struct device *dev, | |||
| 2967 | goto out; | 3148 | goto out; |
| 2968 | } | 3149 | } |
| 2969 | mptsas_set_rphy(ioc, phy_info, rphy); | 3150 | mptsas_set_rphy(ioc, phy_info, rphy); |
| 3151 | if (identify.device_type == SAS_EDGE_EXPANDER_DEVICE || | ||
| 3152 | identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) | ||
| 3153 | mptsas_exp_repmanufacture_info(ioc, | ||
| 3154 | identify.sas_address, | ||
| 3155 | rphy_to_expander_device(rphy)); | ||
| 2970 | } | 3156 | } |
| 2971 | 3157 | ||
| 2972 | out: | 3158 | out: |
