diff options
Diffstat (limited to 'arch/powerpc')
25 files changed, 390 insertions, 168 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 09a8743143f3..d3e5e9bc8f94 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
@@ -55,6 +55,8 @@ struct device_node; | |||
55 | #define EEH_PE_RECOVERING (1 << 1) /* Recovering PE */ | 55 | #define EEH_PE_RECOVERING (1 << 1) /* Recovering PE */ |
56 | #define EEH_PE_PHB_DEAD (1 << 2) /* Dead PHB */ | 56 | #define EEH_PE_PHB_DEAD (1 << 2) /* Dead PHB */ |
57 | 57 | ||
58 | #define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */ | ||
59 | |||
58 | struct eeh_pe { | 60 | struct eeh_pe { |
59 | int type; /* PE type: PHB/Bus/Device */ | 61 | int type; /* PE type: PHB/Bus/Device */ |
60 | int state; /* PE EEH dependent mode */ | 62 | int state; /* PE EEH dependent mode */ |
@@ -72,8 +74,8 @@ struct eeh_pe { | |||
72 | struct list_head child; /* Child PEs */ | 74 | struct list_head child; /* Child PEs */ |
73 | }; | 75 | }; |
74 | 76 | ||
75 | #define eeh_pe_for_each_dev(pe, edev) \ | 77 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ |
76 | list_for_each_entry(edev, &pe->edevs, list) | 78 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) |
77 | 79 | ||
78 | /* | 80 | /* |
79 | * The struct is used to trace EEH state for the associated | 81 | * The struct is used to trace EEH state for the associated |
@@ -82,7 +84,13 @@ struct eeh_pe { | |||
82 | * another tree except the currently existing tree of PCI | 84 | * another tree except the currently existing tree of PCI |
83 | * buses and PCI devices | 85 | * buses and PCI devices |
84 | */ | 86 | */ |
85 | #define EEH_DEV_IRQ_DISABLED (1<<0) /* Interrupt disabled */ | 87 | #define EEH_DEV_BRIDGE (1 << 0) /* PCI bridge */ |
88 | #define EEH_DEV_ROOT_PORT (1 << 1) /* PCIe root port */ | ||
89 | #define EEH_DEV_DS_PORT (1 << 2) /* Downstream port */ | ||
90 | #define EEH_DEV_IRQ_DISABLED (1 << 3) /* Interrupt disabled */ | ||
91 | #define EEH_DEV_DISCONNECTED (1 << 4) /* Removing from PE */ | ||
92 | |||
93 | #define EEH_DEV_SYSFS (1 << 8) /* Sysfs created */ | ||
86 | 94 | ||
87 | struct eeh_dev { | 95 | struct eeh_dev { |
88 | int mode; /* EEH mode */ | 96 | int mode; /* EEH mode */ |
@@ -90,11 +98,13 @@ struct eeh_dev { | |||
90 | int config_addr; /* Config address */ | 98 | int config_addr; /* Config address */ |
91 | int pe_config_addr; /* PE config address */ | 99 | int pe_config_addr; /* PE config address */ |
92 | u32 config_space[16]; /* Saved PCI config space */ | 100 | u32 config_space[16]; /* Saved PCI config space */ |
101 | u8 pcie_cap; /* Saved PCIe capability */ | ||
93 | struct eeh_pe *pe; /* Associated PE */ | 102 | struct eeh_pe *pe; /* Associated PE */ |
94 | struct list_head list; /* Form link list in the PE */ | 103 | struct list_head list; /* Form link list in the PE */ |
95 | struct pci_controller *phb; /* Associated PHB */ | 104 | struct pci_controller *phb; /* Associated PHB */ |
96 | struct device_node *dn; /* Associated device node */ | 105 | struct device_node *dn; /* Associated device node */ |
97 | struct pci_dev *pdev; /* Associated PCI device */ | 106 | struct pci_dev *pdev; /* Associated PCI device */ |
107 | struct pci_bus *bus; /* PCI bus for partial hotplug */ | ||
98 | }; | 108 | }; |
99 | 109 | ||
100 | static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) | 110 | static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) |
@@ -193,8 +203,10 @@ int eeh_phb_pe_create(struct pci_controller *phb); | |||
193 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); | 203 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); |
194 | struct eeh_pe *eeh_pe_get(struct eeh_dev *edev); | 204 | struct eeh_pe *eeh_pe_get(struct eeh_dev *edev); |
195 | int eeh_add_to_parent_pe(struct eeh_dev *edev); | 205 | int eeh_add_to_parent_pe(struct eeh_dev *edev); |
196 | int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe); | 206 | int eeh_rmv_from_parent_pe(struct eeh_dev *edev); |
197 | void eeh_pe_update_time_stamp(struct eeh_pe *pe); | 207 | void eeh_pe_update_time_stamp(struct eeh_pe *pe); |
208 | void *eeh_pe_traverse(struct eeh_pe *root, | ||
209 | eeh_traverse_func fn, void *flag); | ||
198 | void *eeh_pe_dev_traverse(struct eeh_pe *root, | 210 | void *eeh_pe_dev_traverse(struct eeh_pe *root, |
199 | eeh_traverse_func fn, void *flag); | 211 | eeh_traverse_func fn, void *flag); |
200 | void eeh_pe_restore_bars(struct eeh_pe *pe); | 212 | void eeh_pe_restore_bars(struct eeh_pe *pe); |
@@ -209,10 +221,12 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, | |||
209 | unsigned long val); | 221 | unsigned long val); |
210 | int eeh_dev_check_failure(struct eeh_dev *edev); | 222 | int eeh_dev_check_failure(struct eeh_dev *edev); |
211 | void eeh_addr_cache_build(void); | 223 | void eeh_addr_cache_build(void); |
224 | void eeh_add_device_early(struct device_node *); | ||
212 | void eeh_add_device_tree_early(struct device_node *); | 225 | void eeh_add_device_tree_early(struct device_node *); |
226 | void eeh_add_device_late(struct pci_dev *); | ||
213 | void eeh_add_device_tree_late(struct pci_bus *); | 227 | void eeh_add_device_tree_late(struct pci_bus *); |
214 | void eeh_add_sysfs_files(struct pci_bus *); | 228 | void eeh_add_sysfs_files(struct pci_bus *); |
215 | void eeh_remove_bus_device(struct pci_dev *, int); | 229 | void eeh_remove_device(struct pci_dev *); |
216 | 230 | ||
217 | /** | 231 | /** |
218 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. | 232 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. |
@@ -252,13 +266,17 @@ static inline unsigned long eeh_check_failure(const volatile void __iomem *token | |||
252 | 266 | ||
253 | static inline void eeh_addr_cache_build(void) { } | 267 | static inline void eeh_addr_cache_build(void) { } |
254 | 268 | ||
269 | static inline void eeh_add_device_early(struct device_node *dn) { } | ||
270 | |||
255 | static inline void eeh_add_device_tree_early(struct device_node *dn) { } | 271 | static inline void eeh_add_device_tree_early(struct device_node *dn) { } |
256 | 272 | ||
273 | static inline void eeh_add_device_late(struct pci_dev *dev) { } | ||
274 | |||
257 | static inline void eeh_add_device_tree_late(struct pci_bus *bus) { } | 275 | static inline void eeh_add_device_tree_late(struct pci_bus *bus) { } |
258 | 276 | ||
259 | static inline void eeh_add_sysfs_files(struct pci_bus *bus) { } | 277 | static inline void eeh_add_sysfs_files(struct pci_bus *bus) { } |
260 | 278 | ||
261 | static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { } | 279 | static inline void eeh_remove_device(struct pci_dev *dev) { } |
262 | 280 | ||
263 | #define EEH_POSSIBLE_ERROR(val, type) (0) | 281 | #define EEH_POSSIBLE_ERROR(val, type) (0) |
264 | #define EEH_IO_ERROR_VALUE(size) (-1UL) | 282 | #define EEH_IO_ERROR_VALUE(size) (-1UL) |
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index ba713f166fa5..10be1dd01c6b 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
@@ -96,10 +96,11 @@ static inline bool arch_irqs_disabled(void) | |||
96 | #endif | 96 | #endif |
97 | 97 | ||
98 | #define hard_irq_disable() do { \ | 98 | #define hard_irq_disable() do { \ |
99 | u8 _was_enabled = get_paca()->soft_enabled; \ | 99 | u8 _was_enabled; \ |
100 | __hard_irq_disable(); \ | 100 | __hard_irq_disable(); \ |
101 | get_paca()->soft_enabled = 0; \ | 101 | _was_enabled = local_paca->soft_enabled; \ |
102 | get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; \ | 102 | local_paca->soft_enabled = 0; \ |
103 | local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \ | ||
103 | if (_was_enabled) \ | 104 | if (_was_enabled) \ |
104 | trace_hardirqs_off(); \ | 105 | trace_hardirqs_off(); \ |
105 | } while(0) | 106 | } while(0) |
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index c1df590ec444..49fa55bfbac4 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h | |||
@@ -82,10 +82,9 @@ struct exception_table_entry; | |||
82 | void sort_ex_table(struct exception_table_entry *start, | 82 | void sort_ex_table(struct exception_table_entry *start, |
83 | struct exception_table_entry *finish); | 83 | struct exception_table_entry *finish); |
84 | 84 | ||
85 | #ifdef CONFIG_MODVERSIONS | 85 | #if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64) |
86 | #define ARCH_RELOCATES_KCRCTAB | 86 | #define ARCH_RELOCATES_KCRCTAB |
87 | 87 | #define reloc_start PHYSICAL_START | |
88 | extern const unsigned long reloc_start[]; | ||
89 | #endif | 88 | #endif |
90 | #endif /* __KERNEL__ */ | 89 | #endif /* __KERNEL__ */ |
91 | #endif /* _ASM_POWERPC_MODULE_H */ | 90 | #endif /* _ASM_POWERPC_MODULE_H */ |
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 2c1d8cb9b265..32d0d2018faf 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h | |||
@@ -209,7 +209,6 @@ static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) | |||
209 | extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn); | 209 | extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn); |
210 | 210 | ||
211 | /** Remove all of the PCI devices under this bus */ | 211 | /** Remove all of the PCI devices under this bus */ |
212 | extern void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe); | ||
213 | extern void pcibios_remove_pci_devices(struct pci_bus *bus); | 212 | extern void pcibios_remove_pci_devices(struct pci_bus *bus); |
214 | 213 | ||
215 | /** Discover new pci devices under this bus, and add them */ | 214 | /** Discover new pci devices under this bus, and add them */ |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 5d7d9c2a5473..a6840e4e24f7 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -1088,7 +1088,8 @@ | |||
1088 | #define PVR_970MP 0x0044 | 1088 | #define PVR_970MP 0x0044 |
1089 | #define PVR_970GX 0x0045 | 1089 | #define PVR_970GX 0x0045 |
1090 | #define PVR_POWER7p 0x004A | 1090 | #define PVR_POWER7p 0x004A |
1091 | #define PVR_POWER8 0x004B | 1091 | #define PVR_POWER8E 0x004B |
1092 | #define PVR_POWER8 0x004D | ||
1092 | #define PVR_BE 0x0070 | 1093 | #define PVR_BE 0x0070 |
1093 | #define PVR_PA6T 0x0090 | 1094 | #define PVR_PA6T 0x0090 |
1094 | 1095 | ||
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 2a45d0f04385..22973a74df73 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -494,9 +494,27 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
494 | .cpu_restore = __restore_cpu_power7, | 494 | .cpu_restore = __restore_cpu_power7, |
495 | .platform = "power7+", | 495 | .platform = "power7+", |
496 | }, | 496 | }, |
497 | { /* Power8 */ | 497 | { /* Power8E */ |
498 | .pvr_mask = 0xffff0000, | 498 | .pvr_mask = 0xffff0000, |
499 | .pvr_value = 0x004b0000, | 499 | .pvr_value = 0x004b0000, |
500 | .cpu_name = "POWER8E (raw)", | ||
501 | .cpu_features = CPU_FTRS_POWER8, | ||
502 | .cpu_user_features = COMMON_USER_POWER8, | ||
503 | .cpu_user_features2 = COMMON_USER2_POWER8, | ||
504 | .mmu_features = MMU_FTRS_POWER8, | ||
505 | .icache_bsize = 128, | ||
506 | .dcache_bsize = 128, | ||
507 | .num_pmcs = 6, | ||
508 | .pmc_type = PPC_PMC_IBM, | ||
509 | .oprofile_cpu_type = "ppc64/power8", | ||
510 | .oprofile_type = PPC_OPROFILE_INVALID, | ||
511 | .cpu_setup = __setup_cpu_power8, | ||
512 | .cpu_restore = __restore_cpu_power8, | ||
513 | .platform = "power8", | ||
514 | }, | ||
515 | { /* Power8 */ | ||
516 | .pvr_mask = 0xffff0000, | ||
517 | .pvr_value = 0x004d0000, | ||
500 | .cpu_name = "POWER8 (raw)", | 518 | .cpu_name = "POWER8 (raw)", |
501 | .cpu_features = CPU_FTRS_POWER8, | 519 | .cpu_features = CPU_FTRS_POWER8, |
502 | .cpu_user_features = COMMON_USER_POWER8, | 520 | .cpu_user_features = COMMON_USER_POWER8, |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 39954fe941b8..ea9414c8088d 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
@@ -231,7 +231,7 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
231 | void eeh_slot_error_detail(struct eeh_pe *pe, int severity) | 231 | void eeh_slot_error_detail(struct eeh_pe *pe, int severity) |
232 | { | 232 | { |
233 | size_t loglen = 0; | 233 | size_t loglen = 0; |
234 | struct eeh_dev *edev; | 234 | struct eeh_dev *edev, *tmp; |
235 | bool valid_cfg_log = true; | 235 | bool valid_cfg_log = true; |
236 | 236 | ||
237 | /* | 237 | /* |
@@ -251,7 +251,7 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity) | |||
251 | eeh_pe_restore_bars(pe); | 251 | eeh_pe_restore_bars(pe); |
252 | 252 | ||
253 | pci_regs_buf[0] = 0; | 253 | pci_regs_buf[0] = 0; |
254 | eeh_pe_for_each_dev(pe, edev) { | 254 | eeh_pe_for_each_dev(pe, edev, tmp) { |
255 | loglen += eeh_gather_pci_data(edev, pci_regs_buf + loglen, | 255 | loglen += eeh_gather_pci_data(edev, pci_regs_buf + loglen, |
256 | EEH_PCI_REGS_LOG_LEN - loglen); | 256 | EEH_PCI_REGS_LOG_LEN - loglen); |
257 | } | 257 | } |
@@ -499,8 +499,6 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon | |||
499 | } | 499 | } |
500 | 500 | ||
501 | eeh_dev_check_failure(edev); | 501 | eeh_dev_check_failure(edev); |
502 | |||
503 | pci_dev_put(eeh_dev_to_pci_dev(edev)); | ||
504 | return val; | 502 | return val; |
505 | } | 503 | } |
506 | 504 | ||
@@ -838,7 +836,7 @@ core_initcall_sync(eeh_init); | |||
838 | * on the CEC architecture, type of the device, on earlier boot | 836 | * on the CEC architecture, type of the device, on earlier boot |
839 | * command-line arguments & etc. | 837 | * command-line arguments & etc. |
840 | */ | 838 | */ |
841 | static void eeh_add_device_early(struct device_node *dn) | 839 | void eeh_add_device_early(struct device_node *dn) |
842 | { | 840 | { |
843 | struct pci_controller *phb; | 841 | struct pci_controller *phb; |
844 | 842 | ||
@@ -886,7 +884,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_early); | |||
886 | * This routine must be used to complete EEH initialization for PCI | 884 | * This routine must be used to complete EEH initialization for PCI |
887 | * devices that were added after system boot (e.g. hotplug, dlpar). | 885 | * devices that were added after system boot (e.g. hotplug, dlpar). |
888 | */ | 886 | */ |
889 | static void eeh_add_device_late(struct pci_dev *dev) | 887 | void eeh_add_device_late(struct pci_dev *dev) |
890 | { | 888 | { |
891 | struct device_node *dn; | 889 | struct device_node *dn; |
892 | struct eeh_dev *edev; | 890 | struct eeh_dev *edev; |
@@ -902,9 +900,23 @@ static void eeh_add_device_late(struct pci_dev *dev) | |||
902 | pr_debug("EEH: Already referenced !\n"); | 900 | pr_debug("EEH: Already referenced !\n"); |
903 | return; | 901 | return; |
904 | } | 902 | } |
905 | WARN_ON(edev->pdev); | ||
906 | 903 | ||
907 | pci_dev_get(dev); | 904 | /* |
905 | * The EEH cache might not be removed correctly because of | ||
906 | * unbalanced kref to the device during unplug time, which | ||
907 | * relies on pcibios_release_device(). So we have to remove | ||
908 | * that here explicitly. | ||
909 | */ | ||
910 | if (edev->pdev) { | ||
911 | eeh_rmv_from_parent_pe(edev); | ||
912 | eeh_addr_cache_rmv_dev(edev->pdev); | ||
913 | eeh_sysfs_remove_device(edev->pdev); | ||
914 | edev->mode &= ~EEH_DEV_SYSFS; | ||
915 | |||
916 | edev->pdev = NULL; | ||
917 | dev->dev.archdata.edev = NULL; | ||
918 | } | ||
919 | |||
908 | edev->pdev = dev; | 920 | edev->pdev = dev; |
909 | dev->dev.archdata.edev = edev; | 921 | dev->dev.archdata.edev = edev; |
910 | 922 | ||
@@ -967,7 +979,6 @@ EXPORT_SYMBOL_GPL(eeh_add_sysfs_files); | |||
967 | /** | 979 | /** |
968 | * eeh_remove_device - Undo EEH setup for the indicated pci device | 980 | * eeh_remove_device - Undo EEH setup for the indicated pci device |
969 | * @dev: pci device to be removed | 981 | * @dev: pci device to be removed |
970 | * @purge_pe: remove the PE or not | ||
971 | * | 982 | * |
972 | * This routine should be called when a device is removed from | 983 | * This routine should be called when a device is removed from |
973 | * a running system (e.g. by hotplug or dlpar). It unregisters | 984 | * a running system (e.g. by hotplug or dlpar). It unregisters |
@@ -975,7 +986,7 @@ EXPORT_SYMBOL_GPL(eeh_add_sysfs_files); | |||
975 | * this device will no longer be detected after this call; thus, | 986 | * this device will no longer be detected after this call; thus, |
976 | * i/o errors affecting this slot may leave this device unusable. | 987 | * i/o errors affecting this slot may leave this device unusable. |
977 | */ | 988 | */ |
978 | static void eeh_remove_device(struct pci_dev *dev, int purge_pe) | 989 | void eeh_remove_device(struct pci_dev *dev) |
979 | { | 990 | { |
980 | struct eeh_dev *edev; | 991 | struct eeh_dev *edev; |
981 | 992 | ||
@@ -986,42 +997,29 @@ static void eeh_remove_device(struct pci_dev *dev, int purge_pe) | |||
986 | /* Unregister the device with the EEH/PCI address search system */ | 997 | /* Unregister the device with the EEH/PCI address search system */ |
987 | pr_debug("EEH: Removing device %s\n", pci_name(dev)); | 998 | pr_debug("EEH: Removing device %s\n", pci_name(dev)); |
988 | 999 | ||
989 | if (!edev || !edev->pdev) { | 1000 | if (!edev || !edev->pdev || !edev->pe) { |
990 | pr_debug("EEH: Not referenced !\n"); | 1001 | pr_debug("EEH: Not referenced !\n"); |
991 | return; | 1002 | return; |
992 | } | 1003 | } |
1004 | |||
1005 | /* | ||
1006 | * During the hotplug for EEH error recovery, we need the EEH | ||
1007 | * device attached to the parent PE in order for BAR restore | ||
1008 | * a bit later. So we keep it for BAR restore and remove it | ||
1009 | * from the parent PE during the BAR resotre. | ||
1010 | */ | ||
993 | edev->pdev = NULL; | 1011 | edev->pdev = NULL; |
994 | dev->dev.archdata.edev = NULL; | 1012 | dev->dev.archdata.edev = NULL; |
995 | pci_dev_put(dev); | 1013 | if (!(edev->pe->state & EEH_PE_KEEP)) |
1014 | eeh_rmv_from_parent_pe(edev); | ||
1015 | else | ||
1016 | edev->mode |= EEH_DEV_DISCONNECTED; | ||
996 | 1017 | ||
997 | eeh_rmv_from_parent_pe(edev, purge_pe); | ||
998 | eeh_addr_cache_rmv_dev(dev); | 1018 | eeh_addr_cache_rmv_dev(dev); |
999 | eeh_sysfs_remove_device(dev); | 1019 | eeh_sysfs_remove_device(dev); |
1020 | edev->mode &= ~EEH_DEV_SYSFS; | ||
1000 | } | 1021 | } |
1001 | 1022 | ||
1002 | /** | ||
1003 | * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device | ||
1004 | * @dev: PCI device | ||
1005 | * @purge_pe: remove the corresponding PE or not | ||
1006 | * | ||
1007 | * This routine must be called when a device is removed from the | ||
1008 | * running system through hotplug or dlpar. The corresponding | ||
1009 | * PCI address cache will be removed. | ||
1010 | */ | ||
1011 | void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) | ||
1012 | { | ||
1013 | struct pci_bus *bus = dev->subordinate; | ||
1014 | struct pci_dev *child, *tmp; | ||
1015 | |||
1016 | eeh_remove_device(dev, purge_pe); | ||
1017 | |||
1018 | if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
1019 | list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) | ||
1020 | eeh_remove_bus_device(child, purge_pe); | ||
1021 | } | ||
1022 | } | ||
1023 | EXPORT_SYMBOL_GPL(eeh_remove_bus_device); | ||
1024 | |||
1025 | static int proc_eeh_show(struct seq_file *m, void *v) | 1023 | static int proc_eeh_show(struct seq_file *m, void *v) |
1026 | { | 1024 | { |
1027 | if (0 == eeh_subsystem_enabled) { | 1025 | if (0 == eeh_subsystem_enabled) { |
diff --git a/arch/powerpc/kernel/eeh_cache.c b/arch/powerpc/kernel/eeh_cache.c index f9ac1232a746..e8c9fd546a5c 100644 --- a/arch/powerpc/kernel/eeh_cache.c +++ b/arch/powerpc/kernel/eeh_cache.c | |||
@@ -68,16 +68,12 @@ static inline struct eeh_dev *__eeh_addr_cache_get_device(unsigned long addr) | |||
68 | struct pci_io_addr_range *piar; | 68 | struct pci_io_addr_range *piar; |
69 | piar = rb_entry(n, struct pci_io_addr_range, rb_node); | 69 | piar = rb_entry(n, struct pci_io_addr_range, rb_node); |
70 | 70 | ||
71 | if (addr < piar->addr_lo) { | 71 | if (addr < piar->addr_lo) |
72 | n = n->rb_left; | 72 | n = n->rb_left; |
73 | } else { | 73 | else if (addr > piar->addr_hi) |
74 | if (addr > piar->addr_hi) { | 74 | n = n->rb_right; |
75 | n = n->rb_right; | 75 | else |
76 | } else { | 76 | return piar->edev; |
77 | pci_dev_get(piar->pcidev); | ||
78 | return piar->edev; | ||
79 | } | ||
80 | } | ||
81 | } | 77 | } |
82 | 78 | ||
83 | return NULL; | 79 | return NULL; |
@@ -156,7 +152,6 @@ eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
156 | if (!piar) | 152 | if (!piar) |
157 | return NULL; | 153 | return NULL; |
158 | 154 | ||
159 | pci_dev_get(dev); | ||
160 | piar->addr_lo = alo; | 155 | piar->addr_lo = alo; |
161 | piar->addr_hi = ahi; | 156 | piar->addr_hi = ahi; |
162 | piar->edev = pci_dev_to_eeh_dev(dev); | 157 | piar->edev = pci_dev_to_eeh_dev(dev); |
@@ -250,7 +245,6 @@ restart: | |||
250 | 245 | ||
251 | if (piar->pcidev == dev) { | 246 | if (piar->pcidev == dev) { |
252 | rb_erase(n, &pci_io_addr_cache_root.rb_root); | 247 | rb_erase(n, &pci_io_addr_cache_root.rb_root); |
253 | pci_dev_put(piar->pcidev); | ||
254 | kfree(piar); | 248 | kfree(piar); |
255 | goto restart; | 249 | goto restart; |
256 | } | 250 | } |
@@ -302,12 +296,10 @@ void eeh_addr_cache_build(void) | |||
302 | if (!edev) | 296 | if (!edev) |
303 | continue; | 297 | continue; |
304 | 298 | ||
305 | pci_dev_get(dev); /* matching put is in eeh_remove_device() */ | ||
306 | dev->dev.archdata.edev = edev; | 299 | dev->dev.archdata.edev = edev; |
307 | edev->pdev = dev; | 300 | edev->pdev = dev; |
308 | 301 | ||
309 | eeh_addr_cache_insert_dev(dev); | 302 | eeh_addr_cache_insert_dev(dev); |
310 | |||
311 | eeh_sysfs_add_device(dev); | 303 | eeh_sysfs_add_device(dev); |
312 | } | 304 | } |
313 | 305 | ||
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 2b1ce17cae50..36bed5a12750 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
@@ -143,10 +143,14 @@ static void eeh_disable_irq(struct pci_dev *dev) | |||
143 | static void eeh_enable_irq(struct pci_dev *dev) | 143 | static void eeh_enable_irq(struct pci_dev *dev) |
144 | { | 144 | { |
145 | struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); | 145 | struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); |
146 | struct irq_desc *desc; | ||
146 | 147 | ||
147 | if ((edev->mode) & EEH_DEV_IRQ_DISABLED) { | 148 | if ((edev->mode) & EEH_DEV_IRQ_DISABLED) { |
148 | edev->mode &= ~EEH_DEV_IRQ_DISABLED; | 149 | edev->mode &= ~EEH_DEV_IRQ_DISABLED; |
149 | enable_irq(dev->irq); | 150 | |
151 | desc = irq_to_desc(dev->irq); | ||
152 | if (desc && desc->depth > 0) | ||
153 | enable_irq(dev->irq); | ||
150 | } | 154 | } |
151 | } | 155 | } |
152 | 156 | ||
@@ -338,6 +342,54 @@ static void *eeh_report_failure(void *data, void *userdata) | |||
338 | return NULL; | 342 | return NULL; |
339 | } | 343 | } |
340 | 344 | ||
345 | static void *eeh_rmv_device(void *data, void *userdata) | ||
346 | { | ||
347 | struct pci_driver *driver; | ||
348 | struct eeh_dev *edev = (struct eeh_dev *)data; | ||
349 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | ||
350 | int *removed = (int *)userdata; | ||
351 | |||
352 | /* | ||
353 | * Actually, we should remove the PCI bridges as well. | ||
354 | * However, that's lots of complexity to do that, | ||
355 | * particularly some of devices under the bridge might | ||
356 | * support EEH. So we just care about PCI devices for | ||
357 | * simplicity here. | ||
358 | */ | ||
359 | if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) | ||
360 | return NULL; | ||
361 | driver = eeh_pcid_get(dev); | ||
362 | if (driver && driver->err_handler) | ||
363 | return NULL; | ||
364 | |||
365 | /* Remove it from PCI subsystem */ | ||
366 | pr_debug("EEH: Removing %s without EEH sensitive driver\n", | ||
367 | pci_name(dev)); | ||
368 | edev->bus = dev->bus; | ||
369 | edev->mode |= EEH_DEV_DISCONNECTED; | ||
370 | (*removed)++; | ||
371 | |||
372 | pci_stop_and_remove_bus_device(dev); | ||
373 | |||
374 | return NULL; | ||
375 | } | ||
376 | |||
377 | static void *eeh_pe_detach_dev(void *data, void *userdata) | ||
378 | { | ||
379 | struct eeh_pe *pe = (struct eeh_pe *)data; | ||
380 | struct eeh_dev *edev, *tmp; | ||
381 | |||
382 | eeh_pe_for_each_dev(pe, edev, tmp) { | ||
383 | if (!(edev->mode & EEH_DEV_DISCONNECTED)) | ||
384 | continue; | ||
385 | |||
386 | edev->mode &= ~(EEH_DEV_DISCONNECTED | EEH_DEV_IRQ_DISABLED); | ||
387 | eeh_rmv_from_parent_pe(edev); | ||
388 | } | ||
389 | |||
390 | return NULL; | ||
391 | } | ||
392 | |||
341 | /** | 393 | /** |
342 | * eeh_reset_device - Perform actual reset of a pci slot | 394 | * eeh_reset_device - Perform actual reset of a pci slot |
343 | * @pe: EEH PE | 395 | * @pe: EEH PE |
@@ -349,8 +401,9 @@ static void *eeh_report_failure(void *data, void *userdata) | |||
349 | */ | 401 | */ |
350 | static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) | 402 | static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) |
351 | { | 403 | { |
404 | struct pci_bus *frozen_bus = eeh_pe_bus_get(pe); | ||
352 | struct timeval tstamp; | 405 | struct timeval tstamp; |
353 | int cnt, rc; | 406 | int cnt, rc, removed = 0; |
354 | 407 | ||
355 | /* pcibios will clear the counter; save the value */ | 408 | /* pcibios will clear the counter; save the value */ |
356 | cnt = pe->freeze_count; | 409 | cnt = pe->freeze_count; |
@@ -362,8 +415,11 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) | |||
362 | * devices are expected to be attached soon when calling | 415 | * devices are expected to be attached soon when calling |
363 | * into pcibios_add_pci_devices(). | 416 | * into pcibios_add_pci_devices(). |
364 | */ | 417 | */ |
418 | eeh_pe_state_mark(pe, EEH_PE_KEEP); | ||
365 | if (bus) | 419 | if (bus) |
366 | __pcibios_remove_pci_devices(bus, 0); | 420 | pcibios_remove_pci_devices(bus); |
421 | else if (frozen_bus) | ||
422 | eeh_pe_dev_traverse(pe, eeh_rmv_device, &removed); | ||
367 | 423 | ||
368 | /* Reset the pci controller. (Asserts RST#; resets config space). | 424 | /* Reset the pci controller. (Asserts RST#; resets config space). |
369 | * Reconfigure bridges and devices. Don't try to bring the system | 425 | * Reconfigure bridges and devices. Don't try to bring the system |
@@ -384,9 +440,24 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus) | |||
384 | * potentially weird things happen. | 440 | * potentially weird things happen. |
385 | */ | 441 | */ |
386 | if (bus) { | 442 | if (bus) { |
443 | pr_info("EEH: Sleep 5s ahead of complete hotplug\n"); | ||
387 | ssleep(5); | 444 | ssleep(5); |
445 | |||
446 | /* | ||
447 | * The EEH device is still connected with its parent | ||
448 | * PE. We should disconnect it so the binding can be | ||
449 | * rebuilt when adding PCI devices. | ||
450 | */ | ||
451 | eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL); | ||
388 | pcibios_add_pci_devices(bus); | 452 | pcibios_add_pci_devices(bus); |
453 | } else if (frozen_bus && removed) { | ||
454 | pr_info("EEH: Sleep 5s ahead of partial hotplug\n"); | ||
455 | ssleep(5); | ||
456 | |||
457 | eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL); | ||
458 | pcibios_add_pci_devices(frozen_bus); | ||
389 | } | 459 | } |
460 | eeh_pe_state_clear(pe, EEH_PE_KEEP); | ||
390 | 461 | ||
391 | pe->tstamp = tstamp; | 462 | pe->tstamp = tstamp; |
392 | pe->freeze_count = cnt; | 463 | pe->freeze_count = cnt; |
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 016588a6f5ed..f9450537e335 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c | |||
@@ -149,8 +149,8 @@ static struct eeh_pe *eeh_pe_next(struct eeh_pe *pe, | |||
149 | * callback returns something other than NULL, or no more PEs | 149 | * callback returns something other than NULL, or no more PEs |
150 | * to be traversed. | 150 | * to be traversed. |
151 | */ | 151 | */ |
152 | static void *eeh_pe_traverse(struct eeh_pe *root, | 152 | void *eeh_pe_traverse(struct eeh_pe *root, |
153 | eeh_traverse_func fn, void *flag) | 153 | eeh_traverse_func fn, void *flag) |
154 | { | 154 | { |
155 | struct eeh_pe *pe; | 155 | struct eeh_pe *pe; |
156 | void *ret; | 156 | void *ret; |
@@ -176,7 +176,7 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root, | |||
176 | eeh_traverse_func fn, void *flag) | 176 | eeh_traverse_func fn, void *flag) |
177 | { | 177 | { |
178 | struct eeh_pe *pe; | 178 | struct eeh_pe *pe; |
179 | struct eeh_dev *edev; | 179 | struct eeh_dev *edev, *tmp; |
180 | void *ret; | 180 | void *ret; |
181 | 181 | ||
182 | if (!root) { | 182 | if (!root) { |
@@ -186,7 +186,7 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root, | |||
186 | 186 | ||
187 | /* Traverse root PE */ | 187 | /* Traverse root PE */ |
188 | for (pe = root; pe; pe = eeh_pe_next(pe, root)) { | 188 | for (pe = root; pe; pe = eeh_pe_next(pe, root)) { |
189 | eeh_pe_for_each_dev(pe, edev) { | 189 | eeh_pe_for_each_dev(pe, edev, tmp) { |
190 | ret = fn(edev, flag); | 190 | ret = fn(edev, flag); |
191 | if (ret) | 191 | if (ret) |
192 | return ret; | 192 | return ret; |
@@ -333,7 +333,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) | |||
333 | while (parent) { | 333 | while (parent) { |
334 | if (!(parent->type & EEH_PE_INVALID)) | 334 | if (!(parent->type & EEH_PE_INVALID)) |
335 | break; | 335 | break; |
336 | parent->type &= ~EEH_PE_INVALID; | 336 | parent->type &= ~(EEH_PE_INVALID | EEH_PE_KEEP); |
337 | parent = parent->parent; | 337 | parent = parent->parent; |
338 | } | 338 | } |
339 | pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n", | 339 | pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n", |
@@ -397,21 +397,20 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) | |||
397 | /** | 397 | /** |
398 | * eeh_rmv_from_parent_pe - Remove one EEH device from the associated PE | 398 | * eeh_rmv_from_parent_pe - Remove one EEH device from the associated PE |
399 | * @edev: EEH device | 399 | * @edev: EEH device |
400 | * @purge_pe: remove PE or not | ||
401 | * | 400 | * |
402 | * The PE hierarchy tree might be changed when doing PCI hotplug. | 401 | * The PE hierarchy tree might be changed when doing PCI hotplug. |
403 | * Also, the PCI devices or buses could be removed from the system | 402 | * Also, the PCI devices or buses could be removed from the system |
404 | * during EEH recovery. So we have to call the function remove the | 403 | * during EEH recovery. So we have to call the function remove the |
405 | * corresponding PE accordingly if necessary. | 404 | * corresponding PE accordingly if necessary. |
406 | */ | 405 | */ |
407 | int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe) | 406 | int eeh_rmv_from_parent_pe(struct eeh_dev *edev) |
408 | { | 407 | { |
409 | struct eeh_pe *pe, *parent, *child; | 408 | struct eeh_pe *pe, *parent, *child; |
410 | int cnt; | 409 | int cnt; |
411 | 410 | ||
412 | if (!edev->pe) { | 411 | if (!edev->pe) { |
413 | pr_warning("%s: No PE found for EEH device %s\n", | 412 | pr_debug("%s: No PE found for EEH device %s\n", |
414 | __func__, edev->dn->full_name); | 413 | __func__, edev->dn->full_name); |
415 | return -EEXIST; | 414 | return -EEXIST; |
416 | } | 415 | } |
417 | 416 | ||
@@ -431,7 +430,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe) | |||
431 | if (pe->type & EEH_PE_PHB) | 430 | if (pe->type & EEH_PE_PHB) |
432 | break; | 431 | break; |
433 | 432 | ||
434 | if (purge_pe) { | 433 | if (!(pe->state & EEH_PE_KEEP)) { |
435 | if (list_empty(&pe->edevs) && | 434 | if (list_empty(&pe->edevs) && |
436 | list_empty(&pe->child_list)) { | 435 | list_empty(&pe->child_list)) { |
437 | list_del(&pe->child); | 436 | list_del(&pe->child); |
@@ -502,7 +501,7 @@ static void *__eeh_pe_state_mark(void *data, void *flag) | |||
502 | { | 501 | { |
503 | struct eeh_pe *pe = (struct eeh_pe *)data; | 502 | struct eeh_pe *pe = (struct eeh_pe *)data; |
504 | int state = *((int *)flag); | 503 | int state = *((int *)flag); |
505 | struct eeh_dev *tmp; | 504 | struct eeh_dev *edev, *tmp; |
506 | struct pci_dev *pdev; | 505 | struct pci_dev *pdev; |
507 | 506 | ||
508 | /* | 507 | /* |
@@ -512,8 +511,8 @@ static void *__eeh_pe_state_mark(void *data, void *flag) | |||
512 | * the PCI device driver. | 511 | * the PCI device driver. |
513 | */ | 512 | */ |
514 | pe->state |= state; | 513 | pe->state |= state; |
515 | eeh_pe_for_each_dev(pe, tmp) { | 514 | eeh_pe_for_each_dev(pe, edev, tmp) { |
516 | pdev = eeh_dev_to_pci_dev(tmp); | 515 | pdev = eeh_dev_to_pci_dev(edev); |
517 | if (pdev) | 516 | if (pdev) |
518 | pdev->error_state = pci_channel_io_frozen; | 517 | pdev->error_state = pci_channel_io_frozen; |
519 | } | 518 | } |
@@ -579,7 +578,7 @@ void eeh_pe_state_clear(struct eeh_pe *pe, int state) | |||
579 | * blocked on normal path during the stage. So we need utilize | 578 | * blocked on normal path during the stage. So we need utilize |
580 | * eeh operations, which is always permitted. | 579 | * eeh operations, which is always permitted. |
581 | */ | 580 | */ |
582 | static void eeh_bridge_check_link(struct pci_dev *pdev, | 581 | static void eeh_bridge_check_link(struct eeh_dev *edev, |
583 | struct device_node *dn) | 582 | struct device_node *dn) |
584 | { | 583 | { |
585 | int cap; | 584 | int cap; |
@@ -590,16 +589,17 @@ static void eeh_bridge_check_link(struct pci_dev *pdev, | |||
590 | * We only check root port and downstream ports of | 589 | * We only check root port and downstream ports of |
591 | * PCIe switches | 590 | * PCIe switches |
592 | */ | 591 | */ |
593 | if (!pci_is_pcie(pdev) || | 592 | if (!(edev->mode & (EEH_DEV_ROOT_PORT | EEH_DEV_DS_PORT))) |
594 | (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && | ||
595 | pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)) | ||
596 | return; | 593 | return; |
597 | 594 | ||
598 | pr_debug("%s: Check PCIe link for %s ...\n", | 595 | pr_debug("%s: Check PCIe link for %04x:%02x:%02x.%01x ...\n", |
599 | __func__, pci_name(pdev)); | 596 | __func__, edev->phb->global_number, |
597 | edev->config_addr >> 8, | ||
598 | PCI_SLOT(edev->config_addr & 0xFF), | ||
599 | PCI_FUNC(edev->config_addr & 0xFF)); | ||
600 | 600 | ||
601 | /* Check slot status */ | 601 | /* Check slot status */ |
602 | cap = pdev->pcie_cap; | 602 | cap = edev->pcie_cap; |
603 | eeh_ops->read_config(dn, cap + PCI_EXP_SLTSTA, 2, &val); | 603 | eeh_ops->read_config(dn, cap + PCI_EXP_SLTSTA, 2, &val); |
604 | if (!(val & PCI_EXP_SLTSTA_PDS)) { | 604 | if (!(val & PCI_EXP_SLTSTA_PDS)) { |
605 | pr_debug(" No card in the slot (0x%04x) !\n", val); | 605 | pr_debug(" No card in the slot (0x%04x) !\n", val); |
@@ -653,8 +653,7 @@ static void eeh_bridge_check_link(struct pci_dev *pdev, | |||
653 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) | 653 | #define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF)) |
654 | #define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)]) | 654 | #define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)]) |
655 | 655 | ||
656 | static void eeh_restore_bridge_bars(struct pci_dev *pdev, | 656 | static void eeh_restore_bridge_bars(struct eeh_dev *edev, |
657 | struct eeh_dev *edev, | ||
658 | struct device_node *dn) | 657 | struct device_node *dn) |
659 | { | 658 | { |
660 | int i; | 659 | int i; |
@@ -680,7 +679,7 @@ static void eeh_restore_bridge_bars(struct pci_dev *pdev, | |||
680 | eeh_ops->write_config(dn, PCI_COMMAND, 4, edev->config_space[1]); | 679 | eeh_ops->write_config(dn, PCI_COMMAND, 4, edev->config_space[1]); |
681 | 680 | ||
682 | /* Check the PCIe link is ready */ | 681 | /* Check the PCIe link is ready */ |
683 | eeh_bridge_check_link(pdev, dn); | 682 | eeh_bridge_check_link(edev, dn); |
684 | } | 683 | } |
685 | 684 | ||
686 | static void eeh_restore_device_bars(struct eeh_dev *edev, | 685 | static void eeh_restore_device_bars(struct eeh_dev *edev, |
@@ -729,19 +728,12 @@ static void eeh_restore_device_bars(struct eeh_dev *edev, | |||
729 | */ | 728 | */ |
730 | static void *eeh_restore_one_device_bars(void *data, void *flag) | 729 | static void *eeh_restore_one_device_bars(void *data, void *flag) |
731 | { | 730 | { |
732 | struct pci_dev *pdev = NULL; | ||
733 | struct eeh_dev *edev = (struct eeh_dev *)data; | 731 | struct eeh_dev *edev = (struct eeh_dev *)data; |
734 | struct device_node *dn = eeh_dev_to_of_node(edev); | 732 | struct device_node *dn = eeh_dev_to_of_node(edev); |
735 | 733 | ||
736 | /* Trace the PCI bridge */ | 734 | /* Do special restore for bridges */ |
737 | if (eeh_probe_mode_dev()) { | 735 | if (edev->mode & EEH_DEV_BRIDGE) |
738 | pdev = eeh_dev_to_pci_dev(edev); | 736 | eeh_restore_bridge_bars(edev, dn); |
739 | if (pdev->hdr_type != PCI_HEADER_TYPE_BRIDGE) | ||
740 | pdev = NULL; | ||
741 | } | ||
742 | |||
743 | if (pdev) | ||
744 | eeh_restore_bridge_bars(pdev, edev, dn); | ||
745 | else | 737 | else |
746 | eeh_restore_device_bars(edev, dn); | 738 | eeh_restore_device_bars(edev, dn); |
747 | 739 | ||
diff --git a/arch/powerpc/kernel/eeh_sysfs.c b/arch/powerpc/kernel/eeh_sysfs.c index e7ae3484918c..5d753d4f2c75 100644 --- a/arch/powerpc/kernel/eeh_sysfs.c +++ b/arch/powerpc/kernel/eeh_sysfs.c | |||
@@ -56,19 +56,40 @@ EEH_SHOW_ATTR(eeh_pe_config_addr, pe_config_addr, "0x%x"); | |||
56 | 56 | ||
57 | void eeh_sysfs_add_device(struct pci_dev *pdev) | 57 | void eeh_sysfs_add_device(struct pci_dev *pdev) |
58 | { | 58 | { |
59 | struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev); | ||
59 | int rc=0; | 60 | int rc=0; |
60 | 61 | ||
62 | if (edev && (edev->mode & EEH_DEV_SYSFS)) | ||
63 | return; | ||
64 | |||
61 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode); | 65 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode); |
62 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr); | 66 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr); |
63 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); | 67 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); |
64 | 68 | ||
65 | if (rc) | 69 | if (rc) |
66 | printk(KERN_WARNING "EEH: Unable to create sysfs entries\n"); | 70 | printk(KERN_WARNING "EEH: Unable to create sysfs entries\n"); |
71 | else if (edev) | ||
72 | edev->mode |= EEH_DEV_SYSFS; | ||
67 | } | 73 | } |
68 | 74 | ||
69 | void eeh_sysfs_remove_device(struct pci_dev *pdev) | 75 | void eeh_sysfs_remove_device(struct pci_dev *pdev) |
70 | { | 76 | { |
77 | struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev); | ||
78 | |||
79 | /* | ||
80 | * The parent directory might have been removed. We needn't | ||
81 | * continue for that case. | ||
82 | */ | ||
83 | if (!pdev->dev.kobj.sd) { | ||
84 | if (edev) | ||
85 | edev->mode &= ~EEH_DEV_SYSFS; | ||
86 | return; | ||
87 | } | ||
88 | |||
71 | device_remove_file(&pdev->dev, &dev_attr_eeh_mode); | 89 | device_remove_file(&pdev->dev, &dev_attr_eeh_mode); |
72 | device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr); | 90 | device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr); |
73 | device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); | 91 | device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); |
92 | |||
93 | if (edev) | ||
94 | edev->mode &= ~EEH_DEV_SYSFS; | ||
74 | } | 95 | } |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index f46914a0f33e..7d22a675fe1a 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -1462,6 +1462,8 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus) | |||
1462 | /* Allocate bus and devices resources */ | 1462 | /* Allocate bus and devices resources */ |
1463 | pcibios_allocate_bus_resources(bus); | 1463 | pcibios_allocate_bus_resources(bus); |
1464 | pcibios_claim_one_bus(bus); | 1464 | pcibios_claim_one_bus(bus); |
1465 | if (!pci_has_flag(PCI_PROBE_ONLY)) | ||
1466 | pci_assign_unassigned_bus_resources(bus); | ||
1465 | 1467 | ||
1466 | /* Fixup EEH */ | 1468 | /* Fixup EEH */ |
1467 | eeh_add_device_tree_late(bus); | 1469 | eeh_add_device_tree_late(bus); |
diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c index 3f608800c06b..c1e17ae68a08 100644 --- a/arch/powerpc/kernel/pci-hotplug.c +++ b/arch/powerpc/kernel/pci-hotplug.c | |||
@@ -22,45 +22,40 @@ | |||
22 | #include <asm/eeh.h> | 22 | #include <asm/eeh.h> |
23 | 23 | ||
24 | /** | 24 | /** |
25 | * __pcibios_remove_pci_devices - remove all devices under this bus | 25 | * pcibios_release_device - release PCI device |
26 | * @dev: PCI device | ||
27 | * | ||
28 | * The function is called before releasing the indicated PCI device. | ||
29 | */ | ||
30 | void pcibios_release_device(struct pci_dev *dev) | ||
31 | { | ||
32 | eeh_remove_device(dev); | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * pcibios_remove_pci_devices - remove all devices under this bus | ||
26 | * @bus: the indicated PCI bus | 37 | * @bus: the indicated PCI bus |
27 | * @purge_pe: destroy the PE on removal of PCI devices | ||
28 | * | 38 | * |
29 | * Remove all of the PCI devices under this bus both from the | 39 | * Remove all of the PCI devices under this bus both from the |
30 | * linux pci device tree, and from the powerpc EEH address cache. | 40 | * linux pci device tree, and from the powerpc EEH address cache. |
31 | * By default, the corresponding PE will be destroied during the | ||
32 | * normal PCI hotplug path. For PCI hotplug during EEH recovery, | ||
33 | * the corresponding PE won't be destroied and deallocated. | ||
34 | */ | 41 | */ |
35 | void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe) | 42 | void pcibios_remove_pci_devices(struct pci_bus *bus) |
36 | { | 43 | { |
37 | struct pci_dev *dev, *tmp; | 44 | struct pci_dev *dev, *tmp; |
38 | struct pci_bus *child_bus; | 45 | struct pci_bus *child_bus; |
39 | 46 | ||
40 | /* First go down child busses */ | 47 | /* First go down child busses */ |
41 | list_for_each_entry(child_bus, &bus->children, node) | 48 | list_for_each_entry(child_bus, &bus->children, node) |
42 | __pcibios_remove_pci_devices(child_bus, purge_pe); | 49 | pcibios_remove_pci_devices(child_bus); |
43 | 50 | ||
44 | pr_debug("PCI: Removing devices on bus %04x:%02x\n", | 51 | pr_debug("PCI: Removing devices on bus %04x:%02x\n", |
45 | pci_domain_nr(bus), bus->number); | 52 | pci_domain_nr(bus), bus->number); |
46 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { | 53 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { |
47 | pr_debug(" * Removing %s...\n", pci_name(dev)); | 54 | pr_debug(" Removing %s...\n", pci_name(dev)); |
48 | eeh_remove_bus_device(dev, purge_pe); | ||
49 | pci_stop_and_remove_bus_device(dev); | 55 | pci_stop_and_remove_bus_device(dev); |
50 | } | 56 | } |
51 | } | 57 | } |
52 | 58 | ||
53 | /** | ||
54 | * pcibios_remove_pci_devices - remove all devices under this bus | ||
55 | * @bus: the indicated PCI bus | ||
56 | * | ||
57 | * Remove all of the PCI devices under this bus both from the | ||
58 | * linux pci device tree, and from the powerpc EEH address cache. | ||
59 | */ | ||
60 | void pcibios_remove_pci_devices(struct pci_bus *bus) | ||
61 | { | ||
62 | __pcibios_remove_pci_devices(bus, 1); | ||
63 | } | ||
64 | EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices); | 59 | EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices); |
65 | 60 | ||
66 | /** | 61 | /** |
@@ -76,7 +71,7 @@ EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices); | |||
76 | */ | 71 | */ |
77 | void pcibios_add_pci_devices(struct pci_bus * bus) | 72 | void pcibios_add_pci_devices(struct pci_bus * bus) |
78 | { | 73 | { |
79 | int slotno, num, mode, pass, max; | 74 | int slotno, mode, pass, max; |
80 | struct pci_dev *dev; | 75 | struct pci_dev *dev; |
81 | struct device_node *dn = pci_bus_to_OF_node(bus); | 76 | struct device_node *dn = pci_bus_to_OF_node(bus); |
82 | 77 | ||
@@ -90,11 +85,15 @@ void pcibios_add_pci_devices(struct pci_bus * bus) | |||
90 | /* use ofdt-based probe */ | 85 | /* use ofdt-based probe */ |
91 | of_rescan_bus(dn, bus); | 86 | of_rescan_bus(dn, bus); |
92 | } else if (mode == PCI_PROBE_NORMAL) { | 87 | } else if (mode == PCI_PROBE_NORMAL) { |
93 | /* use legacy probe */ | 88 | /* |
89 | * Use legacy probe. In the partial hotplug case, we | ||
90 | * probably have grandchildren devices unplugged. So | ||
91 | * we don't check the return value from pci_scan_slot() in | ||
92 | * order for fully rescan all the way down to pick them up. | ||
93 | * They can have been removed during partial hotplug. | ||
94 | */ | ||
94 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); | 95 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); |
95 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); | 96 | pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); |
96 | if (!num) | ||
97 | return; | ||
98 | pcibios_setup_bus_devices(bus); | 97 | pcibios_setup_bus_devices(bus); |
99 | max = bus->busn_res.start; | 98 | max = bus->busn_res.start; |
100 | for (pass = 0; pass < 2; pass++) { | 99 | for (pass = 0; pass < 2; pass++) { |
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 6b0ba5854d99..15d9105323bf 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c | |||
@@ -230,11 +230,14 @@ void of_scan_pci_bridge(struct pci_dev *dev) | |||
230 | return; | 230 | return; |
231 | } | 231 | } |
232 | 232 | ||
233 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); | 233 | bus = pci_find_bus(pci_domain_nr(dev->bus), busrange[0]); |
234 | if (!bus) { | 234 | if (!bus) { |
235 | printk(KERN_ERR "Failed to create pci bus for %s\n", | 235 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); |
236 | node->full_name); | 236 | if (!bus) { |
237 | return; | 237 | printk(KERN_ERR "Failed to create pci bus for %s\n", |
238 | node->full_name); | ||
239 | return; | ||
240 | } | ||
238 | } | 241 | } |
239 | 242 | ||
240 | bus->primary = dev->bus->number; | 243 | bus->primary = dev->bus->number; |
@@ -292,6 +295,38 @@ void of_scan_pci_bridge(struct pci_dev *dev) | |||
292 | } | 295 | } |
293 | EXPORT_SYMBOL(of_scan_pci_bridge); | 296 | EXPORT_SYMBOL(of_scan_pci_bridge); |
294 | 297 | ||
298 | static struct pci_dev *of_scan_pci_dev(struct pci_bus *bus, | ||
299 | struct device_node *dn) | ||
300 | { | ||
301 | struct pci_dev *dev = NULL; | ||
302 | const u32 *reg; | ||
303 | int reglen, devfn; | ||
304 | |||
305 | pr_debug(" * %s\n", dn->full_name); | ||
306 | if (!of_device_is_available(dn)) | ||
307 | return NULL; | ||
308 | |||
309 | reg = of_get_property(dn, "reg", ®len); | ||
310 | if (reg == NULL || reglen < 20) | ||
311 | return NULL; | ||
312 | devfn = (reg[0] >> 8) & 0xff; | ||
313 | |||
314 | /* Check if the PCI device is already there */ | ||
315 | dev = pci_get_slot(bus, devfn); | ||
316 | if (dev) { | ||
317 | pci_dev_put(dev); | ||
318 | return dev; | ||
319 | } | ||
320 | |||
321 | /* create a new pci_dev for this device */ | ||
322 | dev = of_create_pci_dev(dn, bus, devfn); | ||
323 | if (!dev) | ||
324 | return NULL; | ||
325 | |||
326 | pr_debug(" dev header type: %x\n", dev->hdr_type); | ||
327 | return dev; | ||
328 | } | ||
329 | |||
295 | /** | 330 | /** |
296 | * __of_scan_bus - given a PCI bus node, setup bus and scan for child devices | 331 | * __of_scan_bus - given a PCI bus node, setup bus and scan for child devices |
297 | * @node: device tree node for the PCI bus | 332 | * @node: device tree node for the PCI bus |
@@ -302,8 +337,6 @@ static void __of_scan_bus(struct device_node *node, struct pci_bus *bus, | |||
302 | int rescan_existing) | 337 | int rescan_existing) |
303 | { | 338 | { |
304 | struct device_node *child; | 339 | struct device_node *child; |
305 | const u32 *reg; | ||
306 | int reglen, devfn; | ||
307 | struct pci_dev *dev; | 340 | struct pci_dev *dev; |
308 | 341 | ||
309 | pr_debug("of_scan_bus(%s) bus no %d...\n", | 342 | pr_debug("of_scan_bus(%s) bus no %d...\n", |
@@ -311,16 +344,7 @@ static void __of_scan_bus(struct device_node *node, struct pci_bus *bus, | |||
311 | 344 | ||
312 | /* Scan direct children */ | 345 | /* Scan direct children */ |
313 | for_each_child_of_node(node, child) { | 346 | for_each_child_of_node(node, child) { |
314 | pr_debug(" * %s\n", child->full_name); | 347 | dev = of_scan_pci_dev(bus, child); |
315 | if (!of_device_is_available(child)) | ||
316 | continue; | ||
317 | reg = of_get_property(child, "reg", ®len); | ||
318 | if (reg == NULL || reglen < 20) | ||
319 | continue; | ||
320 | devfn = (reg[0] >> 8) & 0xff; | ||
321 | |||
322 | /* create a new pci_dev for this device */ | ||
323 | dev = of_create_pci_dev(child, bus, devfn); | ||
324 | if (!dev) | 348 | if (!dev) |
325 | continue; | 349 | continue; |
326 | pr_debug(" dev header type: %x\n", dev->hdr_type); | 350 | pr_debug(" dev header type: %x\n", dev->hdr_type); |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 5eccda9fd33f..607902424e73 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -644,7 +644,8 @@ unsigned char ibm_architecture_vec[] = { | |||
644 | W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */ | 644 | W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */ |
645 | W(0xffff0000), W(0x003e0000), /* POWER6 */ | 645 | W(0xffff0000), W(0x003e0000), /* POWER6 */ |
646 | W(0xffff0000), W(0x003f0000), /* POWER7 */ | 646 | W(0xffff0000), W(0x003f0000), /* POWER7 */ |
647 | W(0xffff0000), W(0x004b0000), /* POWER8 */ | 647 | W(0xffff0000), W(0x004b0000), /* POWER8E */ |
648 | W(0xffff0000), W(0x004d0000), /* POWER8 */ | ||
648 | W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */ | 649 | W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */ |
649 | W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ | 650 | W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ |
650 | W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */ | 651 | W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */ |
@@ -706,7 +707,7 @@ unsigned char ibm_architecture_vec[] = { | |||
706 | * must match by the macro below. Update the definition if | 707 | * must match by the macro below. Update the definition if |
707 | * the structure layout changes. | 708 | * the structure layout changes. |
708 | */ | 709 | */ |
709 | #define IBM_ARCH_VEC_NRCORES_OFFSET 117 | 710 | #define IBM_ARCH_VEC_NRCORES_OFFSET 125 |
710 | W(NR_CPUS), /* number of cores supported */ | 711 | W(NR_CPUS), /* number of cores supported */ |
711 | 0, | 712 | 0, |
712 | 0, | 713 | 0, |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 654e479802f2..f096e72262f4 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -38,9 +38,6 @@ jiffies = jiffies_64 + 4; | |||
38 | #endif | 38 | #endif |
39 | SECTIONS | 39 | SECTIONS |
40 | { | 40 | { |
41 | . = 0; | ||
42 | reloc_start = .; | ||
43 | |||
44 | . = KERNELBASE; | 41 | . = KERNELBASE; |
45 | 42 | ||
46 | /* | 43 | /* |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 3f0c30ae4791..c33d939120c9 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -43,6 +43,7 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) | |||
43 | { | 43 | { |
44 | unsigned long va; | 44 | unsigned long va; |
45 | unsigned int penc; | 45 | unsigned int penc; |
46 | unsigned long sllp; | ||
46 | 47 | ||
47 | /* | 48 | /* |
48 | * We need 14 to 65 bits of va for a tlibe of 4K page | 49 | * We need 14 to 65 bits of va for a tlibe of 4K page |
@@ -64,7 +65,9 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) | |||
64 | /* clear out bits after (52) [0....52.....63] */ | 65 | /* clear out bits after (52) [0....52.....63] */ |
65 | va &= ~((1ul << (64 - 52)) - 1); | 66 | va &= ~((1ul << (64 - 52)) - 1); |
66 | va |= ssize << 8; | 67 | va |= ssize << 8; |
67 | va |= mmu_psize_defs[apsize].sllp << 6; | 68 | sllp = ((mmu_psize_defs[apsize].sllp & SLB_VSID_L) >> 6) | |
69 | ((mmu_psize_defs[apsize].sllp & SLB_VSID_LP) >> 4); | ||
70 | va |= sllp << 5; | ||
68 | asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2) | 71 | asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2) |
69 | : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206) | 72 | : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206) |
70 | : "memory"); | 73 | : "memory"); |
@@ -98,6 +101,7 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) | |||
98 | { | 101 | { |
99 | unsigned long va; | 102 | unsigned long va; |
100 | unsigned int penc; | 103 | unsigned int penc; |
104 | unsigned long sllp; | ||
101 | 105 | ||
102 | /* VPN_SHIFT can be atmost 12 */ | 106 | /* VPN_SHIFT can be atmost 12 */ |
103 | va = vpn << VPN_SHIFT; | 107 | va = vpn << VPN_SHIFT; |
@@ -113,7 +117,9 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) | |||
113 | /* clear out bits after(52) [0....52.....63] */ | 117 | /* clear out bits after(52) [0....52.....63] */ |
114 | va &= ~((1ul << (64 - 52)) - 1); | 118 | va &= ~((1ul << (64 - 52)) - 1); |
115 | va |= ssize << 8; | 119 | va |= ssize << 8; |
116 | va |= mmu_psize_defs[apsize].sllp << 6; | 120 | sllp = ((mmu_psize_defs[apsize].sllp & SLB_VSID_L) >> 6) | |
121 | ((mmu_psize_defs[apsize].sllp & SLB_VSID_LP) >> 4); | ||
122 | va |= sllp << 5; | ||
117 | asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)" | 123 | asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)" |
118 | : : "r"(va) : "memory"); | 124 | : : "r"(va) : "memory"); |
119 | break; | 125 | break; |
@@ -554,6 +560,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | |||
554 | seg_off |= vpi << shift; | 560 | seg_off |= vpi << shift; |
555 | } | 561 | } |
556 | *vpn = vsid << (SID_SHIFT - VPN_SHIFT) | seg_off >> VPN_SHIFT; | 562 | *vpn = vsid << (SID_SHIFT - VPN_SHIFT) | seg_off >> VPN_SHIFT; |
563 | break; | ||
557 | case MMU_SEGSIZE_1T: | 564 | case MMU_SEGSIZE_1T: |
558 | /* We only have 40 - 23 bits of seg_off in avpn */ | 565 | /* We only have 40 - 23 bits of seg_off in avpn */ |
559 | seg_off = (avpn & 0x1ffff) << 23; | 566 | seg_off = (avpn & 0x1ffff) << 23; |
@@ -563,6 +570,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | |||
563 | seg_off |= vpi << shift; | 570 | seg_off |= vpi << shift; |
564 | } | 571 | } |
565 | *vpn = vsid << (SID_SHIFT_1T - VPN_SHIFT) | seg_off >> VPN_SHIFT; | 572 | *vpn = vsid << (SID_SHIFT_1T - VPN_SHIFT) | seg_off >> VPN_SHIFT; |
573 | break; | ||
566 | default: | 574 | default: |
567 | *vpn = size = 0; | 575 | *vpn = size = 0; |
568 | } | 576 | } |
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index a3985aee77fe..24a45f91c65f 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c | |||
@@ -1252,8 +1252,11 @@ nocheck: | |||
1252 | 1252 | ||
1253 | ret = 0; | 1253 | ret = 0; |
1254 | out: | 1254 | out: |
1255 | if (has_branch_stack(event)) | 1255 | if (has_branch_stack(event)) { |
1256 | power_pmu_bhrb_enable(event); | 1256 | power_pmu_bhrb_enable(event); |
1257 | cpuhw->bhrb_filter = ppmu->bhrb_filter_map( | ||
1258 | event->attr.branch_sample_type); | ||
1259 | } | ||
1257 | 1260 | ||
1258 | perf_pmu_enable(event->pmu); | 1261 | perf_pmu_enable(event->pmu); |
1259 | local_irq_restore(flags); | 1262 | local_irq_restore(flags); |
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index 96a64d6a8bdf..7466374d2787 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c | |||
@@ -561,18 +561,13 @@ static int power8_generic_events[] = { | |||
561 | static u64 power8_bhrb_filter_map(u64 branch_sample_type) | 561 | static u64 power8_bhrb_filter_map(u64 branch_sample_type) |
562 | { | 562 | { |
563 | u64 pmu_bhrb_filter = 0; | 563 | u64 pmu_bhrb_filter = 0; |
564 | u64 br_privilege = branch_sample_type & ONLY_PLM; | ||
565 | 564 | ||
566 | /* BHRB and regular PMU events share the same prvillege state | 565 | /* BHRB and regular PMU events share the same privilege state |
567 | * filter configuration. BHRB is always recorded along with a | 566 | * filter configuration. BHRB is always recorded along with a |
568 | * regular PMU event. So privilege state filter criteria for BHRB | 567 | * regular PMU event. As the privilege state filter is handled |
569 | * and the companion PMU events has to be the same. As a default | 568 | * in the basic PMC configuration of the accompanying regular |
570 | * "perf record" tool sets all privillege bits ON when no filter | 569 | * PMU event, we ignore any separate BHRB specific request. |
571 | * criteria is provided in the command line. So as along as all | ||
572 | * privillege bits are ON or they are OFF, we are good to go. | ||
573 | */ | 570 | */ |
574 | if ((br_privilege != 7) && (br_privilege != 0)) | ||
575 | return -1; | ||
576 | 571 | ||
577 | /* No branch filter requested */ | 572 | /* No branch filter requested */ |
578 | if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY) | 573 | if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY) |
@@ -621,10 +616,19 @@ static struct power_pmu power8_pmu = { | |||
621 | 616 | ||
622 | static int __init init_power8_pmu(void) | 617 | static int __init init_power8_pmu(void) |
623 | { | 618 | { |
619 | int rc; | ||
620 | |||
624 | if (!cur_cpu_spec->oprofile_cpu_type || | 621 | if (!cur_cpu_spec->oprofile_cpu_type || |
625 | strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power8")) | 622 | strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power8")) |
626 | return -ENODEV; | 623 | return -ENODEV; |
627 | 624 | ||
628 | return register_power_pmu(&power8_pmu); | 625 | rc = register_power_pmu(&power8_pmu); |
626 | if (rc) | ||
627 | return rc; | ||
628 | |||
629 | /* Tell userspace that EBB is supported */ | ||
630 | cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB; | ||
631 | |||
632 | return 0; | ||
629 | } | 633 | } |
630 | early_initcall(init_power8_pmu); | 634 | early_initcall(init_power8_pmu); |
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 969cce73055a..79663d26e6ea 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c | |||
@@ -114,7 +114,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
114 | * the root bridge. So it's not reasonable to continue | 114 | * the root bridge. So it's not reasonable to continue |
115 | * the probing. | 115 | * the probing. |
116 | */ | 116 | */ |
117 | if (!dn || !edev) | 117 | if (!dn || !edev || edev->pe) |
118 | return 0; | 118 | return 0; |
119 | 119 | ||
120 | /* Skip for PCI-ISA bridge */ | 120 | /* Skip for PCI-ISA bridge */ |
@@ -122,8 +122,19 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
122 | return 0; | 122 | return 0; |
123 | 123 | ||
124 | /* Initialize eeh device */ | 124 | /* Initialize eeh device */ |
125 | edev->class_code = dev->class; | 125 | edev->class_code = dev->class; |
126 | edev->mode = 0; | 126 | edev->mode &= 0xFFFFFF00; |
127 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
128 | edev->mode |= EEH_DEV_BRIDGE; | ||
129 | if (pci_is_pcie(dev)) { | ||
130 | edev->pcie_cap = pci_pcie_cap(dev); | ||
131 | |||
132 | if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) | ||
133 | edev->mode |= EEH_DEV_ROOT_PORT; | ||
134 | else if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) | ||
135 | edev->mode |= EEH_DEV_DS_PORT; | ||
136 | } | ||
137 | |||
127 | edev->config_addr = ((dev->bus->number << 8) | dev->devfn); | 138 | edev->config_addr = ((dev->bus->number << 8) | dev->devfn); |
128 | edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); | 139 | edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); |
129 | 140 | ||
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 49b57b9f835d..d8140b125e62 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -1266,7 +1266,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1266 | opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE); | 1266 | opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE); |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | void pnv_pci_init_ioda2_phb(struct device_node *np) | 1269 | void __init pnv_pci_init_ioda2_phb(struct device_node *np) |
1270 | { | 1270 | { |
1271 | pnv_pci_init_ioda_phb(np, 0, PNV_PHB_IODA2); | 1271 | pnv_pci_init_ioda_phb(np, 0, PNV_PHB_IODA2); |
1272 | } | 1272 | } |
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 1bd3399146ed..62b4f8025de0 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
@@ -19,7 +19,6 @@ config PPC_PSERIES | |||
19 | select ZLIB_DEFLATE | 19 | select ZLIB_DEFLATE |
20 | select PPC_DOORBELL | 20 | select PPC_DOORBELL |
21 | select HAVE_CONTEXT_TRACKING | 21 | select HAVE_CONTEXT_TRACKING |
22 | select HOTPLUG if SMP | ||
23 | select HOTPLUG_CPU if SMP | 22 | select HOTPLUG_CPU if SMP |
24 | default y | 23 | default y |
25 | 24 | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index b456b157d33d..7fbc25b1813f 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c | |||
@@ -133,6 +133,48 @@ static int pseries_eeh_init(void) | |||
133 | return 0; | 133 | return 0; |
134 | } | 134 | } |
135 | 135 | ||
136 | static int pseries_eeh_cap_start(struct device_node *dn) | ||
137 | { | ||
138 | struct pci_dn *pdn = PCI_DN(dn); | ||
139 | u32 status; | ||
140 | |||
141 | if (!pdn) | ||
142 | return 0; | ||
143 | |||
144 | rtas_read_config(pdn, PCI_STATUS, 2, &status); | ||
145 | if (!(status & PCI_STATUS_CAP_LIST)) | ||
146 | return 0; | ||
147 | |||
148 | return PCI_CAPABILITY_LIST; | ||
149 | } | ||
150 | |||
151 | |||
152 | static int pseries_eeh_find_cap(struct device_node *dn, int cap) | ||
153 | { | ||
154 | struct pci_dn *pdn = PCI_DN(dn); | ||
155 | int pos = pseries_eeh_cap_start(dn); | ||
156 | int cnt = 48; /* Maximal number of capabilities */ | ||
157 | u32 id; | ||
158 | |||
159 | if (!pos) | ||
160 | return 0; | ||
161 | |||
162 | while (cnt--) { | ||
163 | rtas_read_config(pdn, pos, 1, &pos); | ||
164 | if (pos < 0x40) | ||
165 | break; | ||
166 | pos &= ~3; | ||
167 | rtas_read_config(pdn, pos + PCI_CAP_LIST_ID, 1, &id); | ||
168 | if (id == 0xff) | ||
169 | break; | ||
170 | if (id == cap) | ||
171 | return pos; | ||
172 | pos += PCI_CAP_LIST_NEXT; | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
136 | /** | 178 | /** |
137 | * pseries_eeh_of_probe - EEH probe on the given device | 179 | * pseries_eeh_of_probe - EEH probe on the given device |
138 | * @dn: OF node | 180 | * @dn: OF node |
@@ -146,14 +188,16 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
146 | { | 188 | { |
147 | struct eeh_dev *edev; | 189 | struct eeh_dev *edev; |
148 | struct eeh_pe pe; | 190 | struct eeh_pe pe; |
191 | struct pci_dn *pdn = PCI_DN(dn); | ||
149 | const u32 *class_code, *vendor_id, *device_id; | 192 | const u32 *class_code, *vendor_id, *device_id; |
150 | const u32 *regs; | 193 | const u32 *regs; |
194 | u32 pcie_flags; | ||
151 | int enable = 0; | 195 | int enable = 0; |
152 | int ret; | 196 | int ret; |
153 | 197 | ||
154 | /* Retrieve OF node and eeh device */ | 198 | /* Retrieve OF node and eeh device */ |
155 | edev = of_node_to_eeh_dev(dn); | 199 | edev = of_node_to_eeh_dev(dn); |
156 | if (!of_device_is_available(dn)) | 200 | if (edev->pe || !of_device_is_available(dn)) |
157 | return NULL; | 201 | return NULL; |
158 | 202 | ||
159 | /* Retrieve class/vendor/device IDs */ | 203 | /* Retrieve class/vendor/device IDs */ |
@@ -167,9 +211,26 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
167 | if (dn->type && !strcmp(dn->type, "isa")) | 211 | if (dn->type && !strcmp(dn->type, "isa")) |
168 | return NULL; | 212 | return NULL; |
169 | 213 | ||
170 | /* Update class code and mode of eeh device */ | 214 | /* |
215 | * Update class code and mode of eeh device. We need | ||
216 | * correctly reflects that current device is root port | ||
217 | * or PCIe switch downstream port. | ||
218 | */ | ||
171 | edev->class_code = *class_code; | 219 | edev->class_code = *class_code; |
172 | edev->mode = 0; | 220 | edev->pcie_cap = pseries_eeh_find_cap(dn, PCI_CAP_ID_EXP); |
221 | edev->mode &= 0xFFFFFF00; | ||
222 | if ((edev->class_code >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
223 | edev->mode |= EEH_DEV_BRIDGE; | ||
224 | if (edev->pcie_cap) { | ||
225 | rtas_read_config(pdn, edev->pcie_cap + PCI_EXP_FLAGS, | ||
226 | 2, &pcie_flags); | ||
227 | pcie_flags = (pcie_flags & PCI_EXP_FLAGS_TYPE) >> 4; | ||
228 | if (pcie_flags == PCI_EXP_TYPE_ROOT_PORT) | ||
229 | edev->mode |= EEH_DEV_ROOT_PORT; | ||
230 | else if (pcie_flags == PCI_EXP_TYPE_DOWNSTREAM) | ||
231 | edev->mode |= EEH_DEV_DS_PORT; | ||
232 | } | ||
233 | } | ||
173 | 234 | ||
174 | /* Retrieve the device address */ | 235 | /* Retrieve the device address */ |
175 | regs = of_get_property(dn, "reg", NULL); | 236 | regs = of_get_property(dn, "reg", NULL); |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 02d6e21619bb..8bad880bd177 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -146,7 +146,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | |||
146 | flags = 0; | 146 | flags = 0; |
147 | 147 | ||
148 | /* Make pHyp happy */ | 148 | /* Make pHyp happy */ |
149 | if ((rflags & _PAGE_NO_CACHE) & !(rflags & _PAGE_WRITETHRU)) | 149 | if ((rflags & _PAGE_NO_CACHE) && !(rflags & _PAGE_WRITETHRU)) |
150 | hpte_r &= ~_PAGE_COHERENT; | 150 | hpte_r &= ~_PAGE_COHERENT; |
151 | if (firmware_has_feature(FW_FEATURE_XCMO) && !(hpte_r & HPTE_R_N)) | 151 | if (firmware_has_feature(FW_FEATURE_XCMO) && !(hpte_r & HPTE_R_N)) |
152 | flags |= H_COALESCE_CAND; | 152 | flags |= H_COALESCE_CAND; |
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 7b3cbde8c783..721c0586b284 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
@@ -287,6 +287,9 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs) | |||
287 | unsigned long *savep; | 287 | unsigned long *savep; |
288 | struct rtas_error_log *h, *errhdr = NULL; | 288 | struct rtas_error_log *h, *errhdr = NULL; |
289 | 289 | ||
290 | /* Mask top two bits */ | ||
291 | regs->gpr[3] &= ~(0x3UL << 62); | ||
292 | |||
290 | if (!VALID_FWNMI_BUFFER(regs->gpr[3])) { | 293 | if (!VALID_FWNMI_BUFFER(regs->gpr[3])) { |
291 | printk(KERN_ERR "FWNMI: corrupt r3 0x%016lx\n", regs->gpr[3]); | 294 | printk(KERN_ERR "FWNMI: corrupt r3 0x%016lx\n", regs->gpr[3]); |
292 | return NULL; | 295 | return NULL; |