diff options
| author | Gavin Shan | 2015-03-17 06:15:06 +0100 | 
|---|---|---|
| committer | Benjamin Herrenschmidt | 2015-03-24 03:15:52 +0100 | 
| commit | ff57b454ddb938d98d48d8df356357000fedc88c (patch) | |
| tree | afb1399b36a933d563ee171fd529e6cf526031a5 /arch/powerpc | |
| parent | powerpc/eeh: Create eeh_dev from pci_dn instead of device_node (diff) | |
| download | kernel-qcow2-linux-ff57b454ddb938d98d48d8df356357000fedc88c.tar.gz kernel-qcow2-linux-ff57b454ddb938d98d48d8df356357000fedc88c.tar.xz kernel-qcow2-linux-ff57b454ddb938d98d48d8df356357000fedc88c.zip | |
powerpc/eeh: Do probe on pci_dn
Originally, EEH core probes on device_node or pci_dev to populate
EEH devices and PEs, which conflicts with the fact: SRIOV VFs are
usually enabled and created by PF's driver and they don't have the
corresponding device_nodes. Instead, SRIOV VFs have dynamically
created pci_dn, which can be used for EEH probe.
The patch reworks EEH probe for PowerNV and pSeries platforms to
do probing based on pci_dn, instead of pci_dev or device_node any
more.
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
| -rw-r--r-- | arch/powerpc/include/asm/eeh.h | 11 | ||||
| -rw-r--r-- | arch/powerpc/kernel/eeh.c | 63 | ||||
| -rw-r--r-- | arch/powerpc/kernel/of_platform.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/pci-hotplug.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/powernv/eeh-powernv.c | 146 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/eeh_pseries.c | 82 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/pci_dlpar.c | 2 | 
7 files changed, 171 insertions, 137 deletions
| diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 2106f83da2d5..87797811808f 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h @@ -207,8 +207,7 @@ struct eeh_ops {  	char *name;  	int (*init)(void);  	int (*post_init)(void); -	void* (*of_probe)(struct device_node *dn, void *flag); -	int (*dev_probe)(struct pci_dev *dev, void *flag); +	void* (*probe)(struct pci_dn *pdn, void *data);  	int (*set_option)(struct eeh_pe *pe, int option);  	int (*get_pe_addr)(struct eeh_pe *pe);  	int (*get_state)(struct eeh_pe *pe, int *state); @@ -287,8 +286,8 @@ int __exit eeh_ops_unregister(const char *name);  int eeh_check_failure(const volatile void __iomem *token);  int eeh_dev_check_failure(struct eeh_dev *edev);  void eeh_addr_cache_build(void); -void eeh_add_device_early(struct device_node *); -void eeh_add_device_tree_early(struct device_node *); +void eeh_add_device_early(struct pci_dn *); +void eeh_add_device_tree_early(struct pci_dn *);  void eeh_add_device_late(struct pci_dev *);  void eeh_add_device_tree_late(struct pci_bus *);  void eeh_add_sysfs_files(struct pci_bus *); @@ -346,9 +345,9 @@ static inline int eeh_check_failure(const volatile void __iomem *token)  static inline void eeh_addr_cache_build(void) { } -static inline void eeh_add_device_early(struct device_node *dn) { } +static inline void eeh_add_device_early(struct pci_dn *pdn) { } -static inline void eeh_add_device_tree_early(struct device_node *dn) { } +static inline void eeh_add_device_tree_early(struct pci_dn *pdn) { }  static inline void eeh_add_device_late(struct pci_dev *dev) { } diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 19a897c810be..9504c2f0bb54 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -969,7 +969,7 @@ static struct notifier_block eeh_reboot_nb = {  int eeh_init(void)  {  	struct pci_controller *hose, *tmp; -	struct device_node *phb; +	struct pci_dn *pdn;  	static int cnt = 0;  	int ret = 0; @@ -1004,20 +1004,9 @@ int eeh_init(void)  		return ret;  	/* Enable EEH for all adapters */ -	if (eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) { -		list_for_each_entry_safe(hose, tmp, -			&hose_list, list_node) { -			phb = hose->dn; -			traverse_pci_devices(phb, eeh_ops->of_probe, NULL); -		} -	} else if (eeh_has_flag(EEH_PROBE_MODE_DEV)) { -		list_for_each_entry_safe(hose, tmp, -			&hose_list, list_node) -			pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL); -	} else { -		pr_warn("%s: Invalid probe mode %x", -			__func__, eeh_subsystem_flags); -		return -EINVAL; +	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { +		pdn = hose->pci_data; +		traverse_pci_dn(pdn, eeh_ops->probe, NULL);  	}  	/* @@ -1043,7 +1032,7 @@ core_initcall_sync(eeh_init);  /**   * eeh_add_device_early - Enable EEH for the indicated device_node - * @dn: device node for which to set up EEH + * @pdn: PCI device node for which to set up EEH   *   * This routine must be used to perform EEH initialization for PCI   * devices that were added after system boot (e.g. hotplug, dlpar). @@ -1053,44 +1042,41 @@ core_initcall_sync(eeh_init);   * on the CEC architecture, type of the device, on earlier boot   * command-line arguments & etc.   */ -void eeh_add_device_early(struct device_node *dn) +void eeh_add_device_early(struct pci_dn *pdn)  {  	struct pci_controller *phb; +	struct eeh_dev *edev = pdn_to_eeh_dev(pdn); -	/* -	 * If we're doing EEH probe based on PCI device, we -	 * would delay the probe until late stage because -	 * the PCI device isn't available this moment. -	 */ -	if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) -		return; - -	if (!of_node_to_eeh_dev(dn)) +	if (!edev)  		return; -	phb = of_node_to_eeh_dev(dn)->phb;  	/* USB Bus children of PCI devices will not have BUID's */ -	if (NULL == phb || 0 == phb->buid) +	phb = edev->phb; +	if (NULL == phb || +	    (eeh_has_flag(EEH_PROBE_MODE_DEVTREE) && 0 == phb->buid))  		return; -	eeh_ops->of_probe(dn, NULL); +	eeh_ops->probe(pdn, NULL);  }  /**   * eeh_add_device_tree_early - Enable EEH for the indicated device - * @dn: device node + * @pdn: PCI device node   *   * This routine must be used to perform EEH initialization for the   * indicated PCI device that was added after system boot (e.g.   * hotplug, dlpar).   */ -void eeh_add_device_tree_early(struct device_node *dn) +void eeh_add_device_tree_early(struct pci_dn *pdn)  { -	struct device_node *sib; +	struct pci_dn *n; + +	if (!pdn) +		return; -	for_each_child_of_node(dn, sib) -		eeh_add_device_tree_early(sib); -	eeh_add_device_early(dn); +	list_for_each_entry(n, &pdn->child_list, list) +		eeh_add_device_tree_early(n); +	eeh_add_device_early(pdn);  }  EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); @@ -1144,13 +1130,6 @@ void eeh_add_device_late(struct pci_dev *dev)  	edev->pdev = dev;  	dev->dev.archdata.edev = edev; -	/* -	 * We have to do the EEH probe here because the PCI device -	 * hasn't been created yet in the early stage. -	 */ -	if (eeh_has_flag(EEH_PROBE_MODE_DEV)) -		eeh_ops->dev_probe(dev, NULL); -  	eeh_addr_cache_insert_dev(dev);  } diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 2f35a72642c6..b60a67d92ebd 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -72,7 +72,7 @@ static int of_pci_phb_probe(struct platform_device *dev)  	/* Register devices with EEH */  	if (dev->dev.of_node->child) -		eeh_add_device_tree_early(dev->dev.of_node); +		eeh_add_device_tree_early(PCI_DN(dev->dev.of_node));  	/* Scan the bus */  	pcibios_scan_phb(phb); diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 5b789177aa29..18d9575729a3 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c @@ -75,7 +75,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus)  	struct pci_dev *dev;  	struct device_node *dn = pci_bus_to_OF_node(bus); -	eeh_add_device_tree_early(dn); +	eeh_add_device_tree_early(PCI_DN(dn));  	mode = PCI_PROBE_NORMAL;  	if (ppc_md.pci_probe_mode) diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 8eac8c57ee86..dcc524fe2a30 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -286,10 +286,82 @@ static int pnv_eeh_post_init(void)  	return ret;  } +static int pnv_eeh_cap_start(struct pci_dn *pdn) +{ +	u32 status; + +	if (!pdn) +		return 0; + +	pnv_pci_cfg_read(pdn, PCI_STATUS, 2, &status); +	if (!(status & PCI_STATUS_CAP_LIST)) +		return 0; + +	return PCI_CAPABILITY_LIST; +} + +static int pnv_eeh_find_cap(struct pci_dn *pdn, int cap) +{ +	int pos = pnv_eeh_cap_start(pdn); +	int cnt = 48;   /* Maximal number of capabilities */ +	u32 id; + +	if (!pos) +		return 0; + +	while (cnt--) { +		pnv_pci_cfg_read(pdn, pos, 1, &pos); +		if (pos < 0x40) +			break; + +		pos &= ~3; +		pnv_pci_cfg_read(pdn, pos + PCI_CAP_LIST_ID, 1, &id); +		if (id == 0xff) +			break; + +		/* Found */ +		if (id == cap) +			return pos; + +		/* Next one */ +		pos += PCI_CAP_LIST_NEXT; +	} + +	return 0; +} + +static int pnv_eeh_find_ecap(struct pci_dn *pdn, int cap) +{ +	struct eeh_dev *edev = pdn_to_eeh_dev(pdn); +	u32 header; +	int pos = 256, ttl = (4096 - 256) / 8; + +	if (!edev || !edev->pcie_cap) +		return 0; +	if (pnv_pci_cfg_read(pdn, pos, 4, &header) != PCIBIOS_SUCCESSFUL) +		return 0; +	else if (!header) +		return 0; + +	while (ttl-- > 0) { +		if (PCI_EXT_CAP_ID(header) == cap && pos) +			return pos; + +		pos = PCI_EXT_CAP_NEXT(header); +		if (pos < 256) +			break; + +		if (pnv_pci_cfg_read(pdn, pos, 4, &header) != PCIBIOS_SUCCESSFUL) +			break; +	} + +	return 0; +} +  /** - * pnv_eeh_dev_probe - Do probe on PCI device - * @dev: PCI device - * @flag: unused + * pnv_eeh_probe - Do probe on PCI device + * @pdn: PCI device node + * @data: unused   *   * When EEH module is installed during system boot, all PCI devices   * are checked one by one to see if it supports EEH. The function @@ -303,12 +375,12 @@ static int pnv_eeh_post_init(void)   * was possiblly triggered by EEH core, the binding between EEH device   * and the PCI device isn't built yet.   */ -static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) +static void *pnv_eeh_probe(struct pci_dn *pdn, void *data)  { -	struct pci_controller *hose = pci_bus_to_host(dev->bus); +	struct pci_controller *hose = pdn->phb;  	struct pnv_phb *phb = hose->private_data; -	struct device_node *dn = pci_device_to_OF_node(dev); -	struct eeh_dev *edev = of_node_to_eeh_dev(dn); +	struct eeh_dev *edev = pdn_to_eeh_dev(pdn); +	uint32_t pcie_flags;  	int ret;  	/* @@ -317,40 +389,42 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag)  	 * the root bridge. So it's not reasonable to continue  	 * the probing.  	 */ -	if (!dn || !edev || edev->pe) -		return 0; +	if (!edev || edev->pe) +		return NULL;  	/* Skip for PCI-ISA bridge */ -	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_ISA) -		return 0; +	if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) +		return NULL;  	/* Initialize eeh device */ -	edev->class_code = dev->class; +	edev->class_code = pdn->class_code;  	edev->mode	&= 0xFFFFFF00; -	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) +	edev->pcix_cap = pnv_eeh_find_cap(pdn, PCI_CAP_ID_PCIX); +	edev->pcie_cap = pnv_eeh_find_cap(pdn, PCI_CAP_ID_EXP); +	edev->aer_cap  = pnv_eeh_find_ecap(pdn, PCI_EXT_CAP_ID_ERR); +	if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) {  		edev->mode |= EEH_DEV_BRIDGE; -	edev->pcix_cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); -	if (pci_is_pcie(dev)) { -		edev->pcie_cap = pci_pcie_cap(dev); - -		if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) -			edev->mode |= EEH_DEV_ROOT_PORT; -		else if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) -			edev->mode |= EEH_DEV_DS_PORT; - -		edev->aer_cap = pci_find_ext_capability(dev, -							PCI_EXT_CAP_ID_ERR); +		if (edev->pcie_cap) { +			pnv_pci_cfg_read(pdn, edev->pcie_cap + PCI_EXP_FLAGS, +					 2, &pcie_flags); +			pcie_flags = (pcie_flags & PCI_EXP_FLAGS_TYPE) >> 4; +			if (pcie_flags == PCI_EXP_TYPE_ROOT_PORT) +				edev->mode |= EEH_DEV_ROOT_PORT; +			else if (pcie_flags == PCI_EXP_TYPE_DOWNSTREAM) +				edev->mode |= EEH_DEV_DS_PORT; +		}  	} -	edev->config_addr	= ((dev->bus->number << 8) | dev->devfn); -	edev->pe_config_addr	= phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); +	edev->config_addr    = (pdn->busno << 8) | (pdn->devfn); +	edev->pe_config_addr = phb->ioda.pe_rmap[edev->config_addr];  	/* Create PE */  	ret = eeh_add_to_parent_pe(edev);  	if (ret) { -		pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n", -			__func__, pci_name(dev), ret); -		return ret; +		pr_warn("%s: Can't add PCI dev %04x:%02x:%02x.%01x to parent PE (%d)\n", +			__func__, hose->global_number, pdn->busno, +			PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn), ret); +		return NULL;  	}  	/* @@ -369,8 +443,10 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag)  	 * Broadcom Austin 4-ports NICs (14e4:1657)  	 * Broadcom Shiner 2-ports 10G NICs (14e4:168e)  	 */ -	if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) || -	    (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e)) +	if ((pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && +	     pdn->device_id == 0x1657) || +	    (pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && +	     pdn->device_id == 0x168e))  		edev->pe->state |= EEH_PE_CFG_RESTRICTED;  	/* @@ -380,7 +456,8 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag)  	 * to PE reset.  	 */  	if (!edev->pe->bus) -		edev->pe->bus = dev->bus; +		edev->pe->bus = pci_find_bus(hose->global_number, +					     pdn->busno);  	/*  	 * Enable EEH explicitly so that we will do EEH check @@ -391,7 +468,7 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag)  	/* Save memory bars */  	eeh_save_bars(edev); -	return 0; +	return NULL;  }  /** @@ -1432,8 +1509,7 @@ static struct eeh_ops pnv_eeh_ops = {  	.name                   = "powernv",  	.init                   = pnv_eeh_init,  	.post_init              = pnv_eeh_post_init, -	.of_probe               = NULL, -	.dev_probe              = pnv_eeh_dev_probe, +	.probe			= pnv_eeh_probe,  	.set_option             = pnv_eeh_set_option,  	.get_pe_addr            = pnv_eeh_get_pe_addr,  	.get_state              = pnv_eeh_get_state, diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index a6c7e19f5eb3..a2946f72d5e7 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -118,9 +118,8 @@ static int pseries_eeh_init(void)  	return 0;  } -static int pseries_eeh_cap_start(struct device_node *dn) +static int pseries_eeh_cap_start(struct pci_dn *pdn)  { -	struct pci_dn *pdn = PCI_DN(dn);  	u32 status;  	if (!pdn) @@ -134,10 +133,9 @@ static int pseries_eeh_cap_start(struct device_node *dn)  } -static int pseries_eeh_find_cap(struct device_node *dn, int cap) +static int pseries_eeh_find_cap(struct pci_dn *pdn, int cap)  { -	struct pci_dn *pdn = PCI_DN(dn); -	int pos = pseries_eeh_cap_start(dn); +	int pos = pseries_eeh_cap_start(pdn);  	int cnt = 48;	/* Maximal number of capabilities */  	u32 id; @@ -160,10 +158,9 @@ static int pseries_eeh_find_cap(struct device_node *dn, int cap)  	return 0;  } -static int pseries_eeh_find_ecap(struct device_node *dn, int cap) +static int pseries_eeh_find_ecap(struct pci_dn *pdn, int cap)  { -	struct pci_dn *pdn = PCI_DN(dn); -	struct eeh_dev *edev = of_node_to_eeh_dev(dn); +	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);  	u32 header;  	int pos = 256;  	int ttl = (4096 - 256) / 8; @@ -191,53 +188,44 @@ static int pseries_eeh_find_ecap(struct device_node *dn, int cap)  }  /** - * pseries_eeh_of_probe - EEH probe on the given device - * @dn: OF node - * @flag: Unused + * pseries_eeh_probe - EEH probe on the given device + * @pdn: PCI device node + * @data: Unused   *   * When EEH module is installed during system boot, all PCI devices   * are checked one by one to see if it supports EEH. The function   * is introduced for the purpose.   */ -static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) +static void *pseries_eeh_probe(struct pci_dn *pdn, void *data)  {  	struct eeh_dev *edev;  	struct eeh_pe pe; -	struct pci_dn *pdn = PCI_DN(dn); -	const __be32 *classp, *vendorp, *devicep; -	u32 class_code; -	const __be32 *regs;  	u32 pcie_flags;  	int enable = 0;  	int ret;  	/* Retrieve OF node and eeh device */ -	edev = of_node_to_eeh_dev(dn); -	if (edev->pe || !of_device_is_available(dn)) +	edev = pdn_to_eeh_dev(pdn); +	if (!edev || edev->pe)  		return NULL; -	/* Retrieve class/vendor/device IDs */ -	classp = of_get_property(dn, "class-code", NULL); -	vendorp = of_get_property(dn, "vendor-id", NULL); -	devicep = of_get_property(dn, "device-id", NULL); - -	/* Skip for bad OF node or PCI-ISA bridge */ -	if (!classp || !vendorp || !devicep) -		return NULL; -	if (dn->type && !strcmp(dn->type, "isa")) +	/* Check class/vendor/device IDs */ +	if (!pdn->vendor_id || !pdn->device_id || !pdn->class_code)  		return NULL; -	class_code = of_read_number(classp, 1); +	/* Skip for PCI-ISA bridge */ +        if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) +		return NULL;  	/*  	 * Update class code and mode of eeh device. We need  	 * correctly reflects that current device is root port  	 * or PCIe switch downstream port.  	 */ -	edev->class_code = class_code; -	edev->pcix_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_PCIX); -	edev->pcie_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_EXP); -	edev->aer_cap = pseries_eeh_find_ecap(dn, PCI_EXT_CAP_ID_ERR); +	edev->class_code = pdn->class_code; +	edev->pcix_cap = pseries_eeh_find_cap(pdn, PCI_CAP_ID_PCIX); +	edev->pcie_cap = pseries_eeh_find_cap(pdn, PCI_CAP_ID_EXP); +	edev->aer_cap = pseries_eeh_find_ecap(pdn, PCI_EXT_CAP_ID_ERR);  	edev->mode &= 0xFFFFFF00;  	if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) {  		edev->mode |= EEH_DEV_BRIDGE; @@ -252,24 +240,16 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)  		}  	} -	/* Retrieve the device address */ -	regs = of_get_property(dn, "reg", NULL); -	if (!regs) { -		pr_warn("%s: OF node property %s::reg not found\n", -			__func__, dn->full_name); -		return NULL; -	} -  	/* Initialize the fake PE */  	memset(&pe, 0, sizeof(struct eeh_pe));  	pe.phb = edev->phb; -	pe.config_addr = of_read_number(regs, 1); +	pe.config_addr = (pdn->busno << 16) | (pdn->devfn << 8);  	/* Enable EEH on the device */  	ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE);  	if (!ret) { -		edev->config_addr = of_read_number(regs, 1);  		/* Retrieve PE address */ +		edev->config_addr = (pdn->busno << 16) | (pdn->devfn << 8);  		edev->pe_config_addr = eeh_ops->get_pe_addr(&pe);  		pe.addr = edev->pe_config_addr; @@ -285,16 +265,17 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)  			eeh_add_flag(EEH_ENABLED);  			eeh_add_to_parent_pe(edev); -			pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", -				__func__, dn->full_name, pe.phb->global_number, -				pe.addr, pe.config_addr); -		} else if (dn->parent && of_node_to_eeh_dev(dn->parent) && -			   (of_node_to_eeh_dev(dn->parent))->pe) { +			pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%d-PE#%x\n", +				__func__, pdn->busno, PCI_SLOT(pdn->devfn), +				PCI_FUNC(pdn->devfn), pe.phb->global_number, +				pe.addr); +		} else if (pdn->parent && pdn_to_eeh_dev(pdn->parent) && +			   (pdn_to_eeh_dev(pdn->parent))->pe) {  			/* This device doesn't support EEH, but it may have an  			 * EEH parent, in which case we mark it as supported.  			 */ -			edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr; -			edev->pe_config_addr = of_node_to_eeh_dev(dn->parent)->pe_config_addr; +			edev->config_addr = pdn_to_eeh_dev(pdn->parent)->config_addr; +			edev->pe_config_addr = pdn_to_eeh_dev(pdn->parent)->pe_config_addr;  			eeh_add_to_parent_pe(edev);  		}  	} @@ -707,8 +688,7 @@ static int pseries_eeh_write_config(struct device_node *dn, int where, int size,  static struct eeh_ops pseries_eeh_ops = {  	.name			= "pseries",  	.init			= pseries_eeh_init, -	.of_probe		= pseries_eeh_of_probe, -	.dev_probe		= NULL, +	.probe			= pseries_eeh_probe,  	.set_option		= pseries_eeh_set_option,  	.get_pe_addr		= pseries_eeh_get_pe_addr,  	.get_state		= pseries_eeh_get_state, diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 89e23811199c..f735f4fee48c 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -82,7 +82,7 @@ struct pci_controller *init_phb_dynamic(struct device_node *dn)  	eeh_dev_phb_init_dynamic(phb);  	if (dn->child) -		eeh_add_device_tree_early(dn); +		eeh_add_device_tree_early(PCI_DN(dn));  	pcibios_scan_phb(phb);  	pcibios_finish_adding_to_bus(phb->bus); | 
