aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_attr.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2009-10-02 15:16:56 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:01:41 -0500
commit0d87841997125971b7a39d21d1435054f91884c3 (patch)
treea30a4fe442ddc654ef170b40e7e2e66199bbad18 /drivers/scsi/lpfc/lpfc_attr.c
parent6a9c52cf22e4ca13816bb2bd9899129cd4445de7 (diff)
[SCSI] lpfc 8.3.5: Add AER support
Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_attr.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index e058f1018ff2..82005b8ad957 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -23,6 +23,7 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/pci.h> 24#include <linux/pci.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/aer.h>
26 27
27#include <scsi/scsi.h> 28#include <scsi/scsi.h>
28#include <scsi/scsi_device.h> 29#include <scsi/scsi_device.h>
@@ -2766,6 +2767,179 @@ static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
2766 lpfc_link_speed_show, lpfc_link_speed_store); 2767 lpfc_link_speed_show, lpfc_link_speed_store);
2767 2768
2768/* 2769/*
2770# lpfc_aer_support: Support PCIe device Advanced Error Reporting (AER)
2771# 0 = aer disabled or not supported
2772# 1 = aer supported and enabled (default)
2773# Value range is [0,1]. Default value is 1.
2774*/
2775
2776/**
2777 * lpfc_aer_support_store - Set the adapter for aer support
2778 *
2779 * @dev: class device that is converted into a Scsi_host.
2780 * @attr: device attribute, not used.
2781 * @buf: containing the string "selective".
2782 * @count: unused variable.
2783 *
2784 * Description:
2785 * If the val is 1 and currently the device's AER capability was not
2786 * enabled, invoke the kernel's enable AER helper routine, trying to
2787 * enable the device's AER capability. If the helper routine enabling
2788 * AER returns success, update the device's cfg_aer_support flag to
2789 * indicate AER is supported by the device; otherwise, if the device
2790 * AER capability is already enabled to support AER, then do nothing.
2791 *
2792 * If the val is 0 and currently the device's AER support was enabled,
2793 * invoke the kernel's disable AER helper routine. After that, update
2794 * the device's cfg_aer_support flag to indicate AER is not supported
2795 * by the device; otherwise, if the device AER capability is already
2796 * disabled from supporting AER, then do nothing.
2797 *
2798 * Returns:
2799 * length of the buf on success if val is in range the intended mode
2800 * is supported.
2801 * -EINVAL if val out of range or intended mode is not supported.
2802 **/
2803static ssize_t
2804lpfc_aer_support_store(struct device *dev, struct device_attribute *attr,
2805 const char *buf, size_t count)
2806{
2807 struct Scsi_Host *shost = class_to_shost(dev);
2808 struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
2809 struct lpfc_hba *phba = vport->phba;
2810 int val = 0, rc = -EINVAL;
2811
2812 if (!isdigit(buf[0]))
2813 return -EINVAL;
2814 if (sscanf(buf, "%i", &val) != 1)
2815 return -EINVAL;
2816
2817 switch (val) {
2818 case 0:
2819 if (phba->hba_flag & HBA_AER_ENABLED) {
2820 rc = pci_disable_pcie_error_reporting(phba->pcidev);
2821 if (!rc) {
2822 spin_lock_irq(&phba->hbalock);
2823 phba->hba_flag &= ~HBA_AER_ENABLED;
2824 spin_unlock_irq(&phba->hbalock);
2825 phba->cfg_aer_support = 0;
2826 rc = strlen(buf);
2827 } else
2828 rc = -EINVAL;
2829 } else
2830 phba->cfg_aer_support = 0;
2831 rc = strlen(buf);
2832 break;
2833 case 1:
2834 if (!(phba->hba_flag & HBA_AER_ENABLED)) {
2835 rc = pci_enable_pcie_error_reporting(phba->pcidev);
2836 if (!rc) {
2837 spin_lock_irq(&phba->hbalock);
2838 phba->hba_flag |= HBA_AER_ENABLED;
2839 spin_unlock_irq(&phba->hbalock);
2840 phba->cfg_aer_support = 1;
2841 rc = strlen(buf);
2842 } else
2843 rc = -EINVAL;
2844 } else
2845 phba->cfg_aer_support = 1;
2846 rc = strlen(buf);
2847 break;
2848 default:
2849 rc = -EINVAL;
2850 break;
2851 }
2852 return rc;
2853}
2854
2855static int lpfc_aer_support = 1;
2856module_param(lpfc_aer_support, int, 1);
2857MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support");
2858lpfc_param_show(aer_support)
2859
2860/**
2861 * lpfc_aer_support_init - Set the initial adapters aer support flag
2862 * @phba: lpfc_hba pointer.
2863 * @val: link speed value.
2864 *
2865 * Description:
2866 * If val is in a valid range [0,1], then set the adapter's initial
2867 * cfg_aer_support field. It will be up to the driver's probe_one
2868 * routine to determine whether the device's AER support can be set
2869 * or not.
2870 *
2871 * Notes:
2872 * If the value is not in range log a kernel error message, and
2873 * choose the default value of setting AER support and return.
2874 *
2875 * Returns:
2876 * zero if val saved.
2877 * -EINVAL val out of range
2878 **/
2879static int
2880lpfc_aer_support_init(struct lpfc_hba *phba, int val)
2881{
2882 if (val == 0 || val == 1) {
2883 phba->cfg_aer_support = val;
2884 return 0;
2885 }
2886 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2887 "2712 lpfc_aer_support attribute value %d out "
2888 "of range, allowed values are 0|1, setting it "
2889 "to default value of 1\n", val);
2890 phba->cfg_aer_support = 1;
2891 return -EINVAL;
2892}
2893
2894static DEVICE_ATTR(lpfc_aer_support, S_IRUGO | S_IWUSR,
2895 lpfc_aer_support_show, lpfc_aer_support_store);
2896
2897/**
2898 * lpfc_aer_cleanup_state - Clean up aer state to the aer enabled device
2899 * @dev: class device that is converted into a Scsi_host.
2900 * @attr: device attribute, not used.
2901 * @buf: containing the string "selective".
2902 * @count: unused variable.
2903 *
2904 * Description:
2905 * If the @buf contains 1 and the device currently has the AER support
2906 * enabled, then invokes the kernel AER helper routine
2907 * pci_cleanup_aer_uncorrect_error_status to clean up the uncorrectable
2908 * error status register.
2909 *
2910 * Notes:
2911 *
2912 * Returns:
2913 * -EINVAL if the buf does not contain the 1 or the device is not currently
2914 * enabled with the AER support.
2915 **/
2916static ssize_t
2917lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr,
2918 const char *buf, size_t count)
2919{
2920 struct Scsi_Host *shost = class_to_shost(dev);
2921 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2922 struct lpfc_hba *phba = vport->phba;
2923 int val, rc = -1;
2924
2925 if (!isdigit(buf[0]))
2926 return -EINVAL;
2927 if (sscanf(buf, "%i", &val) != 1)
2928 return -EINVAL;
2929
2930 if (val == 1 && phba->hba_flag & HBA_AER_ENABLED)
2931 rc = pci_cleanup_aer_uncorrect_error_status(phba->pcidev);
2932
2933 if (rc == 0)
2934 return strlen(buf);
2935 else
2936 return -EINVAL;
2937}
2938
2939static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL,
2940 lpfc_aer_cleanup_state);
2941
2942/*
2769# lpfc_fcp_class: Determines FC class to use for the FCP protocol. 2943# lpfc_fcp_class: Determines FC class to use for the FCP protocol.
2770# Value range is [2,3]. Default value is 3. 2944# Value range is [2,3]. Default value is 3.
2771*/ 2945*/
@@ -3068,6 +3242,8 @@ struct device_attribute *lpfc_hba_attrs[] = {
3068 &dev_attr_lpfc_max_scsicmpl_time, 3242 &dev_attr_lpfc_max_scsicmpl_time,
3069 &dev_attr_lpfc_stat_data_ctrl, 3243 &dev_attr_lpfc_stat_data_ctrl,
3070 &dev_attr_lpfc_prot_sg_seg_cnt, 3244 &dev_attr_lpfc_prot_sg_seg_cnt,
3245 &dev_attr_lpfc_aer_support,
3246 &dev_attr_lpfc_aer_state_cleanup,
3071 NULL, 3247 NULL,
3072}; 3248};
3073 3249
@@ -4244,6 +4420,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
4244 lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); 4420 lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
4245 lpfc_enable_fip_init(phba, lpfc_enable_fip); 4421 lpfc_enable_fip_init(phba, lpfc_enable_fip);
4246 lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); 4422 lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
4423 lpfc_aer_support_init(phba, lpfc_aer_support);
4247 4424
4248 return; 4425 return;
4249} 4426}