diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-10-02 15:16:56 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:01:41 -0500 |
commit | 0d87841997125971b7a39d21d1435054f91884c3 (patch) | |
tree | a30a4fe442ddc654ef170b40e7e2e66199bbad18 | |
parent | 6a9c52cf22e4ca13816bb2bd9899129cd4445de7 (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>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 177 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 96 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 27 |
4 files changed, 278 insertions, 24 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index c618eaf3c0c8..e5ebb5343421 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -534,6 +534,7 @@ struct lpfc_hba { | |||
534 | #define ASYNC_EVENT 0x80 | 534 | #define ASYNC_EVENT 0x80 |
535 | #define LINK_DISABLED 0x100 /* Link disabled by user */ | 535 | #define LINK_DISABLED 0x100 /* Link disabled by user */ |
536 | #define FCF_DISC_INPROGRESS 0x200 /* FCF discovery in progress */ | 536 | #define FCF_DISC_INPROGRESS 0x200 /* FCF discovery in progress */ |
537 | #define HBA_AER_ENABLED 0x800 /* AER enabled with HBA */ | ||
537 | struct lpfc_dmabuf slim2p; | 538 | struct lpfc_dmabuf slim2p; |
538 | 539 | ||
539 | MAILBOX_t *mbox; | 540 | MAILBOX_t *mbox; |
@@ -607,6 +608,7 @@ struct lpfc_hba { | |||
607 | uint32_t cfg_enable_bg; | 608 | uint32_t cfg_enable_bg; |
608 | uint32_t cfg_enable_fip; | 609 | uint32_t cfg_enable_fip; |
609 | uint32_t cfg_log_verbose; | 610 | uint32_t cfg_log_verbose; |
611 | uint32_t cfg_aer_support; | ||
610 | 612 | ||
611 | lpfc_vpd_t vpd; /* vital product data */ | 613 | lpfc_vpd_t vpd; /* vital product data */ |
612 | 614 | ||
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 | **/ | ||
2803 | static ssize_t | ||
2804 | lpfc_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 | |||
2855 | static int lpfc_aer_support = 1; | ||
2856 | module_param(lpfc_aer_support, int, 1); | ||
2857 | MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support"); | ||
2858 | lpfc_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 | **/ | ||
2879 | static int | ||
2880 | lpfc_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 | |||
2894 | static 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 | **/ | ||
2916 | static ssize_t | ||
2917 | lpfc_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 | |||
2939 | static 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 | } |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 12ab1eae47f9..61925836a09e 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | #include <linux/ctype.h> | 30 | #include <linux/ctype.h> |
31 | #include <linux/aer.h> | ||
31 | 32 | ||
32 | #include <scsi/scsi.h> | 33 | #include <scsi/scsi.h> |
33 | #include <scsi/scsi_device.h> | 34 | #include <scsi/scsi_device.h> |
@@ -7098,6 +7099,7 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev) | |||
7098 | /* Restore device state from PCI config space */ | 7099 | /* Restore device state from PCI config space */ |
7099 | pci_set_power_state(pdev, PCI_D0); | 7100 | pci_set_power_state(pdev, PCI_D0); |
7100 | pci_restore_state(pdev); | 7101 | pci_restore_state(pdev); |
7102 | |||
7101 | if (pdev->is_busmaster) | 7103 | if (pdev->is_busmaster) |
7102 | pci_set_master(pdev); | 7104 | pci_set_master(pdev); |
7103 | 7105 | ||
@@ -7132,6 +7134,53 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev) | |||
7132 | } | 7134 | } |
7133 | 7135 | ||
7134 | /** | 7136 | /** |
7137 | * lpfc_sli_prep_dev_for_reset - Prepare SLI3 device for pci slot reset | ||
7138 | * @phba: pointer to lpfc hba data structure. | ||
7139 | * | ||
7140 | * This routine is called to prepare the SLI3 device for PCI slot reset. It | ||
7141 | * disables the device interrupt and pci device, and aborts the internal FCP | ||
7142 | * pending I/Os. | ||
7143 | **/ | ||
7144 | static void | ||
7145 | lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) | ||
7146 | { | ||
7147 | struct lpfc_sli *psli = &phba->sli; | ||
7148 | struct lpfc_sli_ring *pring; | ||
7149 | |||
7150 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
7151 | "2710 PCI channel I/O frozen\n"); | ||
7152 | /* Disable interrupt and pci device */ | ||
7153 | lpfc_sli_disable_intr(phba); | ||
7154 | pci_disable_device(phba->pcidev); | ||
7155 | /* | ||
7156 | * There may be I/Os dropped by the firmware. | ||
7157 | * Error iocb (I/O) on txcmplq and let the SCSI layer | ||
7158 | * retry it after re-establishing link. | ||
7159 | */ | ||
7160 | pring = &psli->ring[psli->fcp_ring]; | ||
7161 | lpfc_sli_abort_iocb_ring(phba, pring); | ||
7162 | } | ||
7163 | |||
7164 | /** | ||
7165 | * lpfc_sli_prep_dev_for_perm_failure - Prepare SLI3 dev for pci slot disable | ||
7166 | * @phba: pointer to lpfc hba data structure. | ||
7167 | * | ||
7168 | * This routine is called to prepare the SLI3 device for PCI slot permanently | ||
7169 | * disabling. It blocks the SCSI transport layer traffic and flushes the FCP | ||
7170 | * pending I/Os. | ||
7171 | **/ | ||
7172 | static void | ||
7173 | lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba) | ||
7174 | { | ||
7175 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
7176 | "2711 PCI channel I/O permanent failure\n"); | ||
7177 | /* Block all SCSI devices' I/Os on the host */ | ||
7178 | lpfc_scsi_dev_block(phba); | ||
7179 | /* Clean up all driver's outstanding SCSI I/Os */ | ||
7180 | lpfc_sli_flush_fcp_rings(phba); | ||
7181 | } | ||
7182 | |||
7183 | /** | ||
7135 | * lpfc_io_error_detected_s3 - Method for handling SLI-3 device PCI I/O error | 7184 | * lpfc_io_error_detected_s3 - Method for handling SLI-3 device PCI I/O error |
7136 | * @pdev: pointer to PCI device. | 7185 | * @pdev: pointer to PCI device. |
7137 | * @state: the current PCI connection state. | 7186 | * @state: the current PCI connection state. |
@@ -7145,6 +7194,7 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev) | |||
7145 | * as desired. | 7194 | * as desired. |
7146 | * | 7195 | * |
7147 | * Return codes | 7196 | * Return codes |
7197 | * PCI_ERS_RESULT_CAN_RECOVER - can be recovered with reset_link | ||
7148 | * PCI_ERS_RESULT_NEED_RESET - need to reset before recovery | 7198 | * PCI_ERS_RESULT_NEED_RESET - need to reset before recovery |
7149 | * PCI_ERS_RESULT_DISCONNECT - device could not be recovered | 7199 | * PCI_ERS_RESULT_DISCONNECT - device could not be recovered |
7150 | **/ | 7200 | **/ |
@@ -7153,33 +7203,26 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state) | |||
7153 | { | 7203 | { |
7154 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 7204 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
7155 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; | 7205 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
7156 | struct lpfc_sli *psli = &phba->sli; | ||
7157 | struct lpfc_sli_ring *pring; | ||
7158 | 7206 | ||
7159 | if (state == pci_channel_io_perm_failure) { | 7207 | switch (state) { |
7160 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 7208 | case pci_channel_io_normal: |
7161 | "0472 PCI channel I/O permanent failure\n"); | 7209 | /* Non-fatal error, do nothing */ |
7162 | /* Block all SCSI devices' I/Os on the host */ | 7210 | return PCI_ERS_RESULT_CAN_RECOVER; |
7163 | lpfc_scsi_dev_block(phba); | 7211 | case pci_channel_io_frozen: |
7164 | /* Clean up all driver's outstanding SCSI I/Os */ | 7212 | /* Fatal error, prepare for slot reset */ |
7165 | lpfc_sli_flush_fcp_rings(phba); | 7213 | lpfc_sli_prep_dev_for_reset(phba); |
7214 | return PCI_ERS_RESULT_NEED_RESET; | ||
7215 | case pci_channel_io_perm_failure: | ||
7216 | /* Permanent failure, prepare for device down */ | ||
7217 | lpfc_prep_dev_for_perm_failure(phba); | ||
7166 | return PCI_ERS_RESULT_DISCONNECT; | 7218 | return PCI_ERS_RESULT_DISCONNECT; |
7219 | default: | ||
7220 | /* Unknown state, prepare and request slot reset */ | ||
7221 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
7222 | "0472 Unknown PCI error state: x%x\n", state); | ||
7223 | lpfc_sli_prep_dev_for_reset(phba); | ||
7224 | return PCI_ERS_RESULT_NEED_RESET; | ||
7167 | } | 7225 | } |
7168 | |||
7169 | pci_disable_device(pdev); | ||
7170 | /* | ||
7171 | * There may be I/Os dropped by the firmware. | ||
7172 | * Error iocb (I/O) on txcmplq and let the SCSI layer | ||
7173 | * retry it after re-establishing link. | ||
7174 | */ | ||
7175 | pring = &psli->ring[psli->fcp_ring]; | ||
7176 | lpfc_sli_abort_iocb_ring(phba, pring); | ||
7177 | |||
7178 | /* Disable interrupt */ | ||
7179 | lpfc_sli_disable_intr(phba); | ||
7180 | |||
7181 | /* Request a slot reset. */ | ||
7182 | return PCI_ERS_RESULT_NEED_RESET; | ||
7183 | } | 7226 | } |
7184 | 7227 | ||
7185 | /** | 7228 | /** |
@@ -7259,7 +7302,12 @@ lpfc_io_resume_s3(struct pci_dev *pdev) | |||
7259 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 7302 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
7260 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; | 7303 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
7261 | 7304 | ||
7305 | /* Bring the device online */ | ||
7262 | lpfc_online(phba); | 7306 | lpfc_online(phba); |
7307 | |||
7308 | /* Clean up Advanced Error Reporting (AER) if needed */ | ||
7309 | if (phba->hba_flag & HBA_AER_ENABLED) | ||
7310 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
7263 | } | 7311 | } |
7264 | 7312 | ||
7265 | /** | 7313 | /** |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 9693c777425a..42d0f1948a7a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
31 | #include <scsi/scsi_transport_fc.h> | 31 | #include <scsi/scsi_transport_fc.h> |
32 | #include <scsi/fc/fc_fs.h> | 32 | #include <scsi/fc/fc_fs.h> |
33 | #include <linux/aer.h> | ||
33 | 34 | ||
34 | #include "lpfc_hw4.h" | 35 | #include "lpfc_hw4.h" |
35 | #include "lpfc_hw.h" | 36 | #include "lpfc_hw.h" |
@@ -3551,9 +3552,13 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba) | |||
3551 | struct lpfc_sli *psli; | 3552 | struct lpfc_sli *psli; |
3552 | volatile uint32_t word0; | 3553 | volatile uint32_t word0; |
3553 | void __iomem *to_slim; | 3554 | void __iomem *to_slim; |
3555 | uint32_t hba_aer_enabled; | ||
3554 | 3556 | ||
3555 | spin_lock_irq(&phba->hbalock); | 3557 | spin_lock_irq(&phba->hbalock); |
3556 | 3558 | ||
3559 | /* Take PCIe device Advanced Error Reporting (AER) state */ | ||
3560 | hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED; | ||
3561 | |||
3557 | psli = &phba->sli; | 3562 | psli = &phba->sli; |
3558 | 3563 | ||
3559 | /* Restart HBA */ | 3564 | /* Restart HBA */ |
@@ -3593,6 +3598,10 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba) | |||
3593 | /* Give the INITFF and Post time to settle. */ | 3598 | /* Give the INITFF and Post time to settle. */ |
3594 | mdelay(100); | 3599 | mdelay(100); |
3595 | 3600 | ||
3601 | /* Reset HBA AER if it was enabled, note hba_flag was reset above */ | ||
3602 | if (hba_aer_enabled) | ||
3603 | pci_disable_pcie_error_reporting(phba->pcidev); | ||
3604 | |||
3596 | lpfc_hba_down_post(phba); | 3605 | lpfc_hba_down_post(phba); |
3597 | 3606 | ||
3598 | return 0; | 3607 | return 0; |
@@ -4062,6 +4071,24 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) | |||
4062 | if (rc) | 4071 | if (rc) |
4063 | goto lpfc_sli_hba_setup_error; | 4072 | goto lpfc_sli_hba_setup_error; |
4064 | 4073 | ||
4074 | /* Enable PCIe device Advanced Error Reporting (AER) if configured */ | ||
4075 | if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) { | ||
4076 | rc = pci_enable_pcie_error_reporting(phba->pcidev); | ||
4077 | if (!rc) { | ||
4078 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
4079 | "2709 This device supports " | ||
4080 | "Advanced Error Reporting (AER)\n"); | ||
4081 | spin_lock_irq(&phba->hbalock); | ||
4082 | phba->hba_flag |= HBA_AER_ENABLED; | ||
4083 | spin_unlock_irq(&phba->hbalock); | ||
4084 | } else { | ||
4085 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
4086 | "2708 This device does not support " | ||
4087 | "Advanced Error Reporting (AER)\n"); | ||
4088 | phba->cfg_aer_support = 0; | ||
4089 | } | ||
4090 | } | ||
4091 | |||
4065 | if (phba->sli_rev == 3) { | 4092 | if (phba->sli_rev == 3) { |
4066 | phba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE; | 4093 | phba->iocb_cmd_size = SLI3_IOCB_CMD_SIZE; |
4067 | phba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE; | 4094 | phba->iocb_rsp_size = SLI3_IOCB_RSP_SIZE; |