From: Qiuxu Zhuo <qiuxu.zhuo@xxxxxxxxx> Attempt to do function level reset for an RCiEP associated with an RCEC device on fatal error. Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@xxxxxxxxx> --- drivers/pci/pcie/err.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 044df004f20b..9b3ec94bdf1d 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -170,6 +170,17 @@ static void pci_walk_dev_affected(struct pci_dev *dev, int (*cb)(struct pci_dev } } +static enum pci_channel_state flr_on_rciep(struct pci_dev *dev) +{ + if (!pcie_has_flr(dev)) + return PCI_ERS_RESULT_NONE; + + if (pcie_flr(dev)) + return PCI_ERS_RESULT_DISCONNECT; + + return PCI_ERS_RESULT_RECOVERED; +} + pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, enum pci_channel_state state, pci_ers_result_t (*reset_link)(struct pci_dev *pdev)) @@ -191,15 +202,17 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, if (state == pci_channel_io_frozen) { pci_walk_dev_affected(dev, report_frozen_detected, &status); if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) { - pci_warn(dev, "link reset not possible for RCiEP\n"); - status = PCI_ERS_RESULT_NONE; - goto failed; - } - - status = reset_link(dev); - if (status != PCI_ERS_RESULT_RECOVERED) { - pci_warn(dev, "link reset failed\n"); - goto failed; + status = flr_on_rciep(dev); + if (status != PCI_ERS_RESULT_RECOVERED) { + pci_warn(dev, "function level reset failed\n"); + goto failed; + } + } else { + status = reset_link(dev); + if (status != PCI_ERS_RESULT_RECOVERED) { + pci_warn(dev, "link reset failed\n"); + goto failed; + } } } else { pci_walk_dev_affected(dev, report_normal_detected, &status); -- 2.27.0