diff options
author | Gavin Shan <gwshan@linux.vnet.ibm.com> | 2015-03-17 01:15:06 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2015-03-23 22:15:52 -0400 |
commit | ff57b454ddb938d98d48d8df356357000fedc88c (patch) | |
tree | afb1399b36a933d563ee171fd529e6cf526031a5 | |
parent | e8e9b34cef237d4d6fdc0d350cd8a95d1adb9ee9 (diff) |
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>
-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 | ||||
-rw-r--r-- | drivers/pci/hotplug/rpadlpar_core.c | 2 |
8 files changed, 172 insertions, 138 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 { | |||
207 | char *name; | 207 | char *name; |
208 | int (*init)(void); | 208 | int (*init)(void); |
209 | int (*post_init)(void); | 209 | int (*post_init)(void); |
210 | void* (*of_probe)(struct device_node *dn, void *flag); | 210 | void* (*probe)(struct pci_dn *pdn, void *data); |
211 | int (*dev_probe)(struct pci_dev *dev, void *flag); | ||
212 | int (*set_option)(struct eeh_pe *pe, int option); | 211 | int (*set_option)(struct eeh_pe *pe, int option); |
213 | int (*get_pe_addr)(struct eeh_pe *pe); | 212 | int (*get_pe_addr)(struct eeh_pe *pe); |
214 | int (*get_state)(struct eeh_pe *pe, int *state); | 213 | int (*get_state)(struct eeh_pe *pe, int *state); |
@@ -287,8 +286,8 @@ int __exit eeh_ops_unregister(const char *name); | |||
287 | int eeh_check_failure(const volatile void __iomem *token); | 286 | int eeh_check_failure(const volatile void __iomem *token); |
288 | int eeh_dev_check_failure(struct eeh_dev *edev); | 287 | int eeh_dev_check_failure(struct eeh_dev *edev); |
289 | void eeh_addr_cache_build(void); | 288 | void eeh_addr_cache_build(void); |
290 | void eeh_add_device_early(struct device_node *); | 289 | void eeh_add_device_early(struct pci_dn *); |
291 | void eeh_add_device_tree_early(struct device_node *); | 290 | void eeh_add_device_tree_early(struct pci_dn *); |
292 | void eeh_add_device_late(struct pci_dev *); | 291 | void eeh_add_device_late(struct pci_dev *); |
293 | void eeh_add_device_tree_late(struct pci_bus *); | 292 | void eeh_add_device_tree_late(struct pci_bus *); |
294 | void eeh_add_sysfs_files(struct pci_bus *); | 293 | void eeh_add_sysfs_files(struct pci_bus *); |
@@ -346,9 +345,9 @@ static inline int eeh_check_failure(const volatile void __iomem *token) | |||
346 | 345 | ||
347 | static inline void eeh_addr_cache_build(void) { } | 346 | static inline void eeh_addr_cache_build(void) { } |
348 | 347 | ||
349 | static inline void eeh_add_device_early(struct device_node *dn) { } | 348 | static inline void eeh_add_device_early(struct pci_dn *pdn) { } |
350 | 349 | ||
351 | static inline void eeh_add_device_tree_early(struct device_node *dn) { } | 350 | static inline void eeh_add_device_tree_early(struct pci_dn *pdn) { } |
352 | 351 | ||
353 | static inline void eeh_add_device_late(struct pci_dev *dev) { } | 352 | static inline void eeh_add_device_late(struct pci_dev *dev) { } |
354 | 353 | ||
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 = { | |||
969 | int eeh_init(void) | 969 | int eeh_init(void) |
970 | { | 970 | { |
971 | struct pci_controller *hose, *tmp; | 971 | struct pci_controller *hose, *tmp; |
972 | struct device_node *phb; | 972 | struct pci_dn *pdn; |
973 | static int cnt = 0; | 973 | static int cnt = 0; |
974 | int ret = 0; | 974 | int ret = 0; |
975 | 975 | ||
@@ -1004,20 +1004,9 @@ int eeh_init(void) | |||
1004 | return ret; | 1004 | return ret; |
1005 | 1005 | ||
1006 | /* Enable EEH for all adapters */ | 1006 | /* Enable EEH for all adapters */ |
1007 | if (eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) { | 1007 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
1008 | list_for_each_entry_safe(hose, tmp, | 1008 | pdn = hose->pci_data; |
1009 | &hose_list, list_node) { | 1009 | traverse_pci_dn(pdn, eeh_ops->probe, NULL); |
1010 | phb = hose->dn; | ||
1011 | traverse_pci_devices(phb, eeh_ops->of_probe, NULL); | ||
1012 | } | ||
1013 | } else if (eeh_has_flag(EEH_PROBE_MODE_DEV)) { | ||
1014 | list_for_each_entry_safe(hose, tmp, | ||
1015 | &hose_list, list_node) | ||
1016 | pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL); | ||
1017 | } else { | ||
1018 | pr_warn("%s: Invalid probe mode %x", | ||
1019 | __func__, eeh_subsystem_flags); | ||
1020 | return -EINVAL; | ||
1021 | } | 1010 | } |
1022 | 1011 | ||
1023 | /* | 1012 | /* |
@@ -1043,7 +1032,7 @@ core_initcall_sync(eeh_init); | |||
1043 | 1032 | ||
1044 | /** | 1033 | /** |
1045 | * eeh_add_device_early - Enable EEH for the indicated device_node | 1034 | * eeh_add_device_early - Enable EEH for the indicated device_node |
1046 | * @dn: device node for which to set up EEH | 1035 | * @pdn: PCI device node for which to set up EEH |
1047 | * | 1036 | * |
1048 | * This routine must be used to perform EEH initialization for PCI | 1037 | * This routine must be used to perform EEH initialization for PCI |
1049 | * devices that were added after system boot (e.g. hotplug, dlpar). | 1038 | * devices that were added after system boot (e.g. hotplug, dlpar). |
@@ -1053,44 +1042,41 @@ core_initcall_sync(eeh_init); | |||
1053 | * on the CEC architecture, type of the device, on earlier boot | 1042 | * on the CEC architecture, type of the device, on earlier boot |
1054 | * command-line arguments & etc. | 1043 | * command-line arguments & etc. |
1055 | */ | 1044 | */ |
1056 | void eeh_add_device_early(struct device_node *dn) | 1045 | void eeh_add_device_early(struct pci_dn *pdn) |
1057 | { | 1046 | { |
1058 | struct pci_controller *phb; | 1047 | struct pci_controller *phb; |
1048 | struct eeh_dev *edev = pdn_to_eeh_dev(pdn); | ||
1059 | 1049 | ||
1060 | /* | 1050 | if (!edev) |
1061 | * If we're doing EEH probe based on PCI device, we | ||
1062 | * would delay the probe until late stage because | ||
1063 | * the PCI device isn't available this moment. | ||
1064 | */ | ||
1065 | if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) | ||
1066 | return; | ||
1067 | |||
1068 | if (!of_node_to_eeh_dev(dn)) | ||
1069 | return; | 1051 | return; |
1070 | phb = of_node_to_eeh_dev(dn)->phb; | ||
1071 | 1052 | ||
1072 | /* USB Bus children of PCI devices will not have BUID's */ | 1053 | /* USB Bus children of PCI devices will not have BUID's */ |
1073 | if (NULL == phb || 0 == phb->buid) | 1054 | phb = edev->phb; |
1055 | if (NULL == phb || | ||
1056 | (eeh_has_flag(EEH_PROBE_MODE_DEVTREE) && 0 == phb->buid)) | ||
1074 | return; | 1057 | return; |
1075 | 1058 | ||
1076 | eeh_ops->of_probe(dn, NULL); | 1059 | eeh_ops->probe(pdn, NULL); |
1077 | } | 1060 | } |
1078 | 1061 | ||
1079 | /** | 1062 | /** |
1080 | * eeh_add_device_tree_early - Enable EEH for the indicated device | 1063 | * eeh_add_device_tree_early - Enable EEH for the indicated device |
1081 | * @dn: device node | 1064 | * @pdn: PCI device node |
1082 | * | 1065 | * |
1083 | * This routine must be used to perform EEH initialization for the | 1066 | * This routine must be used to perform EEH initialization for the |
1084 | * indicated PCI device that was added after system boot (e.g. | 1067 | * indicated PCI device that was added after system boot (e.g. |
1085 | * hotplug, dlpar). | 1068 | * hotplug, dlpar). |
1086 | */ | 1069 | */ |
1087 | void eeh_add_device_tree_early(struct device_node *dn) | 1070 | void eeh_add_device_tree_early(struct pci_dn *pdn) |
1088 | { | 1071 | { |
1089 | struct device_node *sib; | 1072 | struct pci_dn *n; |
1073 | |||
1074 | if (!pdn) | ||
1075 | return; | ||
1090 | 1076 | ||
1091 | for_each_child_of_node(dn, sib) | 1077 | list_for_each_entry(n, &pdn->child_list, list) |
1092 | eeh_add_device_tree_early(sib); | 1078 | eeh_add_device_tree_early(n); |
1093 | eeh_add_device_early(dn); | 1079 | eeh_add_device_early(pdn); |
1094 | } | 1080 | } |
1095 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); | 1081 | EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); |
1096 | 1082 | ||
@@ -1144,13 +1130,6 @@ void eeh_add_device_late(struct pci_dev *dev) | |||
1144 | edev->pdev = dev; | 1130 | edev->pdev = dev; |
1145 | dev->dev.archdata.edev = edev; | 1131 | dev->dev.archdata.edev = edev; |
1146 | 1132 | ||
1147 | /* | ||
1148 | * We have to do the EEH probe here because the PCI device | ||
1149 | * hasn't been created yet in the early stage. | ||
1150 | */ | ||
1151 | if (eeh_has_flag(EEH_PROBE_MODE_DEV)) | ||
1152 | eeh_ops->dev_probe(dev, NULL); | ||
1153 | |||
1154 | eeh_addr_cache_insert_dev(dev); | 1133 | eeh_addr_cache_insert_dev(dev); |
1155 | } | 1134 | } |
1156 | 1135 | ||
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) | |||
72 | 72 | ||
73 | /* Register devices with EEH */ | 73 | /* Register devices with EEH */ |
74 | if (dev->dev.of_node->child) | 74 | if (dev->dev.of_node->child) |
75 | eeh_add_device_tree_early(dev->dev.of_node); | 75 | eeh_add_device_tree_early(PCI_DN(dev->dev.of_node)); |
76 | 76 | ||
77 | /* Scan the bus */ | 77 | /* Scan the bus */ |
78 | pcibios_scan_phb(phb); | 78 | 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) | |||
75 | struct pci_dev *dev; | 75 | struct pci_dev *dev; |
76 | struct device_node *dn = pci_bus_to_OF_node(bus); | 76 | struct device_node *dn = pci_bus_to_OF_node(bus); |
77 | 77 | ||
78 | eeh_add_device_tree_early(dn); | 78 | eeh_add_device_tree_early(PCI_DN(dn)); |
79 | 79 | ||
80 | mode = PCI_PROBE_NORMAL; | 80 | mode = PCI_PROBE_NORMAL; |
81 | if (ppc_md.pci_probe_mode) | 81 | 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) | |||
286 | return ret; | 286 | return ret; |
287 | } | 287 | } |
288 | 288 | ||
289 | static int pnv_eeh_cap_start(struct pci_dn *pdn) | ||
290 | { | ||
291 | u32 status; | ||
292 | |||
293 | if (!pdn) | ||
294 | return 0; | ||
295 | |||
296 | pnv_pci_cfg_read(pdn, PCI_STATUS, 2, &status); | ||
297 | if (!(status & PCI_STATUS_CAP_LIST)) | ||
298 | return 0; | ||
299 | |||
300 | return PCI_CAPABILITY_LIST; | ||
301 | } | ||
302 | |||
303 | static int pnv_eeh_find_cap(struct pci_dn *pdn, int cap) | ||
304 | { | ||
305 | int pos = pnv_eeh_cap_start(pdn); | ||
306 | int cnt = 48; /* Maximal number of capabilities */ | ||
307 | u32 id; | ||
308 | |||
309 | if (!pos) | ||
310 | return 0; | ||
311 | |||
312 | while (cnt--) { | ||
313 | pnv_pci_cfg_read(pdn, pos, 1, &pos); | ||
314 | if (pos < 0x40) | ||
315 | break; | ||
316 | |||
317 | pos &= ~3; | ||
318 | pnv_pci_cfg_read(pdn, pos + PCI_CAP_LIST_ID, 1, &id); | ||
319 | if (id == 0xff) | ||
320 | break; | ||
321 | |||
322 | /* Found */ | ||
323 | if (id == cap) | ||
324 | return pos; | ||
325 | |||
326 | /* Next one */ | ||
327 | pos += PCI_CAP_LIST_NEXT; | ||
328 | } | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int pnv_eeh_find_ecap(struct pci_dn *pdn, int cap) | ||
334 | { | ||
335 | struct eeh_dev *edev = pdn_to_eeh_dev(pdn); | ||
336 | u32 header; | ||
337 | int pos = 256, ttl = (4096 - 256) / 8; | ||
338 | |||
339 | if (!edev || !edev->pcie_cap) | ||
340 | return 0; | ||
341 | if (pnv_pci_cfg_read(pdn, pos, 4, &header) != PCIBIOS_SUCCESSFUL) | ||
342 | return 0; | ||
343 | else if (!header) | ||
344 | return 0; | ||
345 | |||
346 | while (ttl-- > 0) { | ||
347 | if (PCI_EXT_CAP_ID(header) == cap && pos) | ||
348 | return pos; | ||
349 | |||
350 | pos = PCI_EXT_CAP_NEXT(header); | ||
351 | if (pos < 256) | ||
352 | break; | ||
353 | |||
354 | if (pnv_pci_cfg_read(pdn, pos, 4, &header) != PCIBIOS_SUCCESSFUL) | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
289 | /** | 361 | /** |
290 | * pnv_eeh_dev_probe - Do probe on PCI device | 362 | * pnv_eeh_probe - Do probe on PCI device |
291 | * @dev: PCI device | 363 | * @pdn: PCI device node |
292 | * @flag: unused | 364 | * @data: unused |
293 | * | 365 | * |
294 | * When EEH module is installed during system boot, all PCI devices | 366 | * When EEH module is installed during system boot, all PCI devices |
295 | * are checked one by one to see if it supports EEH. The function | 367 | * are checked one by one to see if it supports EEH. The function |
@@ -303,12 +375,12 @@ static int pnv_eeh_post_init(void) | |||
303 | * was possiblly triggered by EEH core, the binding between EEH device | 375 | * was possiblly triggered by EEH core, the binding between EEH device |
304 | * and the PCI device isn't built yet. | 376 | * and the PCI device isn't built yet. |
305 | */ | 377 | */ |
306 | static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) | 378 | static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) |
307 | { | 379 | { |
308 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | 380 | struct pci_controller *hose = pdn->phb; |
309 | struct pnv_phb *phb = hose->private_data; | 381 | struct pnv_phb *phb = hose->private_data; |
310 | struct device_node *dn = pci_device_to_OF_node(dev); | 382 | struct eeh_dev *edev = pdn_to_eeh_dev(pdn); |
311 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); | 383 | uint32_t pcie_flags; |
312 | int ret; | 384 | int ret; |
313 | 385 | ||
314 | /* | 386 | /* |
@@ -317,40 +389,42 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
317 | * the root bridge. So it's not reasonable to continue | 389 | * the root bridge. So it's not reasonable to continue |
318 | * the probing. | 390 | * the probing. |
319 | */ | 391 | */ |
320 | if (!dn || !edev || edev->pe) | 392 | if (!edev || edev->pe) |
321 | return 0; | 393 | return NULL; |
322 | 394 | ||
323 | /* Skip for PCI-ISA bridge */ | 395 | /* Skip for PCI-ISA bridge */ |
324 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_ISA) | 396 | if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) |
325 | return 0; | 397 | return NULL; |
326 | 398 | ||
327 | /* Initialize eeh device */ | 399 | /* Initialize eeh device */ |
328 | edev->class_code = dev->class; | 400 | edev->class_code = pdn->class_code; |
329 | edev->mode &= 0xFFFFFF00; | 401 | edev->mode &= 0xFFFFFF00; |
330 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | 402 | edev->pcix_cap = pnv_eeh_find_cap(pdn, PCI_CAP_ID_PCIX); |
403 | edev->pcie_cap = pnv_eeh_find_cap(pdn, PCI_CAP_ID_EXP); | ||
404 | edev->aer_cap = pnv_eeh_find_ecap(pdn, PCI_EXT_CAP_ID_ERR); | ||
405 | if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
331 | edev->mode |= EEH_DEV_BRIDGE; | 406 | edev->mode |= EEH_DEV_BRIDGE; |
332 | edev->pcix_cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 407 | if (edev->pcie_cap) { |
333 | if (pci_is_pcie(dev)) { | 408 | pnv_pci_cfg_read(pdn, edev->pcie_cap + PCI_EXP_FLAGS, |
334 | edev->pcie_cap = pci_pcie_cap(dev); | 409 | 2, &pcie_flags); |
335 | 410 | pcie_flags = (pcie_flags & PCI_EXP_FLAGS_TYPE) >> 4; | |
336 | if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) | 411 | if (pcie_flags == PCI_EXP_TYPE_ROOT_PORT) |
337 | edev->mode |= EEH_DEV_ROOT_PORT; | 412 | edev->mode |= EEH_DEV_ROOT_PORT; |
338 | else if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) | 413 | else if (pcie_flags == PCI_EXP_TYPE_DOWNSTREAM) |
339 | edev->mode |= EEH_DEV_DS_PORT; | 414 | edev->mode |= EEH_DEV_DS_PORT; |
340 | 415 | } | |
341 | edev->aer_cap = pci_find_ext_capability(dev, | ||
342 | PCI_EXT_CAP_ID_ERR); | ||
343 | } | 416 | } |
344 | 417 | ||
345 | edev->config_addr = ((dev->bus->number << 8) | dev->devfn); | 418 | edev->config_addr = (pdn->busno << 8) | (pdn->devfn); |
346 | edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); | 419 | edev->pe_config_addr = phb->ioda.pe_rmap[edev->config_addr]; |
347 | 420 | ||
348 | /* Create PE */ | 421 | /* Create PE */ |
349 | ret = eeh_add_to_parent_pe(edev); | 422 | ret = eeh_add_to_parent_pe(edev); |
350 | if (ret) { | 423 | if (ret) { |
351 | pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n", | 424 | pr_warn("%s: Can't add PCI dev %04x:%02x:%02x.%01x to parent PE (%d)\n", |
352 | __func__, pci_name(dev), ret); | 425 | __func__, hose->global_number, pdn->busno, |
353 | return ret; | 426 | PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn), ret); |
427 | return NULL; | ||
354 | } | 428 | } |
355 | 429 | ||
356 | /* | 430 | /* |
@@ -369,8 +443,10 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
369 | * Broadcom Austin 4-ports NICs (14e4:1657) | 443 | * Broadcom Austin 4-ports NICs (14e4:1657) |
370 | * Broadcom Shiner 2-ports 10G NICs (14e4:168e) | 444 | * Broadcom Shiner 2-ports 10G NICs (14e4:168e) |
371 | */ | 445 | */ |
372 | if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) || | 446 | if ((pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && |
373 | (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e)) | 447 | pdn->device_id == 0x1657) || |
448 | (pdn->vendor_id == PCI_VENDOR_ID_BROADCOM && | ||
449 | pdn->device_id == 0x168e)) | ||
374 | edev->pe->state |= EEH_PE_CFG_RESTRICTED; | 450 | edev->pe->state |= EEH_PE_CFG_RESTRICTED; |
375 | 451 | ||
376 | /* | 452 | /* |
@@ -380,7 +456,8 @@ static int pnv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
380 | * to PE reset. | 456 | * to PE reset. |
381 | */ | 457 | */ |
382 | if (!edev->pe->bus) | 458 | if (!edev->pe->bus) |
383 | edev->pe->bus = dev->bus; | 459 | edev->pe->bus = pci_find_bus(hose->global_number, |
460 | pdn->busno); | ||
384 | 461 | ||
385 | /* | 462 | /* |
386 | * Enable EEH explicitly so that we will do EEH check | 463 | * 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) | |||
391 | /* Save memory bars */ | 468 | /* Save memory bars */ |
392 | eeh_save_bars(edev); | 469 | eeh_save_bars(edev); |
393 | 470 | ||
394 | return 0; | 471 | return NULL; |
395 | } | 472 | } |
396 | 473 | ||
397 | /** | 474 | /** |
@@ -1432,8 +1509,7 @@ static struct eeh_ops pnv_eeh_ops = { | |||
1432 | .name = "powernv", | 1509 | .name = "powernv", |
1433 | .init = pnv_eeh_init, | 1510 | .init = pnv_eeh_init, |
1434 | .post_init = pnv_eeh_post_init, | 1511 | .post_init = pnv_eeh_post_init, |
1435 | .of_probe = NULL, | 1512 | .probe = pnv_eeh_probe, |
1436 | .dev_probe = pnv_eeh_dev_probe, | ||
1437 | .set_option = pnv_eeh_set_option, | 1513 | .set_option = pnv_eeh_set_option, |
1438 | .get_pe_addr = pnv_eeh_get_pe_addr, | 1514 | .get_pe_addr = pnv_eeh_get_pe_addr, |
1439 | .get_state = pnv_eeh_get_state, | 1515 | .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) | |||
118 | return 0; | 118 | return 0; |
119 | } | 119 | } |
120 | 120 | ||
121 | static int pseries_eeh_cap_start(struct device_node *dn) | 121 | static int pseries_eeh_cap_start(struct pci_dn *pdn) |
122 | { | 122 | { |
123 | struct pci_dn *pdn = PCI_DN(dn); | ||
124 | u32 status; | 123 | u32 status; |
125 | 124 | ||
126 | if (!pdn) | 125 | if (!pdn) |
@@ -134,10 +133,9 @@ static int pseries_eeh_cap_start(struct device_node *dn) | |||
134 | } | 133 | } |
135 | 134 | ||
136 | 135 | ||
137 | static int pseries_eeh_find_cap(struct device_node *dn, int cap) | 136 | static int pseries_eeh_find_cap(struct pci_dn *pdn, int cap) |
138 | { | 137 | { |
139 | struct pci_dn *pdn = PCI_DN(dn); | 138 | int pos = pseries_eeh_cap_start(pdn); |
140 | int pos = pseries_eeh_cap_start(dn); | ||
141 | int cnt = 48; /* Maximal number of capabilities */ | 139 | int cnt = 48; /* Maximal number of capabilities */ |
142 | u32 id; | 140 | u32 id; |
143 | 141 | ||
@@ -160,10 +158,9 @@ static int pseries_eeh_find_cap(struct device_node *dn, int cap) | |||
160 | return 0; | 158 | return 0; |
161 | } | 159 | } |
162 | 160 | ||
163 | static int pseries_eeh_find_ecap(struct device_node *dn, int cap) | 161 | static int pseries_eeh_find_ecap(struct pci_dn *pdn, int cap) |
164 | { | 162 | { |
165 | struct pci_dn *pdn = PCI_DN(dn); | 163 | struct eeh_dev *edev = pdn_to_eeh_dev(pdn); |
166 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); | ||
167 | u32 header; | 164 | u32 header; |
168 | int pos = 256; | 165 | int pos = 256; |
169 | int ttl = (4096 - 256) / 8; | 166 | int ttl = (4096 - 256) / 8; |
@@ -191,53 +188,44 @@ static int pseries_eeh_find_ecap(struct device_node *dn, int cap) | |||
191 | } | 188 | } |
192 | 189 | ||
193 | /** | 190 | /** |
194 | * pseries_eeh_of_probe - EEH probe on the given device | 191 | * pseries_eeh_probe - EEH probe on the given device |
195 | * @dn: OF node | 192 | * @pdn: PCI device node |
196 | * @flag: Unused | 193 | * @data: Unused |
197 | * | 194 | * |
198 | * When EEH module is installed during system boot, all PCI devices | 195 | * When EEH module is installed during system boot, all PCI devices |
199 | * are checked one by one to see if it supports EEH. The function | 196 | * are checked one by one to see if it supports EEH. The function |
200 | * is introduced for the purpose. | 197 | * is introduced for the purpose. |
201 | */ | 198 | */ |
202 | static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | 199 | static void *pseries_eeh_probe(struct pci_dn *pdn, void *data) |
203 | { | 200 | { |
204 | struct eeh_dev *edev; | 201 | struct eeh_dev *edev; |
205 | struct eeh_pe pe; | 202 | struct eeh_pe pe; |
206 | struct pci_dn *pdn = PCI_DN(dn); | ||
207 | const __be32 *classp, *vendorp, *devicep; | ||
208 | u32 class_code; | ||
209 | const __be32 *regs; | ||
210 | u32 pcie_flags; | 203 | u32 pcie_flags; |
211 | int enable = 0; | 204 | int enable = 0; |
212 | int ret; | 205 | int ret; |
213 | 206 | ||
214 | /* Retrieve OF node and eeh device */ | 207 | /* Retrieve OF node and eeh device */ |
215 | edev = of_node_to_eeh_dev(dn); | 208 | edev = pdn_to_eeh_dev(pdn); |
216 | if (edev->pe || !of_device_is_available(dn)) | 209 | if (!edev || edev->pe) |
217 | return NULL; | 210 | return NULL; |
218 | 211 | ||
219 | /* Retrieve class/vendor/device IDs */ | 212 | /* Check class/vendor/device IDs */ |
220 | classp = of_get_property(dn, "class-code", NULL); | 213 | if (!pdn->vendor_id || !pdn->device_id || !pdn->class_code) |
221 | vendorp = of_get_property(dn, "vendor-id", NULL); | ||
222 | devicep = of_get_property(dn, "device-id", NULL); | ||
223 | |||
224 | /* Skip for bad OF node or PCI-ISA bridge */ | ||
225 | if (!classp || !vendorp || !devicep) | ||
226 | return NULL; | ||
227 | if (dn->type && !strcmp(dn->type, "isa")) | ||
228 | return NULL; | 214 | return NULL; |
229 | 215 | ||
230 | class_code = of_read_number(classp, 1); | 216 | /* Skip for PCI-ISA bridge */ |
217 | if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) | ||
218 | return NULL; | ||
231 | 219 | ||
232 | /* | 220 | /* |
233 | * Update class code and mode of eeh device. We need | 221 | * Update class code and mode of eeh device. We need |
234 | * correctly reflects that current device is root port | 222 | * correctly reflects that current device is root port |
235 | * or PCIe switch downstream port. | 223 | * or PCIe switch downstream port. |
236 | */ | 224 | */ |
237 | edev->class_code = class_code; | 225 | edev->class_code = pdn->class_code; |
238 | edev->pcix_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_PCIX); | 226 | edev->pcix_cap = pseries_eeh_find_cap(pdn, PCI_CAP_ID_PCIX); |
239 | edev->pcie_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_EXP); | 227 | edev->pcie_cap = pseries_eeh_find_cap(pdn, PCI_CAP_ID_EXP); |
240 | edev->aer_cap = pseries_eeh_find_ecap(dn, PCI_EXT_CAP_ID_ERR); | 228 | edev->aer_cap = pseries_eeh_find_ecap(pdn, PCI_EXT_CAP_ID_ERR); |
241 | edev->mode &= 0xFFFFFF00; | 229 | edev->mode &= 0xFFFFFF00; |
242 | if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { | 230 | if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { |
243 | edev->mode |= EEH_DEV_BRIDGE; | 231 | edev->mode |= EEH_DEV_BRIDGE; |
@@ -252,24 +240,16 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
252 | } | 240 | } |
253 | } | 241 | } |
254 | 242 | ||
255 | /* Retrieve the device address */ | ||
256 | regs = of_get_property(dn, "reg", NULL); | ||
257 | if (!regs) { | ||
258 | pr_warn("%s: OF node property %s::reg not found\n", | ||
259 | __func__, dn->full_name); | ||
260 | return NULL; | ||
261 | } | ||
262 | |||
263 | /* Initialize the fake PE */ | 243 | /* Initialize the fake PE */ |
264 | memset(&pe, 0, sizeof(struct eeh_pe)); | 244 | memset(&pe, 0, sizeof(struct eeh_pe)); |
265 | pe.phb = edev->phb; | 245 | pe.phb = edev->phb; |
266 | pe.config_addr = of_read_number(regs, 1); | 246 | pe.config_addr = (pdn->busno << 16) | (pdn->devfn << 8); |
267 | 247 | ||
268 | /* Enable EEH on the device */ | 248 | /* Enable EEH on the device */ |
269 | ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE); | 249 | ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE); |
270 | if (!ret) { | 250 | if (!ret) { |
271 | edev->config_addr = of_read_number(regs, 1); | ||
272 | /* Retrieve PE address */ | 251 | /* Retrieve PE address */ |
252 | edev->config_addr = (pdn->busno << 16) | (pdn->devfn << 8); | ||
273 | edev->pe_config_addr = eeh_ops->get_pe_addr(&pe); | 253 | edev->pe_config_addr = eeh_ops->get_pe_addr(&pe); |
274 | pe.addr = edev->pe_config_addr; | 254 | pe.addr = edev->pe_config_addr; |
275 | 255 | ||
@@ -285,16 +265,17 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
285 | eeh_add_flag(EEH_ENABLED); | 265 | eeh_add_flag(EEH_ENABLED); |
286 | eeh_add_to_parent_pe(edev); | 266 | eeh_add_to_parent_pe(edev); |
287 | 267 | ||
288 | pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", | 268 | pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%d-PE#%x\n", |
289 | __func__, dn->full_name, pe.phb->global_number, | 269 | __func__, pdn->busno, PCI_SLOT(pdn->devfn), |
290 | pe.addr, pe.config_addr); | 270 | PCI_FUNC(pdn->devfn), pe.phb->global_number, |
291 | } else if (dn->parent && of_node_to_eeh_dev(dn->parent) && | 271 | pe.addr); |
292 | (of_node_to_eeh_dev(dn->parent))->pe) { | 272 | } else if (pdn->parent && pdn_to_eeh_dev(pdn->parent) && |
273 | (pdn_to_eeh_dev(pdn->parent))->pe) { | ||
293 | /* This device doesn't support EEH, but it may have an | 274 | /* This device doesn't support EEH, but it may have an |
294 | * EEH parent, in which case we mark it as supported. | 275 | * EEH parent, in which case we mark it as supported. |
295 | */ | 276 | */ |
296 | edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr; | 277 | edev->config_addr = pdn_to_eeh_dev(pdn->parent)->config_addr; |
297 | edev->pe_config_addr = of_node_to_eeh_dev(dn->parent)->pe_config_addr; | 278 | edev->pe_config_addr = pdn_to_eeh_dev(pdn->parent)->pe_config_addr; |
298 | eeh_add_to_parent_pe(edev); | 279 | eeh_add_to_parent_pe(edev); |
299 | } | 280 | } |
300 | } | 281 | } |
@@ -707,8 +688,7 @@ static int pseries_eeh_write_config(struct device_node *dn, int where, int size, | |||
707 | static struct eeh_ops pseries_eeh_ops = { | 688 | static struct eeh_ops pseries_eeh_ops = { |
708 | .name = "pseries", | 689 | .name = "pseries", |
709 | .init = pseries_eeh_init, | 690 | .init = pseries_eeh_init, |
710 | .of_probe = pseries_eeh_of_probe, | 691 | .probe = pseries_eeh_probe, |
711 | .dev_probe = NULL, | ||
712 | .set_option = pseries_eeh_set_option, | 692 | .set_option = pseries_eeh_set_option, |
713 | .get_pe_addr = pseries_eeh_get_pe_addr, | 693 | .get_pe_addr = pseries_eeh_get_pe_addr, |
714 | .get_state = pseries_eeh_get_state, | 694 | .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) | |||
82 | eeh_dev_phb_init_dynamic(phb); | 82 | eeh_dev_phb_init_dynamic(phb); |
83 | 83 | ||
84 | if (dn->child) | 84 | if (dn->child) |
85 | eeh_add_device_tree_early(dn); | 85 | eeh_add_device_tree_early(PCI_DN(dn)); |
86 | 86 | ||
87 | pcibios_scan_phb(phb); | 87 | pcibios_scan_phb(phb); |
88 | pcibios_finish_adding_to_bus(phb->bus); | 88 | pcibios_finish_adding_to_bus(phb->bus); |
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 7660232ef460..e12bafdc42e0 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
@@ -146,7 +146,7 @@ static void dlpar_pci_add_bus(struct device_node *dn) | |||
146 | struct pci_controller *phb = pdn->phb; | 146 | struct pci_controller *phb = pdn->phb; |
147 | struct pci_dev *dev = NULL; | 147 | struct pci_dev *dev = NULL; |
148 | 148 | ||
149 | eeh_add_device_tree_early(dn); | 149 | eeh_add_device_tree_early(pdn); |
150 | 150 | ||
151 | /* Add EADS device to PHB bus, adding new entry to bus->devices */ | 151 | /* Add EADS device to PHB bus, adding new entry to bus->devices */ |
152 | dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); | 152 | dev = of_create_pci_dev(dn, phb->bus, pdn->devfn); |