diff options
author | Oliver O'Halloran <oohall@gmail.com> | 2020-09-18 19:30:46 +1000 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2020-10-06 23:22:25 +1100 |
commit | 395ee2a2a15ba1c4c7c414db24dc3082ba8feab8 (patch) | |
tree | 3444bbb0e4933ed7155d90ab8dde8c2fbb686927 /arch/powerpc | |
parent | 5d69e46a2104050c0a458c6bf6abba5f58f56e4c (diff) |
powerpc/eeh: Move EEH initialisation to an arch initcall
The initialisation of EEH mostly happens in a core_initcall_sync initcall,
followed by registering a bus notifier later on in an arch_initcall.
Anything involving initcall dependecies is mostly incomprehensible unless
you've spent a while staring at code so here's the full sequence:
ppc_md.setup_arch <-- pci_controllers are created here
...time passes...
core_initcall <-- pci_dns are created from DT nodes
core_initcall_sync <-- platforms call eeh_init()
postcore_initcall <-- PCI bus type is registered
postcore_initcall_sync
arch_initcall <-- EEH pci_bus notifier registered
subsys_initcall <-- PHBs are scanned here
There's no real requirement to do the EEH setup at the core_initcall_sync
level. It just needs to be done after pci_dn's are created and before we
start scanning PHBs. Simplify the flow a bit by moving the platform EEH
inititalisation to an arch_initcall so we can fold the bus notifier
registration into eeh_init().
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200918093050.37344-5-oohall@gmail.com
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/eeh.c | 64 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-powernv.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_pseries.c | 2 |
3 files changed, 34 insertions, 34 deletions
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 98faf139e676..c9e25cfce8f0 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -940,6 +940,30 @@ static struct notifier_block eeh_reboot_nb = { .notifier_call = eeh_reboot_notifier, }; +static int eeh_device_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + + switch (action) { + /* + * Note: It's not possible to perform EEH device addition (i.e. + * {pseries,pnv}_pcibios_bus_add_device()) here because it depends on + * the device's resources, which have not yet been set up. + */ + case BUS_NOTIFY_DEL_DEVICE: + eeh_remove_device(to_pci_dev(dev)); + break; + default: + break; + } + return NOTIFY_DONE; +} + +static struct notifier_block eeh_device_nb = { + .notifier_call = eeh_device_notifier, +}; + /** * eeh_init - System wide EEH initialization * @@ -960,7 +984,14 @@ int eeh_init(struct eeh_ops *ops) /* Register reboot notifier */ ret = register_reboot_notifier(&eeh_reboot_nb); if (ret) { - pr_warn("%s: Failed to register notifier (%d)\n", + pr_warn("%s: Failed to register reboot notifier (%d)\n", + __func__, ret); + return ret; + } + + ret = bus_register_notifier(&pci_bus_type, &eeh_device_nb); + if (ret) { + pr_warn("%s: Failed to register bus notifier (%d)\n", __func__, ret); return ret; } @@ -975,37 +1006,6 @@ int eeh_init(struct eeh_ops *ops) return eeh_event_init(); } -static int eeh_device_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - - switch (action) { - /* - * Note: It's not possible to perform EEH device addition (i.e. - * {pseries,pnv}_pcibios_bus_add_device()) here because it depends on - * the device's resources, which have not yet been set up. - */ - case BUS_NOTIFY_DEL_DEVICE: - eeh_remove_device(to_pci_dev(dev)); - break; - default: - break; - } - return NOTIFY_DONE; -} - -static struct notifier_block eeh_device_nb = { - .notifier_call = eeh_device_notifier, -}; - -static __init int eeh_set_bus_notifier(void) -{ - bus_register_notifier(&pci_bus_type, &eeh_device_nb); - return 0; -} -arch_initcall(eeh_set_bus_notifier); - /** * eeh_probe_device() - Perform EEH initialization for the indicated pci device * @dev: pci device for which to set up EEH diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 5db92f39887a..b97ec796dd41 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c @@ -1721,4 +1721,4 @@ static int __init eeh_powernv_init(void) return ret; } -machine_core_initcall_sync(powernv, eeh_powernv_init); +machine_arch_initcall(powernv, eeh_powernv_init); diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index a3ed6a0507da..691b9a38b683 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -985,4 +985,4 @@ static int __init eeh_pseries_init(void) ret); return ret; } -machine_core_initcall_sync(pseries, eeh_pseries_init); +machine_arch_initcall(pseries, eeh_pseries_init); |