diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-11-18 15:40:23 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:01:51 -0500 |
commit | 891478a2442d8d0077651bc8316afaec8d85dd4d (patch) | |
tree | 9758bf87edbf4446ceb2fcce20fcebb1ae31fbfb /drivers/scsi/lpfc | |
parent | 5ffc266ee7a62741ebee89ede15049ec0f02fa75 (diff) |
[SCSI] lpfc 8.3.6 : Fix AER issues
Fix AER issues.
- Made AER sysfs entry point return "Operation not permitted" to
OneConnect HBAs
- Stop and abort all I/Os on HBA for AER uncorrectable non-fatal error
handling
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 33 | ||||
-rwxr-xr-x[-rw-r--r--] | drivers/scsi/lpfc/lpfc_hbadisc.c | 10 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 29 |
3 files changed, 60 insertions, 12 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index d55befb7cf4c..75523603b91c 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -2835,6 +2835,9 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, | |||
2835 | struct lpfc_hba *phba = vport->phba; | 2835 | struct lpfc_hba *phba = vport->phba; |
2836 | int val = 0, rc = -EINVAL; | 2836 | int val = 0, rc = -EINVAL; |
2837 | 2837 | ||
2838 | /* AER not supported on OC devices yet */ | ||
2839 | if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) | ||
2840 | return -EPERM; | ||
2838 | if (!isdigit(buf[0])) | 2841 | if (!isdigit(buf[0])) |
2839 | return -EINVAL; | 2842 | return -EINVAL; |
2840 | if (sscanf(buf, "%i", &val) != 1) | 2843 | if (sscanf(buf, "%i", &val) != 1) |
@@ -2851,10 +2854,11 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, | |||
2851 | phba->cfg_aer_support = 0; | 2854 | phba->cfg_aer_support = 0; |
2852 | rc = strlen(buf); | 2855 | rc = strlen(buf); |
2853 | } else | 2856 | } else |
2854 | rc = -EINVAL; | 2857 | rc = -EPERM; |
2855 | } else | 2858 | } else { |
2856 | phba->cfg_aer_support = 0; | 2859 | phba->cfg_aer_support = 0; |
2857 | rc = strlen(buf); | 2860 | rc = strlen(buf); |
2861 | } | ||
2858 | break; | 2862 | break; |
2859 | case 1: | 2863 | case 1: |
2860 | if (!(phba->hba_flag & HBA_AER_ENABLED)) { | 2864 | if (!(phba->hba_flag & HBA_AER_ENABLED)) { |
@@ -2866,10 +2870,11 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, | |||
2866 | phba->cfg_aer_support = 1; | 2870 | phba->cfg_aer_support = 1; |
2867 | rc = strlen(buf); | 2871 | rc = strlen(buf); |
2868 | } else | 2872 | } else |
2869 | rc = -EINVAL; | 2873 | rc = -EPERM; |
2870 | } else | 2874 | } else { |
2871 | phba->cfg_aer_support = 1; | 2875 | phba->cfg_aer_support = 1; |
2872 | rc = strlen(buf); | 2876 | rc = strlen(buf); |
2877 | } | ||
2873 | break; | 2878 | break; |
2874 | default: | 2879 | default: |
2875 | rc = -EINVAL; | 2880 | rc = -EINVAL; |
@@ -2905,6 +2910,12 @@ lpfc_param_show(aer_support) | |||
2905 | static int | 2910 | static int |
2906 | lpfc_aer_support_init(struct lpfc_hba *phba, int val) | 2911 | lpfc_aer_support_init(struct lpfc_hba *phba, int val) |
2907 | { | 2912 | { |
2913 | /* AER not supported on OC devices yet */ | ||
2914 | if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { | ||
2915 | phba->cfg_aer_support = 0; | ||
2916 | return -EPERM; | ||
2917 | } | ||
2918 | |||
2908 | if (val == 0 || val == 1) { | 2919 | if (val == 0 || val == 1) { |
2909 | phba->cfg_aer_support = val; | 2920 | phba->cfg_aer_support = val; |
2910 | return 0; | 2921 | return 0; |
@@ -2913,6 +2924,7 @@ lpfc_aer_support_init(struct lpfc_hba *phba, int val) | |||
2913 | "2712 lpfc_aer_support attribute value %d out " | 2924 | "2712 lpfc_aer_support attribute value %d out " |
2914 | "of range, allowed values are 0|1, setting it " | 2925 | "of range, allowed values are 0|1, setting it " |
2915 | "to default value of 1\n", val); | 2926 | "to default value of 1\n", val); |
2927 | /* By default, try to enable AER on a device */ | ||
2916 | phba->cfg_aer_support = 1; | 2928 | phba->cfg_aer_support = 1; |
2917 | return -EINVAL; | 2929 | return -EINVAL; |
2918 | } | 2930 | } |
@@ -2948,18 +2960,23 @@ lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr, | |||
2948 | struct lpfc_hba *phba = vport->phba; | 2960 | struct lpfc_hba *phba = vport->phba; |
2949 | int val, rc = -1; | 2961 | int val, rc = -1; |
2950 | 2962 | ||
2963 | /* AER not supported on OC devices yet */ | ||
2964 | if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) | ||
2965 | return -EPERM; | ||
2951 | if (!isdigit(buf[0])) | 2966 | if (!isdigit(buf[0])) |
2952 | return -EINVAL; | 2967 | return -EINVAL; |
2953 | if (sscanf(buf, "%i", &val) != 1) | 2968 | if (sscanf(buf, "%i", &val) != 1) |
2954 | return -EINVAL; | 2969 | return -EINVAL; |
2970 | if (val != 1) | ||
2971 | return -EINVAL; | ||
2955 | 2972 | ||
2956 | if (val == 1 && phba->hba_flag & HBA_AER_ENABLED) | 2973 | if (phba->hba_flag & HBA_AER_ENABLED) |
2957 | rc = pci_cleanup_aer_uncorrect_error_status(phba->pcidev); | 2974 | rc = pci_cleanup_aer_uncorrect_error_status(phba->pcidev); |
2958 | 2975 | ||
2959 | if (rc == 0) | 2976 | if (rc == 0) |
2960 | return strlen(buf); | 2977 | return strlen(buf); |
2961 | else | 2978 | else |
2962 | return -EINVAL; | 2979 | return -EPERM; |
2963 | } | 2980 | } |
2964 | 2981 | ||
2965 | static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL, | 2982 | static DEVICE_ATTR(lpfc_aer_state_cleanup, S_IWUSR, NULL, |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 3c06aa54a3e5..4d7d8846b4da 100644..100755 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -4369,6 +4369,14 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) | |||
4369 | ret = 1; | 4369 | ret = 1; |
4370 | spin_unlock_irq(shost->host_lock); | 4370 | spin_unlock_irq(shost->host_lock); |
4371 | goto out; | 4371 | goto out; |
4372 | } else { | ||
4373 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | ||
4374 | "2624 RPI %x DID %x flg %x still " | ||
4375 | "logged in\n", | ||
4376 | ndlp->nlp_rpi, ndlp->nlp_DID, | ||
4377 | ndlp->nlp_flag); | ||
4378 | if (ndlp->nlp_flag & NLP_RPI_VALID) | ||
4379 | ret = 1; | ||
4372 | } | 4380 | } |
4373 | } | 4381 | } |
4374 | spin_unlock_irq(shost->host_lock); | 4382 | spin_unlock_irq(shost->host_lock); |
@@ -4465,7 +4473,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) | |||
4465 | (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) | 4473 | (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) |
4466 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { | 4474 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
4467 | lpfc_mbx_unreg_vpi(vports[i]); | 4475 | lpfc_mbx_unreg_vpi(vports[i]); |
4468 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 4476 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; |
4469 | vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; | 4477 | vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; |
4470 | } | 4478 | } |
4471 | lpfc_destroy_vport_work_array(phba, vports); | 4479 | lpfc_destroy_vport_work_array(phba, vports); |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6932657d74ad..93679f30a5af 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -7142,6 +7142,28 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev) | |||
7142 | } | 7142 | } |
7143 | 7143 | ||
7144 | /** | 7144 | /** |
7145 | * lpfc_sli_prep_dev_for_recover - Prepare SLI3 device for pci slot recover | ||
7146 | * @phba: pointer to lpfc hba data structure. | ||
7147 | * | ||
7148 | * This routine is called to prepare the SLI3 device for PCI slot recover. It | ||
7149 | * aborts and stops all the on-going I/Os on the pci device. | ||
7150 | **/ | ||
7151 | static void | ||
7152 | lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba) | ||
7153 | { | ||
7154 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
7155 | "2723 PCI channel I/O abort preparing for recovery\n"); | ||
7156 | /* Prepare for bringing HBA offline */ | ||
7157 | lpfc_offline_prep(phba); | ||
7158 | /* Clear sli active flag to prevent sysfs access to HBA */ | ||
7159 | spin_lock_irq(&phba->hbalock); | ||
7160 | phba->sli.sli_flag &= ~LPFC_SLI_ACTIVE; | ||
7161 | spin_unlock_irq(&phba->hbalock); | ||
7162 | /* Stop and flush all I/Os and bring HBA offline */ | ||
7163 | lpfc_offline(phba); | ||
7164 | } | ||
7165 | |||
7166 | /** | ||
7145 | * lpfc_sli_prep_dev_for_reset - Prepare SLI3 device for pci slot reset | 7167 | * lpfc_sli_prep_dev_for_reset - Prepare SLI3 device for pci slot reset |
7146 | * @phba: pointer to lpfc hba data structure. | 7168 | * @phba: pointer to lpfc hba data structure. |
7147 | * | 7169 | * |
@@ -7156,7 +7178,7 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) | |||
7156 | struct lpfc_sli_ring *pring; | 7178 | struct lpfc_sli_ring *pring; |
7157 | 7179 | ||
7158 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 7180 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
7159 | "2710 PCI channel I/O frozen\n"); | 7181 | "2710 PCI channel disable preparing for reset\n"); |
7160 | /* Disable interrupt and pci device */ | 7182 | /* Disable interrupt and pci device */ |
7161 | lpfc_sli_disable_intr(phba); | 7183 | lpfc_sli_disable_intr(phba); |
7162 | pci_disable_device(phba->pcidev); | 7184 | pci_disable_device(phba->pcidev); |
@@ -7181,7 +7203,7 @@ static void | |||
7181 | lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba) | 7203 | lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba) |
7182 | { | 7204 | { |
7183 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 7205 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
7184 | "2711 PCI channel I/O permanent failure\n"); | 7206 | "2711 PCI channel permanent disable for failure\n"); |
7185 | /* Block all SCSI devices' I/Os on the host */ | 7207 | /* Block all SCSI devices' I/Os on the host */ |
7186 | lpfc_scsi_dev_block(phba); | 7208 | lpfc_scsi_dev_block(phba); |
7187 | /* Clean up all driver's outstanding SCSI I/Os */ | 7209 | /* Clean up all driver's outstanding SCSI I/Os */ |
@@ -7214,7 +7236,8 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state) | |||
7214 | 7236 | ||
7215 | switch (state) { | 7237 | switch (state) { |
7216 | case pci_channel_io_normal: | 7238 | case pci_channel_io_normal: |
7217 | /* Non-fatal error, do nothing */ | 7239 | /* Non-fatal error, prepare for recovery */ |
7240 | lpfc_sli_prep_dev_for_recover(phba); | ||
7218 | return PCI_ERS_RESULT_CAN_RECOVER; | 7241 | return PCI_ERS_RESULT_CAN_RECOVER; |
7219 | case pci_channel_io_frozen: | 7242 | case pci_channel_io_frozen: |
7220 | /* Fatal error, prepare for slot reset */ | 7243 | /* Fatal error, prepare for slot reset */ |