aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c96
1 files changed, 72 insertions, 24 deletions
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 **/
7144static void
7145lpfc_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 **/
7172static void
7173lpfc_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/**