diff options
author | Gavin Shan <shangw@linux.vnet.ibm.com> | 2012-09-07 18:44:02 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-09-09 19:35:27 -0400 |
commit | 35e5cfe27e674e4580408b34e7fc97e18460e048 (patch) | |
tree | b601328b2efb63fab07fbc94fa1559da33870b8b | |
parent | 407821a34fce89b4f0b031dbab5cec7d059f46bc (diff) |
powerpc/eeh: Move EEH initialization around
Currently, we have 3 phases for EEH initialization on pSeries platform.
All of them are done through builtin functions: platform initialization,
EEH device creation, and EEH subsystem enablement. All of them are done
no later than ppc_md.setup_arch. That means that the slab/slub isn't ready
yet, so we have to allocate memory chunks on basis of PAGE_SIZE for those
dynamically created EEH devices. That's pretty expensive.
In order to utilize slab/slub for memory allocation, we have to move the EEH
initialization functions around, but all of them should be called after slab
is ready.
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/include/asm/eeh.h | 16 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas_pci.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_dev.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_pseries.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 2 |
6 files changed, 15 insertions, 26 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index d60f99814ffb..06dedffda129 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
@@ -117,11 +117,6 @@ extern int eeh_subsystem_enabled; | |||
117 | 117 | ||
118 | void * __devinit eeh_dev_init(struct device_node *dn, void *data); | 118 | void * __devinit eeh_dev_init(struct device_node *dn, void *data); |
119 | void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb); | 119 | void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb); |
120 | void __init eeh_dev_phb_init(void); | ||
121 | void __init eeh_init(void); | ||
122 | #ifdef CONFIG_PPC_PSERIES | ||
123 | int __init eeh_pseries_init(void); | ||
124 | #endif | ||
125 | int __init eeh_ops_register(struct eeh_ops *ops); | 120 | int __init eeh_ops_register(struct eeh_ops *ops); |
126 | int __exit eeh_ops_unregister(const char *name); | 121 | int __exit eeh_ops_unregister(const char *name); |
127 | unsigned long eeh_check_failure(const volatile void __iomem *token, | 122 | unsigned long eeh_check_failure(const volatile void __iomem *token, |
@@ -156,17 +151,6 @@ static inline void *eeh_dev_init(struct device_node *dn, void *data) | |||
156 | 151 | ||
157 | static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { } | 152 | static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { } |
158 | 153 | ||
159 | static inline void eeh_dev_phb_init(void) { } | ||
160 | |||
161 | static inline void eeh_init(void) { } | ||
162 | |||
163 | #ifdef CONFIG_PPC_PSERIES | ||
164 | static inline int eeh_pseries_init(void) | ||
165 | { | ||
166 | return 0; | ||
167 | } | ||
168 | #endif /* CONFIG_PPC_PSERIES */ | ||
169 | |||
170 | static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val) | 154 | static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val) |
171 | { | 155 | { |
172 | return val; | 156 | return val; |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 179af906dcda..140735c18c36 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -275,9 +275,6 @@ void __init find_and_init_phbs(void) | |||
275 | of_node_put(root); | 275 | of_node_put(root); |
276 | pci_devs_phb_init(); | 276 | pci_devs_phb_init(); |
277 | 277 | ||
278 | /* Create EEH devices for all PHBs */ | ||
279 | eeh_dev_phb_init(); | ||
280 | |||
281 | /* | 278 | /* |
282 | * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties | 279 | * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties |
283 | * in chosen. | 280 | * in chosen. |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index ecd394cf34e6..e819448ea3a7 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -982,7 +982,7 @@ int __exit eeh_ops_unregister(const char *name) | |||
982 | * Even if force-off is set, the EEH hardware is still enabled, so that | 982 | * Even if force-off is set, the EEH hardware is still enabled, so that |
983 | * newer systems can boot. | 983 | * newer systems can boot. |
984 | */ | 984 | */ |
985 | void __init eeh_init(void) | 985 | static int __init eeh_init(void) |
986 | { | 986 | { |
987 | struct pci_controller *hose, *tmp; | 987 | struct pci_controller *hose, *tmp; |
988 | struct device_node *phb; | 988 | struct device_node *phb; |
@@ -992,11 +992,11 @@ void __init eeh_init(void) | |||
992 | if (!eeh_ops) { | 992 | if (!eeh_ops) { |
993 | pr_warning("%s: Platform EEH operation not found\n", | 993 | pr_warning("%s: Platform EEH operation not found\n", |
994 | __func__); | 994 | __func__); |
995 | return; | 995 | return -EEXIST; |
996 | } else if ((ret = eeh_ops->init())) { | 996 | } else if ((ret = eeh_ops->init())) { |
997 | pr_warning("%s: Failed to call platform init function (%d)\n", | 997 | pr_warning("%s: Failed to call platform init function (%d)\n", |
998 | __func__, ret); | 998 | __func__, ret); |
999 | return; | 999 | return ret; |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | raw_spin_lock_init(&confirm_error_lock); | 1002 | raw_spin_lock_init(&confirm_error_lock); |
@@ -1011,8 +1011,12 @@ void __init eeh_init(void) | |||
1011 | printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n"); | 1011 | printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n"); |
1012 | else | 1012 | else |
1013 | printk(KERN_WARNING "EEH: No capable adapters found\n"); | 1013 | printk(KERN_WARNING "EEH: No capable adapters found\n"); |
1014 | |||
1015 | return ret; | ||
1014 | } | 1016 | } |
1015 | 1017 | ||
1018 | core_initcall_sync(eeh_init); | ||
1019 | |||
1016 | /** | 1020 | /** |
1017 | * eeh_add_device_early - Enable EEH for the indicated device_node | 1021 | * eeh_add_device_early - Enable EEH for the indicated device_node |
1018 | * @dn: device node for which to set up EEH | 1022 | * @dn: device node for which to set up EEH |
diff --git a/arch/powerpc/platforms/pseries/eeh_dev.c b/arch/powerpc/platforms/pseries/eeh_dev.c index c4507d095900..ab68c5910f9f 100644 --- a/arch/powerpc/platforms/pseries/eeh_dev.c +++ b/arch/powerpc/platforms/pseries/eeh_dev.c | |||
@@ -93,10 +93,14 @@ void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb) | |||
93 | * Scan all the existing PHBs and create EEH devices for their OF | 93 | * Scan all the existing PHBs and create EEH devices for their OF |
94 | * nodes and their children OF nodes | 94 | * nodes and their children OF nodes |
95 | */ | 95 | */ |
96 | void __init eeh_dev_phb_init(void) | 96 | static int __init eeh_dev_phb_init(void) |
97 | { | 97 | { |
98 | struct pci_controller *phb, *tmp; | 98 | struct pci_controller *phb, *tmp; |
99 | 99 | ||
100 | list_for_each_entry_safe(phb, tmp, &hose_list, list_node) | 100 | list_for_each_entry_safe(phb, tmp, &hose_list, list_node) |
101 | eeh_dev_phb_init_dynamic(phb); | 101 | eeh_dev_phb_init_dynamic(phb); |
102 | |||
103 | return 0; | ||
102 | } | 104 | } |
105 | |||
106 | core_initcall(eeh_dev_phb_init); | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index c33360ec4f4f..5e2805a019c3 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c | |||
@@ -559,7 +559,9 @@ static struct eeh_ops pseries_eeh_ops = { | |||
559 | * EEH initialization on pseries platform. This function should be | 559 | * EEH initialization on pseries platform. This function should be |
560 | * called before any EEH related functions. | 560 | * called before any EEH related functions. |
561 | */ | 561 | */ |
562 | int __init eeh_pseries_init(void) | 562 | static int __init eeh_pseries_init(void) |
563 | { | 563 | { |
564 | return eeh_ops_register(&pseries_eeh_ops); | 564 | return eeh_ops_register(&pseries_eeh_ops); |
565 | } | 565 | } |
566 | |||
567 | early_initcall(eeh_pseries_init); | ||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 36b774442b5c..4a2cd48b21f6 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -388,10 +388,8 @@ static void __init pSeries_setup_arch(void) | |||
388 | 388 | ||
389 | /* Find and initialize PCI host bridges */ | 389 | /* Find and initialize PCI host bridges */ |
390 | init_pci_config_tokens(); | 390 | init_pci_config_tokens(); |
391 | eeh_pseries_init(); | ||
392 | find_and_init_phbs(); | 391 | find_and_init_phbs(); |
393 | pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb); | 392 | pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb); |
394 | eeh_init(); | ||
395 | 393 | ||
396 | pSeries_nvram_init(); | 394 | pSeries_nvram_init(); |
397 | 395 | ||