On Wed, May 14, 2025 at 12:00:11PM +0530, Krishna Chaitanya Chundru wrote: > > > On 5/8/2025 12:40 PM, Manivannan Sadhasivam wrote: > > The PCI link, when down, needs to be recovered to bring it back. But that > > cannot be done in a generic way as link recovery procedure is specific to > > host bridges. So add a new API pci_host_handle_link_down() that could be > > called by the host bridge drivers when the link goes down. > > > > The API will iterate through all the slots and calls the pcie_do_recovery() > > function with 'pci_channel_io_frozen' as the state. This will result in the > > execution of the AER Fatal error handling code. Since the link down > > recovery is pretty much the same as AER Fatal error handling, > > pcie_do_recovery() helper is reused here. First the AER error_detected > > callback will be triggered for the bridge and the downstream devices. Then, > > pci_host_reset_slot() will be called for the slot, which will reset the > > slot using 'reset_slot' callback to recover the link. Once that's done, > > resume message will be broadcasted to the bridge and the downstream devices > > indicating successful link recovery. > > > > In case if the AER support is not enabled in the kernel, only > > pci_bus_error_reset() will be called for each slots as there is no way we > > could inform the drivers about link recovery. > > > > Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasi...@linaro.org> > > --- > > drivers/pci/controller/pci-host-common.c | 58 > > ++++++++++++++++++++++++++++++++ > > drivers/pci/controller/pci-host-common.h | 1 + > > drivers/pci/pci.c | 1 + > > drivers/pci/pcie/err.c | 1 + > > 4 files changed, 61 insertions(+) > > > > diff --git a/drivers/pci/controller/pci-host-common.c > > b/drivers/pci/controller/pci-host-common.c > > index > > f93bc7034e697250711833a5151f7ef177cd62a0..f916f0a874a61ddfbfd99f96975c00fb66dd224c > > 100644 > > --- a/drivers/pci/controller/pci-host-common.c > > +++ b/drivers/pci/controller/pci-host-common.c > > @@ -12,9 +12,11 @@ > > #include <linux/of.h> > > #include <linux/of_address.h> > > #include <linux/of_pci.h> > > +#include <linux/pci.h> > > #include <linux/pci-ecam.h> > > #include <linux/platform_device.h> > > +#include "../pci.h" > > #include "pci-host-common.h" > > static void gen_pci_unmap_cfg(void *ptr) > > @@ -96,5 +98,61 @@ void pci_host_common_remove(struct platform_device *pdev) > > } > > EXPORT_SYMBOL_GPL(pci_host_common_remove); > > +#if IS_ENABLED(CONFIG_PCIEAER) > > +static pci_ers_result_t pci_host_reset_slot(struct pci_dev *dev) > > +{ > > + int ret; > > + > > + ret = pci_bus_error_reset(dev); > > + if (ret) { > > + pci_err(dev, "Failed to reset slot: %d\n", ret); > > + return PCI_ERS_RESULT_DISCONNECT; > > + } > > + > > + pci_info(dev, "Slot has been reset\n"); > > + > > + return PCI_ERS_RESULT_RECOVERED; > > +} > > + > > +static void pci_host_recover_slots(struct pci_host_bridge *host) > > +{ > > + struct pci_bus *bus = host->bus; > > + struct pci_dev *dev; > > + > > + for_each_pci_bridge(dev, bus) { > > + if (!pci_is_root_bus(bus)) > bus here is always constant here, we may need to have check > for dev here like if (!pci_is_root_bus(dev->bus))
Good catch! Ammended it while applying. - Mani -- மணிவண்ணன் சதாசிவம்