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