There're several types of PEs can be supported for now: PHB, Bus and Device dependent PE. For PCI bus dependent PE, tracing the corresponding PCI bus from PE (struct eeh_pe) would make the code more efficient. The patch also enables the retrieval of PCI bus based on the PCI bus dependent PE.
Signed-off-by: Gavin Shan <sha...@linux.vnet.ibm.com> --- arch/powerpc/include/asm/eeh.h | 1 + arch/powerpc/kernel/eeh_pe.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index acdfcaa..f3b49d6 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -59,6 +59,7 @@ struct eeh_pe { int config_addr; /* Traditional PCI address */ int addr; /* PE configuration address */ struct pci_controller *phb; /* Associated PHB */ + struct pci_bus *bus; /* Top PCI bus for bus PE */ int check_count; /* Times of ignored error */ int freeze_count; /* Times of froze up */ int false_positives; /* Times of reported #ff's */ diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 3d2dcf5..5bd1637 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c @@ -304,6 +304,7 @@ static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev) int eeh_add_to_parent_pe(struct eeh_dev *edev) { struct eeh_pe *pe, *parent; + struct eeh_dev *first_edev; eeh_lock(); @@ -326,6 +327,21 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) pe->type = EEH_PE_BUS; edev->pe = pe; + /* + * For PCI bus sensitive PE, we can reset the parent + * bridge in order for hot-reset. However, the PCI + * devices including the associated EEH devices might + * be removed when EEH core is doing recovery. So that + * won't safe to retrieve the bridge through downstream + * EEH device. We have to trace the parent PCI bus, then + * the parent bridge explicitly. + */ + if (eeh_probe_mode_dev() && !pe->bus) { + first_edev = list_first_entry(&pe->edevs, + struct eeh_dev, list); + pe->bus = eeh_dev_to_pci_dev(first_edev)->bus; + } + /* Put the edev to PE */ list_add_tail(&edev->list, &pe->edevs); eeh_unlock(); @@ -641,12 +657,18 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) bus = pe->phb->bus; } else if (pe->type & EEH_PE_BUS || pe->type & EEH_PE_DEVICE) { + if (pe->bus) { + bus = pe->bus; + goto out; + } + edev = list_first_entry(&pe->edevs, struct eeh_dev, list); pdev = eeh_dev_to_pci_dev(edev); if (pdev) bus = pdev->bus; } +out: eeh_unlock(); return bus; -- 1.7.5.4 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev