aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/mcheck
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2014-03-10 16:37:04 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-20 08:43:42 -0400
commit82a8f131aadf55ac7fbc8c6f65f34d83101160de (patch)
treeca5ebea7b1e56bf0e43e0d7895534016123c89f6 /arch/x86/kernel/cpu/mcheck
parent2c666adacc9e4b00b918553ca136b8eef0ec3c2c (diff)
x86, mce: Fix CPU hotplug callback registration
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 mce code in x86 by using this latter form of callback registration. Cc: Tony Luck <tony.luck@intel.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@kernel.org> Cc: "H. Peter Anvin" <hpa@zytor.com> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'arch/x86/kernel/cpu/mcheck')
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 4d5419b249da..9b7734b1f975 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -2434,14 +2434,18 @@ static __init int mcheck_init_device(void)
2434 if (err) 2434 if (err)
2435 return err; 2435 return err;
2436 2436
2437 cpu_notifier_register_begin();
2437 for_each_online_cpu(i) { 2438 for_each_online_cpu(i) {
2438 err = mce_device_create(i); 2439 err = mce_device_create(i);
2439 if (err) 2440 if (err) {
2441 cpu_notifier_register_done();
2440 return err; 2442 return err;
2443 }
2441 } 2444 }
2442 2445
2443 register_syscore_ops(&mce_syscore_ops); 2446 register_syscore_ops(&mce_syscore_ops);
2444 register_hotcpu_notifier(&mce_cpu_notifier); 2447 __register_hotcpu_notifier(&mce_cpu_notifier);
2448 cpu_notifier_register_done();
2445 2449
2446 /* register character device /dev/mcelog */ 2450 /* register character device /dev/mcelog */
2447 misc_register(&mce_chrdev_device); 2451 misc_register(&mce_chrdev_device);