pds_core: add attempts to fix broken PCI
If we see a 0xff value from a PCI register read, we know that the PCI connection is broken, possibly by a low level reset that didn't go through the nice pci_error_handlers path. Make use of the PCI cleanup code that we already have from the reset handlers and add some detection and attempted recovery from a broken PCI connection. Signed-off-by: Shannon Nelson <shannon.nelson@amd.com> Reviewed-by: Brett Creeley <brett.creeley@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ffa5585833
commit
1e18ec3e9d
@ -578,6 +578,18 @@ err_out:
|
||||
pdsc_teardown(pdsc, PDSC_TEARDOWN_RECOVERY);
|
||||
}
|
||||
|
||||
static void pdsc_check_pci_health(struct pdsc *pdsc)
|
||||
{
|
||||
u8 fw_status = ioread8(&pdsc->info_regs->fw_status);
|
||||
|
||||
/* is PCI broken? */
|
||||
if (fw_status != PDS_RC_BAD_PCI)
|
||||
return;
|
||||
|
||||
pdsc_reset_prepare(pdsc->pdev);
|
||||
pdsc_reset_done(pdsc->pdev);
|
||||
}
|
||||
|
||||
void pdsc_health_thread(struct work_struct *work)
|
||||
{
|
||||
struct pdsc *pdsc = container_of(work, struct pdsc, health_work);
|
||||
@ -604,6 +616,8 @@ void pdsc_health_thread(struct work_struct *work)
|
||||
pdsc_fw_down(pdsc);
|
||||
}
|
||||
|
||||
pdsc_check_pci_health(pdsc);
|
||||
|
||||
pdsc->fw_generation = pdsc->fw_status & PDS_CORE_FW_STS_F_GENERATION;
|
||||
|
||||
out_unlock:
|
||||
|
@ -283,6 +283,9 @@ int pdsc_devcmd_reset(struct pdsc *pdsc);
|
||||
int pdsc_dev_reinit(struct pdsc *pdsc);
|
||||
int pdsc_dev_init(struct pdsc *pdsc);
|
||||
|
||||
void pdsc_reset_prepare(struct pci_dev *pdev);
|
||||
void pdsc_reset_done(struct pci_dev *pdev);
|
||||
|
||||
int pdsc_intr_alloc(struct pdsc *pdsc, char *name,
|
||||
irq_handler_t handler, void *data);
|
||||
void pdsc_intr_free(struct pdsc *pdsc, int index);
|
||||
|
@ -445,7 +445,7 @@ static void pdsc_remove(struct pci_dev *pdev)
|
||||
devlink_free(dl);
|
||||
}
|
||||
|
||||
static void pdsc_reset_prepare(struct pci_dev *pdev)
|
||||
void pdsc_reset_prepare(struct pci_dev *pdev)
|
||||
{
|
||||
struct pdsc *pdsc = pci_get_drvdata(pdev);
|
||||
|
||||
@ -457,7 +457,7 @@ static void pdsc_reset_prepare(struct pci_dev *pdev)
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static void pdsc_reset_done(struct pci_dev *pdev)
|
||||
void pdsc_reset_done(struct pci_dev *pdev)
|
||||
{
|
||||
struct pdsc *pdsc = pci_get_drvdata(pdev);
|
||||
struct device *dev = pdsc->dev;
|
||||
|
Loading…
x
Reference in New Issue
Block a user