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 device dependent PE.

Signed-off-by: Gavin Shan <sha...@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/eeh.h          |    1 +
 arch/powerpc/platforms/pseries/eeh_pe.c |   25 ++++++++++++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 9230aa4..557d82a 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -62,6 +62,7 @@ struct eeh_pe {
        int check_count;                /* Times of ignored error       */
        int freeze_count;               /* Times of froze up            */
        int false_positives;            /* Times of reported #ff's      */
+       struct pci_bus *bus;            /* Top PCI bus for bus PE       */
        struct eeh_pe *parent;          /* Parent PE                    */
        struct list_head child_list;    /* Link PE to the child list    */
        struct list_head edevs;         /* Link list of EEH devices     */
diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c 
b/arch/powerpc/platforms/pseries/eeh_pe.c
index 93ed9cb..03f8223 100644
--- a/arch/powerpc/platforms/pseries/eeh_pe.c
+++ b/arch/powerpc/platforms/pseries/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();
@@ -639,13 +655,20 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
 
        if (pe->type & EEH_PE_PHB) {
                bus = pe->phb->bus;
-       } else if (pe->type & EEH_PE_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

Reply via email to