If AER attempts to do recovery for any device, and DPC is active on any upstream port, AER should not do recovery, since it will be handled by DPC Change-Id: Ida507ce9145f420e35302db34e967f1b421e15c9 Signed-off-by: Oza Pawandeep <poza@xxxxxxxxxxxxxx> diff --git a/drivers/pci/pcie/pcie-err.c b/drivers/pci/pcie/pcie-err.c index 858c94c..1991cc8 100644 --- a/drivers/pci/pcie/pcie-err.c +++ b/drivers/pci/pcie/pcie-err.c @@ -274,6 +274,22 @@ pci_ers_result_t pci_broadcast_error_message(struct pci_dev *dev, return result_data.result; } +/* + * pcie_port_upstream_bridge - returns immediate upstream bridge. + * dev: pcie device + */ +static struct pci_dev *pcie_port_upstream_bridge(struct pci_dev *dev) +{ + struct pci_dev *parent; + + parent = pci_upstream_bridge(dev); + + if (parent && pci_is_pcie(parent)) + return parent; + + return NULL; +} + /** * pci_do_recovery - handle nonfatal/fatal error recovery process * @dev: pointer to a pci_dev data structure of agent detecting an error @@ -287,9 +303,29 @@ void pci_do_recovery(struct pci_dev *dev, int severity) { pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED; enum pci_channel_state state; + struct pcie_port_service_driver *driver; + struct pci_dev *pdev = dev; mutex_lock(&pci_err_recovery_lock); + if (severity != PCI_ERR_DPC_FATAL) { + /* + * DPC service could be running in RP + * or any upstream switch. + */ + do { + driver = pci_find_dpc_service(pdev); + if (driver) { + dev_printk(KERN_NOTICE, &dev->dev, + "AER: Recovery to be done by DPC %s\n", + pci_name(dev)); + mutex_unlock(&pci_err_recovery_lock); + return; + } + pdev = pcie_port_upstream_bridge(dev); + } while (pdev); + } + if ((severity == PCI_ERR_AER_FATAL) || (severity == PCI_ERR_DPC_FATAL)) state = pci_channel_io_frozen; -- Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc., a Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.