]> git.karo-electronics.de Git - linux-beck.git/commitdiff
powerpc, sysfs: Fix CPU hotplug callback registration
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Mon, 10 Mar 2014 20:36:31 +0000 (02:06 +0530)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 20 Mar 2014 12:43:42 +0000 (13:43 +0100)
Subsystems that want to register CPU hotplug callbacks, as well as perform
initialization for the CPUs that are already online, often do it as shown
below:

get_online_cpus();

for_each_online_cpu(cpu)
init_cpu(cpu);

register_cpu_notifier(&foobar_cpu_notifier);

put_online_cpus();

This is wrong, since it is prone to ABBA deadlocks involving the
cpu_add_remove_lock and the cpu_hotplug.lock (when running concurrently
with CPU hotplug operations).

Instead, the correct and race-free way of performing the callback
registration is:

cpu_notifier_register_begin();

for_each_online_cpu(cpu)
init_cpu(cpu);

/* Note the use of the double underscored version of the API */
__register_cpu_notifier(&foobar_cpu_notifier);

cpu_notifier_register_done();

Fix the sysfs code in powerpc by using this latter form of callback
registration.

Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Olof Johansson <olof@lixom.net>
Cc: Wang Dongsheng <dongsheng.wang@freescale.com>
Cc: Ingo Molnar <mingo@kernel.org>
Acked-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
arch/powerpc/kernel/sysfs.c

index 97e1dc91768374e7a7c5b56eb6752b7df5ae05ea..d90d4b7810d69edfa2283367aa7146edbcac8fa0 100644 (file)
@@ -975,7 +975,8 @@ static int __init topology_init(void)
        int cpu;
 
        register_nodes();
-       register_cpu_notifier(&sysfs_cpu_nb);
+
+       cpu_notifier_register_begin();
 
        for_each_possible_cpu(cpu) {
                struct cpu *c = &per_cpu(cpu_devices, cpu);
@@ -999,6 +1000,11 @@ static int __init topology_init(void)
                if (cpu_online(cpu))
                        register_cpu_online(cpu);
        }
+
+       __register_cpu_notifier(&sysfs_cpu_nb);
+
+       cpu_notifier_register_done();
+
 #ifdef CONFIG_PPC64
        sysfs_create_dscr_default();
 #endif /* CONFIG_PPC64 */