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 12:01:51 -0600 |
commit | 891478a2442d8d0077651bc8316afaec8d85dd4d (patch) | |
tree | 9758bf87edbf4446ceb2fcce20fcebb1ae31fbfb | |
parent | 5ffc266ee7a62741ebee89ede15049ec0f02fa75 (diff) | |
download | linux-stable-891478a2442d8d0077651bc8316afaec8d85dd4d.tar.gz linux-stable-891478a2442d8d0077651bc8316afaec8d85dd4d.tar.bz2 linux-stable-891478a2442d8d0077651bc8316afaec8d85dd4d.zip |
[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>
-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, struct lpfc_hba *phba = vport->phba; int val = 0, rc = -EINVAL; + /* AER not supported on OC devices yet */ + if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) + return -EPERM; if (!isdigit(buf[0])) return -EINVAL; if (sscanf(buf, "%i", &val) != 1) @@ -2851,10 +2854,11 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, phba->cfg_aer_support = 0; rc = strlen(buf); } else - rc = -EINVAL; - } else + rc = -EPERM; + } else { phba->cfg_aer_support = 0; - rc = strlen(buf); + rc = strlen(buf); + } break; case 1: if (!(phba->hba_flag & HBA_AER_ENABLED)) { @@ -2866,10 +2870,11 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr, phba->cfg_aer_support = 1; rc = strlen(buf); } else - rc = -EINVAL; - } else + rc = -EPERM; + } else { phba->cfg_aer_support = 1; - rc = strlen(buf); + rc = strlen(buf); + } break; default: rc = -EINVAL; @@ -2905,6 +2910,12 @@ lpfc_param_show(aer_support) static int lpfc_aer_support_init(struct lpfc_hba *phba, int val) { + /* AER not supported on OC devices yet */ + if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) { + phba->cfg_aer_support = 0; + return -EPERM; + } + if (val == 0 || val == 1) { phba->cfg_aer_support = val; return 0; @@ -2913,6 +2924,7 @@ lpfc_aer_support_init(struct lpfc_hba *phba, int val) "2712 lpfc_aer_support attribute value %d out " "of range, allowed values are 0|1, setting it " "to default value of 1\n", val); + /* By default, try to enable AER on a device */ phba->cfg_aer_support = 1; return -EINVAL; } @@ -2948,18 +2960,23 @@ lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr, struct lpfc_hba *phba = vport->phba; int val, rc = -1; + /* AER not supported on OC devices yet */ + if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) + return -EPERM; if (!isdigit(buf[0])) return -EINVAL; if (sscanf(buf, "%i", &val) != 1) return -EINVAL; + if (val != 1) + return -EINVAL; - if (val == 1 && phba->hba_flag & HBA_AER_ENABLED) + if (phba->hba_flag & HBA_AER_ENABLED) rc = pci_cleanup_aer_uncorrect_error_status(phba->pcidev); if (rc == 0) return strlen(buf); else - return -EINVAL; + return -EPERM; } 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) ret = 1; spin_unlock_irq(shost->host_lock); goto out; + } else { + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, + "2624 RPI %x DID %x flg %x still " + "logged in\n", + ndlp->nlp_rpi, ndlp->nlp_DID, + ndlp->nlp_flag); + if (ndlp->nlp_flag & NLP_RPI_VALID) + ret = 1; } } spin_unlock_irq(shost->host_lock); @@ -4465,7 +4473,7 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { lpfc_mbx_unreg_vpi(vports[i]); - vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; + vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; } 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) } /** + * lpfc_sli_prep_dev_for_recover - Prepare SLI3 device for pci slot recover + * @phba: pointer to lpfc hba data structure. + * + * This routine is called to prepare the SLI3 device for PCI slot recover. It + * aborts and stops all the on-going I/Os on the pci device. + **/ +static void +lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba) +{ + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2723 PCI channel I/O abort preparing for recovery\n"); + /* Prepare for bringing HBA offline */ + lpfc_offline_prep(phba); + /* Clear sli active flag to prevent sysfs access to HBA */ + spin_lock_irq(&phba->hbalock); + phba->sli.sli_flag &= ~LPFC_SLI_ACTIVE; + spin_unlock_irq(&phba->hbalock); + /* Stop and flush all I/Os and bring HBA offline */ + lpfc_offline(phba); +} + +/** * lpfc_sli_prep_dev_for_reset - Prepare SLI3 device for pci slot reset * @phba: pointer to lpfc hba data structure. * @@ -7156,7 +7178,7 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) struct lpfc_sli_ring *pring; lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2710 PCI channel I/O frozen\n"); + "2710 PCI channel disable preparing for reset\n"); /* Disable interrupt and pci device */ lpfc_sli_disable_intr(phba); pci_disable_device(phba->pcidev); @@ -7181,7 +7203,7 @@ static void lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2711 PCI channel I/O permanent failure\n"); + "2711 PCI channel permanent disable for failure\n"); /* Block all SCSI devices' I/Os on the host */ lpfc_scsi_dev_block(phba); /* 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) switch (state) { case pci_channel_io_normal: - /* Non-fatal error, do nothing */ + /* Non-fatal error, prepare for recovery */ + lpfc_sli_prep_dev_for_recover(phba); return PCI_ERS_RESULT_CAN_RECOVER; case pci_channel_io_frozen: /* Fatal error, prepare for slot reset */ |