aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2010-06-08 18:31:21 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-27 13:01:35 -0400
commit75baf69657ea2107f2c202cd29dada206ae4b7c4 (patch)
tree76f48393730c19e0a0286ceaa5132d8e500f127f /drivers/scsi/lpfc
parentc20c426732a5a5d21e99b36286f79c2024115341 (diff)
[SCSI] lpfc 8.3.14: PCI fixes and enhancements
- Allow enabling MSI-X intterupts with fewer vectors than requested by looking at the return value from pci_enable_msix. - Implemented driver PCI AER error handling routines for supporting AER error recovering on SLI4 devices. - Remove redundant SLI_ACTIVE checks Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> 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.c22
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c195
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c41
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h1
5 files changed, 228 insertions, 41 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 39b0760c438d..a7c6b7390554 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -864,7 +864,6 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
864 uint32_t *mrpi, uint32_t *arpi, 864 uint32_t *mrpi, uint32_t *arpi,
865 uint32_t *mvpi, uint32_t *avpi) 865 uint32_t *mvpi, uint32_t *avpi)
866{ 866{
867 struct lpfc_sli *psli = &phba->sli;
868 struct lpfc_mbx_read_config *rd_config; 867 struct lpfc_mbx_read_config *rd_config;
869 LPFC_MBOXQ_t *pmboxq; 868 LPFC_MBOXQ_t *pmboxq;
870 MAILBOX_t *pmb; 869 MAILBOX_t *pmb;
@@ -893,8 +892,7 @@ lpfc_get_hba_info(struct lpfc_hba *phba,
893 pmb->mbxOwner = OWN_HOST; 892 pmb->mbxOwner = OWN_HOST;
894 pmboxq->context1 = NULL; 893 pmboxq->context1 = NULL;
895 894
896 if ((phba->pport->fc_flag & FC_OFFLINE_MODE) || 895 if (phba->pport->fc_flag & FC_OFFLINE_MODE)
897 (!(psli->sli_flag & LPFC_SLI_ACTIVE)))
898 rc = MBX_NOT_FINISHED; 896 rc = MBX_NOT_FINISHED;
899 else 897 else
900 rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); 898 rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
@@ -2943,9 +2941,6 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr,
2943 struct lpfc_hba *phba = vport->phba; 2941 struct lpfc_hba *phba = vport->phba;
2944 int val = 0, rc = -EINVAL; 2942 int val = 0, rc = -EINVAL;
2945 2943
2946 /* AER not supported on OC devices yet */
2947 if (phba->pci_dev_grp == LPFC_PCI_DEV_OC)
2948 return -EPERM;
2949 if (!isdigit(buf[0])) 2944 if (!isdigit(buf[0]))
2950 return -EINVAL; 2945 return -EINVAL;
2951 if (sscanf(buf, "%i", &val) != 1) 2946 if (sscanf(buf, "%i", &val) != 1)
@@ -3018,12 +3013,6 @@ lpfc_param_show(aer_support)
3018static int 3013static int
3019lpfc_aer_support_init(struct lpfc_hba *phba, int val) 3014lpfc_aer_support_init(struct lpfc_hba *phba, int val)
3020{ 3015{
3021 /* AER not supported on OC devices yet */
3022 if (phba->pci_dev_grp == LPFC_PCI_DEV_OC) {
3023 phba->cfg_aer_support = 0;
3024 return -EPERM;
3025 }
3026
3027 if (val == 0 || val == 1) { 3016 if (val == 0 || val == 1) {
3028 phba->cfg_aer_support = val; 3017 phba->cfg_aer_support = val;
3029 return 0; 3018 return 0;
@@ -3068,9 +3057,6 @@ lpfc_aer_cleanup_state(struct device *dev, struct device_attribute *attr,
3068 struct lpfc_hba *phba = vport->phba; 3057 struct lpfc_hba *phba = vport->phba;
3069 int val, rc = -1; 3058 int val, rc = -1;
3070 3059
3071 /* AER not supported on OC devices yet */
3072 if (phba->pci_dev_grp == LPFC_PCI_DEV_OC)
3073 return -EPERM;
3074 if (!isdigit(buf[0])) 3060 if (!isdigit(buf[0]))
3075 return -EINVAL; 3061 return -EINVAL;
3076 if (sscanf(buf, "%i", &val) != 1) 3062 if (sscanf(buf, "%i", &val) != 1)
@@ -4099,8 +4085,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
4099 pmboxq->context1 = NULL; 4085 pmboxq->context1 = NULL;
4100 pmboxq->vport = vport; 4086 pmboxq->vport = vport;
4101 4087
4102 if ((vport->fc_flag & FC_OFFLINE_MODE) || 4088 if (vport->fc_flag & FC_OFFLINE_MODE)
4103 (!(psli->sli_flag & LPFC_SLI_ACTIVE)))
4104 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); 4089 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
4105 else 4090 else
4106 rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); 4091 rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
@@ -4124,8 +4109,7 @@ lpfc_get_stats(struct Scsi_Host *shost)
4124 pmboxq->context1 = NULL; 4109 pmboxq->context1 = NULL;
4125 pmboxq->vport = vport; 4110 pmboxq->vport = vport;
4126 4111
4127 if ((vport->fc_flag & FC_OFFLINE_MODE) || 4112 if (vport->fc_flag & FC_OFFLINE_MODE)
4128 (!(psli->sli_flag & LPFC_SLI_ACTIVE)))
4129 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); 4113 rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
4130 else 4114 else
4131 rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); 4115 rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 184e45f286d2..08db674ec580 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -7030,22 +7030,28 @@ lpfc_sli_disable_intr(struct lpfc_hba *phba)
7030static int 7030static int
7031lpfc_sli4_enable_msix(struct lpfc_hba *phba) 7031lpfc_sli4_enable_msix(struct lpfc_hba *phba)
7032{ 7032{
7033 int rc, index; 7033 int vectors, rc, index;
7034 7034
7035 /* Set up MSI-X multi-message vectors */ 7035 /* Set up MSI-X multi-message vectors */
7036 for (index = 0; index < phba->sli4_hba.cfg_eqn; index++) 7036 for (index = 0; index < phba->sli4_hba.cfg_eqn; index++)
7037 phba->sli4_hba.msix_entries[index].entry = index; 7037 phba->sli4_hba.msix_entries[index].entry = index;
7038 7038
7039 /* Configure MSI-X capability structure */ 7039 /* Configure MSI-X capability structure */
7040 vectors = phba->sli4_hba.cfg_eqn;
7041enable_msix_vectors:
7040 rc = pci_enable_msix(phba->pcidev, phba->sli4_hba.msix_entries, 7042 rc = pci_enable_msix(phba->pcidev, phba->sli4_hba.msix_entries,
7041 phba->sli4_hba.cfg_eqn); 7043 vectors);
7042 if (rc) { 7044 if (rc > 1) {
7045 vectors = rc;
7046 goto enable_msix_vectors;
7047 } else if (rc) {
7043 lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 7048 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
7044 "0484 PCI enable MSI-X failed (%d)\n", rc); 7049 "0484 PCI enable MSI-X failed (%d)\n", rc);
7045 goto msi_fail_out; 7050 goto msi_fail_out;
7046 } 7051 }
7052
7047 /* Log MSI-X vector assignment */ 7053 /* Log MSI-X vector assignment */
7048 for (index = 0; index < phba->sli4_hba.cfg_eqn; index++) 7054 for (index = 0; index < vectors; index++)
7049 lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 7055 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
7050 "0489 MSI-X entry[%d]: vector=x%x " 7056 "0489 MSI-X entry[%d]: vector=x%x "
7051 "message=%d\n", index, 7057 "message=%d\n", index,
@@ -7067,7 +7073,7 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
7067 } 7073 }
7068 7074
7069 /* The rest of the vector(s) are associated to fast-path handler(s) */ 7075 /* The rest of the vector(s) are associated to fast-path handler(s) */
7070 for (index = 1; index < phba->sli4_hba.cfg_eqn; index++) { 7076 for (index = 1; index < vectors; index++) {
7071 phba->sli4_hba.fcp_eq_hdl[index - 1].idx = index - 1; 7077 phba->sli4_hba.fcp_eq_hdl[index - 1].idx = index - 1;
7072 phba->sli4_hba.fcp_eq_hdl[index - 1].phba = phba; 7078 phba->sli4_hba.fcp_eq_hdl[index - 1].phba = phba;
7073 rc = request_irq(phba->sli4_hba.msix_entries[index].vector, 7079 rc = request_irq(phba->sli4_hba.msix_entries[index].vector,
@@ -7081,6 +7087,7 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
7081 goto cfg_fail_out; 7087 goto cfg_fail_out;
7082 } 7088 }
7083 } 7089 }
7090 phba->sli4_hba.msix_vec_nr = vectors;
7084 7091
7085 return rc; 7092 return rc;
7086 7093
@@ -7114,9 +7121,10 @@ lpfc_sli4_disable_msix(struct lpfc_hba *phba)
7114 /* Free up MSI-X multi-message vectors */ 7121 /* Free up MSI-X multi-message vectors */
7115 free_irq(phba->sli4_hba.msix_entries[0].vector, phba); 7122 free_irq(phba->sli4_hba.msix_entries[0].vector, phba);
7116 7123
7117 for (index = 1; index < phba->sli4_hba.cfg_eqn; index++) 7124 for (index = 1; index < phba->sli4_hba.msix_vec_nr; index++)
7118 free_irq(phba->sli4_hba.msix_entries[index].vector, 7125 free_irq(phba->sli4_hba.msix_entries[index].vector,
7119 &phba->sli4_hba.fcp_eq_hdl[index - 1]); 7126 &phba->sli4_hba.fcp_eq_hdl[index - 1]);
7127
7120 /* Disable MSI-X */ 7128 /* Disable MSI-X */
7121 pci_disable_msix(phba->pcidev); 7129 pci_disable_msix(phba->pcidev);
7122 7130
@@ -7158,6 +7166,7 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba)
7158 pci_disable_msi(phba->pcidev); 7166 pci_disable_msi(phba->pcidev);
7159 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, 7167 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
7160 "0490 MSI request_irq failed (%d)\n", rc); 7168 "0490 MSI request_irq failed (%d)\n", rc);
7169 return rc;
7161 } 7170 }
7162 7171
7163 for (index = 0; index < phba->cfg_fcp_eq_count; index++) { 7172 for (index = 0; index < phba->cfg_fcp_eq_count; index++) {
@@ -7165,7 +7174,7 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba)
7165 phba->sli4_hba.fcp_eq_hdl[index].phba = phba; 7174 phba->sli4_hba.fcp_eq_hdl[index].phba = phba;
7166 } 7175 }
7167 7176
7168 return rc; 7177 return 0;
7169} 7178}
7170 7179
7171/** 7180/**
@@ -7876,6 +7885,9 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba)
7876 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 7885 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
7877 "2710 PCI channel disable preparing for reset\n"); 7886 "2710 PCI channel disable preparing for reset\n");
7878 7887
7888 /* Block any management I/Os to the device */
7889 lpfc_block_mgmt_io(phba);
7890
7879 /* Block all SCSI devices' I/Os on the host */ 7891 /* Block all SCSI devices' I/Os on the host */
7880 lpfc_scsi_dev_block(phba); 7892 lpfc_scsi_dev_block(phba);
7881 7893
@@ -7885,6 +7897,7 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba)
7885 /* Disable interrupt and pci device */ 7897 /* Disable interrupt and pci device */
7886 lpfc_sli_disable_intr(phba); 7898 lpfc_sli_disable_intr(phba);
7887 pci_disable_device(phba->pcidev); 7899 pci_disable_device(phba->pcidev);
7900
7888 /* Flush all driver's outstanding SCSI I/Os as we are to reset */ 7901 /* Flush all driver's outstanding SCSI I/Os as we are to reset */
7889 lpfc_sli_flush_fcp_rings(phba); 7902 lpfc_sli_flush_fcp_rings(phba);
7890} 7903}
@@ -7898,7 +7911,7 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba)
7898 * pending I/Os. 7911 * pending I/Os.
7899 **/ 7912 **/
7900static void 7913static void
7901lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba) 7914lpfc_sli_prep_dev_for_perm_failure(struct lpfc_hba *phba)
7902{ 7915{
7903 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 7916 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
7904 "2711 PCI channel permanent disable for failure\n"); 7917 "2711 PCI channel permanent disable for failure\n");
@@ -7947,7 +7960,7 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state)
7947 return PCI_ERS_RESULT_NEED_RESET; 7960 return PCI_ERS_RESULT_NEED_RESET;
7948 case pci_channel_io_perm_failure: 7961 case pci_channel_io_perm_failure:
7949 /* Permanent failure, prepare for device down */ 7962 /* Permanent failure, prepare for device down */
7950 lpfc_prep_dev_for_perm_failure(phba); 7963 lpfc_sli_prep_dev_for_perm_failure(phba);
7951 return PCI_ERS_RESULT_DISCONNECT; 7964 return PCI_ERS_RESULT_DISCONNECT;
7952 default: 7965 default:
7953 /* Unknown state, prepare and request slot reset */ 7966 /* Unknown state, prepare and request slot reset */
@@ -8016,7 +8029,8 @@ lpfc_io_slot_reset_s3(struct pci_dev *pdev)
8016 } else 8029 } else
8017 phba->intr_mode = intr_mode; 8030 phba->intr_mode = intr_mode;
8018 8031
8019 /* Take device offline; this will perform cleanup */ 8032 /* Take device offline, it will perform cleanup */
8033 lpfc_offline_prep(phba);
8020 lpfc_offline(phba); 8034 lpfc_offline(phba);
8021 lpfc_sli_brdrestart(phba); 8035 lpfc_sli_brdrestart(phba);
8022 8036
@@ -8201,6 +8215,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
8201 /* Default to single FCP EQ for non-MSI-X */ 8215 /* Default to single FCP EQ for non-MSI-X */
8202 if (phba->intr_type != MSIX) 8216 if (phba->intr_type != MSIX)
8203 phba->cfg_fcp_eq_count = 1; 8217 phba->cfg_fcp_eq_count = 1;
8218 else if (phba->sli4_hba.msix_vec_nr < phba->cfg_fcp_eq_count)
8219 phba->cfg_fcp_eq_count = phba->sli4_hba.msix_vec_nr - 1;
8204 /* Set up SLI-4 HBA */ 8220 /* Set up SLI-4 HBA */
8205 if (lpfc_sli4_hba_setup(phba)) { 8221 if (lpfc_sli4_hba_setup(phba)) {
8206 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 8222 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -8362,7 +8378,7 @@ lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg)
8362 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 8378 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
8363 8379
8364 lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 8380 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
8365 "0298 PCI device Power Management suspend.\n"); 8381 "2843 PCI device Power Management suspend.\n");
8366 8382
8367 /* Bring down the device */ 8383 /* Bring down the device */
8368 lpfc_offline_prep(phba); 8384 lpfc_offline_prep(phba);
@@ -8453,6 +8469,84 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev)
8453} 8469}
8454 8470
8455/** 8471/**
8472 * lpfc_sli4_prep_dev_for_recover - Prepare SLI4 device for pci slot recover
8473 * @phba: pointer to lpfc hba data structure.
8474 *
8475 * This routine is called to prepare the SLI4 device for PCI slot recover. It
8476 * aborts all the outstanding SCSI I/Os to the pci device.
8477 **/
8478static void
8479lpfc_sli4_prep_dev_for_recover(struct lpfc_hba *phba)
8480{
8481 struct lpfc_sli *psli = &phba->sli;
8482 struct lpfc_sli_ring *pring;
8483
8484 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8485 "2828 PCI channel I/O abort preparing for recovery\n");
8486 /*
8487 * There may be errored I/Os through HBA, abort all I/Os on txcmplq
8488 * and let the SCSI mid-layer to retry them to recover.
8489 */
8490 pring = &psli->ring[psli->fcp_ring];
8491 lpfc_sli_abort_iocb_ring(phba, pring);
8492}
8493
8494/**
8495 * lpfc_sli4_prep_dev_for_reset - Prepare SLI4 device for pci slot reset
8496 * @phba: pointer to lpfc hba data structure.
8497 *
8498 * This routine is called to prepare the SLI4 device for PCI slot reset. It
8499 * disables the device interrupt and pci device, and aborts the internal FCP
8500 * pending I/Os.
8501 **/
8502static void
8503lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
8504{
8505 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8506 "2826 PCI channel disable preparing for reset\n");
8507
8508 /* Block any management I/Os to the device */
8509 lpfc_block_mgmt_io(phba);
8510
8511 /* Block all SCSI devices' I/Os on the host */
8512 lpfc_scsi_dev_block(phba);
8513
8514 /* stop all timers */
8515 lpfc_stop_hba_timers(phba);
8516
8517 /* Disable interrupt and pci device */
8518 lpfc_sli4_disable_intr(phba);
8519 pci_disable_device(phba->pcidev);
8520
8521 /* Flush all driver's outstanding SCSI I/Os as we are to reset */
8522 lpfc_sli_flush_fcp_rings(phba);
8523}
8524
8525/**
8526 * lpfc_sli4_prep_dev_for_perm_failure - Prepare SLI4 dev for pci slot disable
8527 * @phba: pointer to lpfc hba data structure.
8528 *
8529 * This routine is called to prepare the SLI4 device for PCI slot permanently
8530 * disabling. It blocks the SCSI transport layer traffic and flushes the FCP
8531 * pending I/Os.
8532 **/
8533static void
8534lpfc_sli4_prep_dev_for_perm_failure(struct lpfc_hba *phba)
8535{
8536 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8537 "2827 PCI channel permanent disable for failure\n");
8538
8539 /* Block all SCSI devices' I/Os on the host */
8540 lpfc_scsi_dev_block(phba);
8541
8542 /* stop all timers */
8543 lpfc_stop_hba_timers(phba);
8544
8545 /* Clean up all driver's outstanding SCSI I/Os */
8546 lpfc_sli_flush_fcp_rings(phba);
8547}
8548
8549/**
8456 * lpfc_io_error_detected_s4 - Method for handling PCI I/O error to SLI-4 device 8550 * lpfc_io_error_detected_s4 - Method for handling PCI I/O error to SLI-4 device
8457 * @pdev: pointer to PCI device. 8551 * @pdev: pointer to PCI device.
8458 * @state: the current PCI connection state. 8552 * @state: the current PCI connection state.
@@ -8471,7 +8565,29 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev)
8471static pci_ers_result_t 8565static pci_ers_result_t
8472lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state) 8566lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state)
8473{ 8567{
8474 return PCI_ERS_RESULT_NEED_RESET; 8568 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8569 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
8570
8571 switch (state) {
8572 case pci_channel_io_normal:
8573 /* Non-fatal error, prepare for recovery */
8574 lpfc_sli4_prep_dev_for_recover(phba);
8575 return PCI_ERS_RESULT_CAN_RECOVER;
8576 case pci_channel_io_frozen:
8577 /* Fatal error, prepare for slot reset */
8578 lpfc_sli4_prep_dev_for_reset(phba);
8579 return PCI_ERS_RESULT_NEED_RESET;
8580 case pci_channel_io_perm_failure:
8581 /* Permanent failure, prepare for device down */
8582 lpfc_sli4_prep_dev_for_perm_failure(phba);
8583 return PCI_ERS_RESULT_DISCONNECT;
8584 default:
8585 /* Unknown state, prepare and request slot reset */
8586 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8587 "2825 Unknown PCI error state: x%x\n", state);
8588 lpfc_sli4_prep_dev_for_reset(phba);
8589 return PCI_ERS_RESULT_NEED_RESET;
8590 }
8475} 8591}
8476 8592
8477/** 8593/**
@@ -8495,6 +8611,39 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state)
8495static pci_ers_result_t 8611static pci_ers_result_t
8496lpfc_io_slot_reset_s4(struct pci_dev *pdev) 8612lpfc_io_slot_reset_s4(struct pci_dev *pdev)
8497{ 8613{
8614 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8615 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
8616 struct lpfc_sli *psli = &phba->sli;
8617 uint32_t intr_mode;
8618
8619 dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
8620 if (pci_enable_device_mem(pdev)) {
8621 printk(KERN_ERR "lpfc: Cannot re-enable "
8622 "PCI device after reset.\n");
8623 return PCI_ERS_RESULT_DISCONNECT;
8624 }
8625
8626 pci_restore_state(pdev);
8627 if (pdev->is_busmaster)
8628 pci_set_master(pdev);
8629
8630 spin_lock_irq(&phba->hbalock);
8631 psli->sli_flag &= ~LPFC_SLI_ACTIVE;
8632 spin_unlock_irq(&phba->hbalock);
8633
8634 /* Configure and enable interrupt */
8635 intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
8636 if (intr_mode == LPFC_INTR_ERROR) {
8637 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
8638 "2824 Cannot re-enable interrupt after "
8639 "slot reset.\n");
8640 return PCI_ERS_RESULT_DISCONNECT;
8641 } else
8642 phba->intr_mode = intr_mode;
8643
8644 /* Log the current active interrupt mode */
8645 lpfc_log_intr_mode(phba, phba->intr_mode);
8646
8498 return PCI_ERS_RESULT_RECOVERED; 8647 return PCI_ERS_RESULT_RECOVERED;
8499} 8648}
8500 8649
@@ -8511,7 +8660,27 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
8511static void 8660static void
8512lpfc_io_resume_s4(struct pci_dev *pdev) 8661lpfc_io_resume_s4(struct pci_dev *pdev)
8513{ 8662{
8514 return; 8663 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8664 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
8665
8666 /*
8667 * In case of slot reset, as function reset is performed through
8668 * mailbox command which needs DMA to be enabled, this operation
8669 * has to be moved to the io resume phase. Taking device offline
8670 * will perform the necessary cleanup.
8671 */
8672 if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE)) {
8673 /* Perform device reset */
8674 lpfc_offline_prep(phba);
8675 lpfc_offline(phba);
8676 lpfc_sli_brdrestart(phba);
8677 /* Bring the device back online */
8678 lpfc_online(phba);
8679 }
8680
8681 /* Clean up Advanced Error Reporting (AER) if needed */
8682 if (phba->hba_flag & HBA_AER_ENABLED)
8683 pci_cleanup_aer_uncorrect_error_status(pdev);
8515} 8684}
8516 8685
8517/** 8686/**
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c6bdf63925d9..f68753ea941f 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -2295,15 +2295,21 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
2295 struct lpfc_vport *vport = pIocbIn->vport; 2295 struct lpfc_vport *vport = pIocbIn->vport;
2296 struct lpfc_rport_data *rdata = lpfc_cmd->rdata; 2296 struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
2297 struct lpfc_nodelist *pnode = rdata->pnode; 2297 struct lpfc_nodelist *pnode = rdata->pnode;
2298 struct scsi_cmnd *cmd = lpfc_cmd->pCmd; 2298 struct scsi_cmnd *cmd;
2299 int result; 2299 int result;
2300 struct scsi_device *tmp_sdev; 2300 struct scsi_device *tmp_sdev;
2301 int depth; 2301 int depth;
2302 unsigned long flags; 2302 unsigned long flags;
2303 struct lpfc_fast_path_event *fast_path_evt; 2303 struct lpfc_fast_path_event *fast_path_evt;
2304 struct Scsi_Host *shost = cmd->device->host; 2304 struct Scsi_Host *shost;
2305 uint32_t queue_depth, scsi_id; 2305 uint32_t queue_depth, scsi_id;
2306 2306
2307 /* Sanity check on return of outstanding command */
2308 if (!(lpfc_cmd->pCmd))
2309 return;
2310 cmd = lpfc_cmd->pCmd;
2311 shost = cmd->device->host;
2312
2307 lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; 2313 lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
2308 lpfc_cmd->status = pIocbOut->iocb.ulpStatus; 2314 lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
2309 /* pick up SLI4 exhange busy status from HBA */ 2315 /* pick up SLI4 exhange busy status from HBA */
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index ae3cb0ab0ae4..9c609546b4ef 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -3593,13 +3593,16 @@ static int
3593lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) 3593lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
3594{ 3594{
3595 struct lpfc_sli *psli = &phba->sli; 3595 struct lpfc_sli *psli = &phba->sli;
3596 3596 uint32_t hba_aer_enabled;
3597 3597
3598 /* Restart HBA */ 3598 /* Restart HBA */
3599 lpfc_printf_log(phba, KERN_INFO, LOG_SLI, 3599 lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
3600 "0296 Restart HBA Data: x%x x%x\n", 3600 "0296 Restart HBA Data: x%x x%x\n",
3601 phba->pport->port_state, psli->sli_flag); 3601 phba->pport->port_state, psli->sli_flag);
3602 3602
3603 /* Take PCIe device Advanced Error Reporting (AER) state */
3604 hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED;
3605
3603 lpfc_sli4_brdreset(phba); 3606 lpfc_sli4_brdreset(phba);
3604 3607
3605 spin_lock_irq(&phba->hbalock); 3608 spin_lock_irq(&phba->hbalock);
@@ -3611,6 +3614,10 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
3611 memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets)); 3614 memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
3612 psli->stats_start = get_seconds(); 3615 psli->stats_start = get_seconds();
3613 3616
3617 /* Reset HBA AER if it was enabled, note hba_flag was reset above */
3618 if (hba_aer_enabled)
3619 pci_disable_pcie_error_reporting(phba->pcidev);
3620
3614 lpfc_hba_down_post(phba); 3621 lpfc_hba_down_post(phba);
3615 3622
3616 return 0; 3623 return 0;
@@ -4554,6 +4561,24 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
4554 /* Start error attention (ERATT) polling timer */ 4561 /* Start error attention (ERATT) polling timer */
4555 mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL); 4562 mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL);
4556 4563
4564 /* Enable PCIe device Advanced Error Reporting (AER) if configured */
4565 if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) {
4566 rc = pci_enable_pcie_error_reporting(phba->pcidev);
4567 if (!rc) {
4568 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
4569 "2829 This device supports "
4570 "Advanced Error Reporting (AER)\n");
4571 spin_lock_irq(&phba->hbalock);
4572 phba->hba_flag |= HBA_AER_ENABLED;
4573 spin_unlock_irq(&phba->hbalock);
4574 } else {
4575 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
4576 "2830 This device does not support "
4577 "Advanced Error Reporting (AER)\n");
4578 phba->cfg_aer_support = 0;
4579 }
4580 }
4581
4557 /* 4582 /*
4558 * The port is ready, set the host's link state to LINK_DOWN 4583 * The port is ready, set the host's link state to LINK_DOWN
4559 * in preparation for link interrupts. 4584 * in preparation for link interrupts.
@@ -9089,9 +9114,10 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
9089 } 9114 }
9090 } 9115 }
9091 if (unlikely(!cq)) { 9116 if (unlikely(!cq)) {
9092 lpfc_printf_log(phba, KERN_ERR, LOG_SLI, 9117 if (phba->sli.sli_flag & LPFC_SLI_ACTIVE)
9093 "0365 Slow-path CQ identifier (%d) does " 9118 lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
9094 "not exist\n", cqid); 9119 "0365 Slow-path CQ identifier "
9120 "(%d) does not exist\n", cqid);
9095 return; 9121 return;
9096 } 9122 }
9097 9123
@@ -9321,9 +9347,10 @@ lpfc_sli4_fp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
9321 9347
9322 cq = phba->sli4_hba.fcp_cq[fcp_cqidx]; 9348 cq = phba->sli4_hba.fcp_cq[fcp_cqidx];
9323 if (unlikely(!cq)) { 9349 if (unlikely(!cq)) {
9324 lpfc_printf_log(phba, KERN_ERR, LOG_SLI, 9350 if (phba->sli.sli_flag & LPFC_SLI_ACTIVE)
9325 "0367 Fast-path completion queue does not " 9351 lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
9326 "exist\n"); 9352 "0367 Fast-path completion queue "
9353 "does not exist\n");
9327 return; 9354 return;
9328 } 9355 }
9329 9356
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index 1f8ec72c5dcb..ccdb95774e84 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -382,6 +382,7 @@ struct lpfc_sli4_hba {
382 struct lpfc_pc_sli4_params pc_sli4_params; 382 struct lpfc_pc_sli4_params pc_sli4_params;
383 struct msix_entry *msix_entries; 383 struct msix_entry *msix_entries;
384 uint32_t cfg_eqn; 384 uint32_t cfg_eqn;
385 uint32_t msix_vec_nr;
385 struct lpfc_fcp_eq_hdl *fcp_eq_hdl; /* FCP per-WQ handle */ 386 struct lpfc_fcp_eq_hdl *fcp_eq_hdl; /* FCP per-WQ handle */
386 /* Pointers to the constructed SLI4 queues */ 387 /* Pointers to the constructed SLI4 queues */
387 struct lpfc_queue **fp_eq; /* Fast-path event queue */ 388 struct lpfc_queue **fp_eq; /* Fast-path event queue */