diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-04-07 10:16:00 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-04-10 08:52:36 -0400 |
commit | 9b37960523afb1b519b406dec4c4f3155b82b2ba (patch) | |
tree | b6a2d07f0f441911c4f7d7580770c23f90c5167e /drivers | |
parent | 58da1ffb2b1234e9c6c75013a649c659cc38ebd4 (diff) |
[SCSI] lpfc 8.2.6 : PCI Parity and EEH handling fixes
PCI Parity and EEH handling Fixes:
- Under a PCI Data Parity Error, remove a completion routine callback that
was on a command that we had already failed and released.
- Under PCI parity error, we were not reinstalling the interrupt handler
in the slot_reset callback, so we never became functional again.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 31 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 3 |
2 files changed, 32 insertions, 2 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 26c67c866d1f..dba6770b506b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -2371,6 +2371,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | |||
2371 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 2371 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
2372 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; | 2372 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
2373 | struct lpfc_sli *psli = &phba->sli; | 2373 | struct lpfc_sli *psli = &phba->sli; |
2374 | int error, retval; | ||
2374 | 2375 | ||
2375 | dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); | 2376 | dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); |
2376 | if (pci_enable_device_mem(pdev)) { | 2377 | if (pci_enable_device_mem(pdev)) { |
@@ -2385,6 +2386,36 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | |||
2385 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | 2386 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; |
2386 | spin_unlock_irq(&phba->hbalock); | 2387 | spin_unlock_irq(&phba->hbalock); |
2387 | 2388 | ||
2389 | /* Enable configured interrupt method */ | ||
2390 | phba->intr_type = NONE; | ||
2391 | if (phba->cfg_use_msi == 2) { | ||
2392 | error = lpfc_enable_msix(phba); | ||
2393 | if (!error) | ||
2394 | phba->intr_type = MSIX; | ||
2395 | } | ||
2396 | |||
2397 | /* Fallback to MSI if MSI-X initialization failed */ | ||
2398 | if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) { | ||
2399 | retval = pci_enable_msi(phba->pcidev); | ||
2400 | if (!retval) | ||
2401 | phba->intr_type = MSI; | ||
2402 | else | ||
2403 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2404 | "0470 Enable MSI failed, continuing " | ||
2405 | "with IRQ\n"); | ||
2406 | } | ||
2407 | |||
2408 | /* MSI-X is the only case the doesn't need to call request_irq */ | ||
2409 | if (phba->intr_type != MSIX) { | ||
2410 | retval = request_irq(phba->pcidev->irq, lpfc_intr_handler, | ||
2411 | IRQF_SHARED, LPFC_DRIVER_NAME, phba); | ||
2412 | if (retval) { | ||
2413 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2414 | "0471 Enable interrupt handler " | ||
2415 | "failed\n"); | ||
2416 | } else if (phba->intr_type != MSI) | ||
2417 | phba->intr_type = INTx; | ||
2418 | } | ||
2388 | 2419 | ||
2389 | /* Take device offline; this will perform cleanup */ | 2420 | /* Take device offline; this will perform cleanup */ |
2390 | lpfc_offline(phba); | 2421 | lpfc_offline(phba); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index c71b9a577770..741e94af4793 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -3634,8 +3634,7 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
3634 | * If the iocb is not found in Firmware queue the iocb | 3634 | * If the iocb is not found in Firmware queue the iocb |
3635 | * might have completed already. Do not free it again. | 3635 | * might have completed already. Do not free it again. |
3636 | */ | 3636 | */ |
3637 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 3637 | if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) { |
3638 | (irsp->un.ulpWord[4] == IOERR_NO_XRI)) { | ||
3639 | spin_unlock_irq(&phba->hbalock); | 3638 | spin_unlock_irq(&phba->hbalock); |
3640 | lpfc_sli_release_iocbq(phba, cmdiocb); | 3639 | lpfc_sli_release_iocbq(phba, cmdiocb); |
3641 | return; | 3640 | return; |