aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/message/fusion/mptsas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/message/fusion/mptsas.c')
-rw-r--r--drivers/message/fusion/mptsas.c211
1 files changed, 206 insertions, 5 deletions
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 83873e3d0ce7..c20bbe45da82 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1075,6 +1075,19 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
1075 return 0; 1075 return 0;
1076} 1076}
1077 1077
1078static void
1079mptsas_block_io_sdev(struct scsi_device *sdev, void *data)
1080{
1081 scsi_device_set_state(sdev, SDEV_BLOCK);
1082}
1083
1084static void
1085mptsas_block_io_starget(struct scsi_target *starget)
1086{
1087 if (starget)
1088 starget_for_each_device(starget, NULL, mptsas_block_io_sdev);
1089}
1090
1078/** 1091/**
1079 * mptsas_target_reset_queue 1092 * mptsas_target_reset_queue
1080 * 1093 *
@@ -1098,10 +1111,11 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc,
1098 id = sas_event_data->TargetID; 1111 id = sas_event_data->TargetID;
1099 channel = sas_event_data->Bus; 1112 channel = sas_event_data->Bus;
1100 1113
1101 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id))) 1114 vtarget = mptsas_find_vtarget(ioc, channel, id);
1102 return; 1115 if (vtarget) {
1103 1116 mptsas_block_io_starget(vtarget->starget);
1104 vtarget->deleted = 1; /* block IO */ 1117 vtarget->deleted = 1; /* block IO */
1118 }
1105 1119
1106 target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event), 1120 target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
1107 GFP_ATOMIC); 1121 GFP_ATOMIC);
@@ -1868,7 +1882,8 @@ mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1868 if (ioc->sas_discovery_quiesce_io) 1882 if (ioc->sas_discovery_quiesce_io)
1869 return SCSI_MLQUEUE_HOST_BUSY; 1883 return SCSI_MLQUEUE_HOST_BUSY;
1870 1884
1871// scsi_print_command(SCpnt); 1885 if (ioc->debug_level & MPT_DEBUG_SCSI)
1886 scsi_print_command(SCpnt);
1872 1887
1873 return mptscsih_qcmd(SCpnt,done); 1888 return mptscsih_qcmd(SCpnt,done);
1874} 1889}
@@ -2686,6 +2701,187 @@ mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2686 return error; 2701 return error;
2687} 2702}
2688 2703
2704struct rep_manu_request{
2705 u8 smp_frame_type;
2706 u8 function;
2707 u8 reserved;
2708 u8 request_length;
2709};
2710
2711struct rep_manu_reply{
2712 u8 smp_frame_type; /* 0x41 */
2713 u8 function; /* 0x01 */
2714 u8 function_result;
2715 u8 response_length;
2716 u16 expander_change_count;
2717 u8 reserved0[2];
2718 u8 sas_format:1;
2719 u8 reserved1:7;
2720 u8 reserved2[3];
2721 u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
2722 u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
2723 u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
2724 u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
2725 u16 component_id;
2726 u8 component_revision_id;
2727 u8 reserved3;
2728 u8 vendor_specific[8];
2729};
2730
2731/**
2732 * mptsas_exp_repmanufacture_info -
2733 * @ioc: per adapter object
2734 * @sas_address: expander sas address
2735 * @edev: the sas_expander_device object
2736 *
2737 * Fills in the sas_expander_device object when SMP port is created.
2738 *
2739 * Returns 0 for success, non-zero for failure.
2740 */
2741static int
2742mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
2743 u64 sas_address, struct sas_expander_device *edev)
2744{
2745 MPT_FRAME_HDR *mf;
2746 SmpPassthroughRequest_t *smpreq;
2747 SmpPassthroughReply_t *smprep;
2748 struct rep_manu_reply *manufacture_reply;
2749 struct rep_manu_request *manufacture_request;
2750 int ret;
2751 int flagsLength;
2752 unsigned long timeleft;
2753 char *psge;
2754 unsigned long flags;
2755 void *data_out = NULL;
2756 dma_addr_t data_out_dma = 0;
2757 u32 sz;
2758
2759 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2760 if (ioc->ioc_reset_in_progress) {
2761 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2762 printk(MYIOC_s_INFO_FMT "%s: host reset in progress!\n",
2763 __func__, ioc->name);
2764 return -EFAULT;
2765 }
2766 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2767
2768 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2769 if (ret)
2770 goto out;
2771
2772 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2773 if (!mf) {
2774 ret = -ENOMEM;
2775 goto out_unlock;
2776 }
2777
2778 smpreq = (SmpPassthroughRequest_t *)mf;
2779 memset(smpreq, 0, sizeof(*smpreq));
2780
2781 sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
2782
2783 data_out = pci_alloc_consistent(ioc->pcidev, sz, &data_out_dma);
2784 if (!data_out) {
2785 printk(KERN_ERR "Memory allocation failure at %s:%d/%s()!\n",
2786 __FILE__, __LINE__, __func__);
2787 ret = -ENOMEM;
2788 goto put_mf;
2789 }
2790
2791 manufacture_request = data_out;
2792 manufacture_request->smp_frame_type = 0x40;
2793 manufacture_request->function = 1;
2794 manufacture_request->reserved = 0;
2795 manufacture_request->request_length = 0;
2796
2797 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2798 smpreq->PhysicalPort = 0xFF;
2799 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2800 smpreq->RequestDataLength = sizeof(struct rep_manu_request);
2801
2802 psge = (char *)
2803 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2804
2805 flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2806 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2807 MPI_SGE_FLAGS_HOST_TO_IOC |
2808 MPI_SGE_FLAGS_END_OF_BUFFER;
2809 flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2810 flagsLength |= sizeof(struct rep_manu_request);
2811
2812 ioc->add_sge(psge, flagsLength, data_out_dma);
2813 psge += ioc->SGE_size;
2814
2815 flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2816 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2817 MPI_SGE_FLAGS_IOC_TO_HOST |
2818 MPI_SGE_FLAGS_END_OF_BUFFER;
2819 flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2820 flagsLength |= sizeof(struct rep_manu_reply);
2821 ioc->add_sge(psge, flagsLength, data_out_dma +
2822 sizeof(struct rep_manu_request));
2823
2824 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2825 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2826
2827 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2828 if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2829 ret = -ETIME;
2830 mpt_free_msg_frame(ioc, mf);
2831 mf = NULL;
2832 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2833 goto out_free;
2834 if (!timeleft)
2835 mpt_HardResetHandler(ioc, CAN_SLEEP);
2836 goto out_free;
2837 }
2838
2839 mf = NULL;
2840
2841 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
2842 u8 *tmp;
2843
2844 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2845 if (le16_to_cpu(smprep->ResponseDataLength) !=
2846 sizeof(struct rep_manu_reply))
2847 goto out_free;
2848
2849 manufacture_reply = data_out + sizeof(struct rep_manu_request);
2850 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
2851 SAS_EXPANDER_VENDOR_ID_LEN);
2852 strncpy(edev->product_id, manufacture_reply->product_id,
2853 SAS_EXPANDER_PRODUCT_ID_LEN);
2854 strncpy(edev->product_rev, manufacture_reply->product_rev,
2855 SAS_EXPANDER_PRODUCT_REV_LEN);
2856 edev->level = manufacture_reply->sas_format;
2857 if (manufacture_reply->sas_format) {
2858 strncpy(edev->component_vendor_id,
2859 manufacture_reply->component_vendor_id,
2860 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
2861 tmp = (u8 *)&manufacture_reply->component_id;
2862 edev->component_id = tmp[0] << 8 | tmp[1];
2863 edev->component_revision_id =
2864 manufacture_reply->component_revision_id;
2865 }
2866 } else {
2867 printk(MYIOC_s_ERR_FMT
2868 "%s: smp passthru reply failed to be returned\n",
2869 ioc->name, __func__);
2870 ret = -ENXIO;
2871 }
2872out_free:
2873 if (data_out_dma)
2874 pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma);
2875put_mf:
2876 if (mf)
2877 mpt_free_msg_frame(ioc, mf);
2878out_unlock:
2879 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2880 mutex_unlock(&ioc->sas_mgmt.mutex);
2881out:
2882 return ret;
2883 }
2884
2689static void 2885static void
2690mptsas_parse_device_info(struct sas_identify *identify, 2886mptsas_parse_device_info(struct sas_identify *identify,
2691 struct mptsas_devinfo *device_info) 2887 struct mptsas_devinfo *device_info)
@@ -2967,6 +3163,11 @@ static int mptsas_probe_one_phy(struct device *dev,
2967 goto out; 3163 goto out;
2968 } 3164 }
2969 mptsas_set_rphy(ioc, phy_info, rphy); 3165 mptsas_set_rphy(ioc, phy_info, rphy);
3166 if (identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
3167 identify.device_type == SAS_FANOUT_EXPANDER_DEVICE)
3168 mptsas_exp_repmanufacture_info(ioc,
3169 identify.sas_address,
3170 rphy_to_expander_device(rphy));
2970 } 3171 }
2971 3172
2972 out: 3173 out: