powerpc/eeh: Move EEH initialisation to an arch initcall
authorOliver O'Halloran <oohall@gmail.com>
Fri, 18 Sep 2020 09:30:46 +0000 (19:30 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 6 Oct 2020 12:22:25 +0000 (23:22 +1100)
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
arch/powerpc/kernel/eeh.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/pseries/eeh_pseries.c

index 98faf139e6767b4c04b53cf1bbaa3a4f35a34119..c9e25cfce8f0596cf68f3b8e49c072673d89f3a0 100644 (file)
@@ -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
index 5db92f39887acd3702f0539ed0fc69c7d70df5d1..b97ec796dd41c9a8f23ea4a5549518db7db20243 100644 (file)
@@ -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);
index a3ed6a0507daf49fe34144bada9485652613ac14..691b9a38b6834fd87519c827ce7120ed6c22698e 100644 (file)
@@ -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);