Skip to content

Commit

Permalink
pds_core: add attempts to fix broken PCI
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Shannon Nelson authored and David S. Miller committed Sep 18, 2023
1 parent ffa5585 commit 1e18ec3
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 2 deletions.
14 changes: 14 additions & 0 deletions drivers/net/ethernet/amd/pds_core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,18 @@ void pdsc_fw_up(struct pdsc *pdsc)
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);
Expand All @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/amd/pds_core/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/amd/pds_core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;
Expand Down

0 comments on commit 1e18ec3

Please sign in to comment.