aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/message/fusion/mptsas.c186
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
2689struct rep_manu_request{
2690 u8 smp_frame_type;
2691 u8 function;
2692 u8 reserved;
2693 u8 request_length;
2694};
2695
2696struct 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 */
2726static int
2727mptsas_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 }
2857out_free:
2858 if (data_out_dma)
2859 pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma);
2860put_mf:
2861 if (mf)
2862 mpt_free_msg_frame(ioc, mf);
2863out_unlock:
2864 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2865 mutex_unlock(&ioc->sas_mgmt.mutex);
2866out:
2867 return ret;
2868 }
2869
2689static void 2870static void
2690mptsas_parse_device_info(struct sas_identify *identify, 2871mptsas_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: