[PATCH 05/22] powerpc/eeh: Trace PCI bus from PE
Gavin Shan
shangw at linux.vnet.ibm.com
Wed May 15 13:34:41 EST 2013
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 <shangw at 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
More information about the Linuxppc-dev
mailing list