aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/msr.c
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2014-03-10 16:36:37 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-20 08:43:42 -0400
commitde82a01befdd33f6a1c050c7f888e2fa9949f48e (patch)
tree91fcec4235e88d6b084ef05598a610af03571872 /arch/x86/kernel/msr.c
parentd1a5511390b0eb242c70ab977abff28644f66a5a (diff)
x86, msr: 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 msr code in x86 by using this latter form of callback registration. Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@kernel.org> 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/msr.c')
-rw-r--r--arch/x86/kernel/msr.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 05266b5aae22..c9603ac80de5 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -259,14 +259,15 @@ static int __init msr_init(void)
259 goto out_chrdev; 259 goto out_chrdev;
260 } 260 }
261 msr_class->devnode = msr_devnode; 261 msr_class->devnode = msr_devnode;
262 get_online_cpus(); 262
263 cpu_notifier_register_begin();
263 for_each_online_cpu(i) { 264 for_each_online_cpu(i) {
264 err = msr_device_create(i); 265 err = msr_device_create(i);
265 if (err != 0) 266 if (err != 0)
266 goto out_class; 267 goto out_class;
267 } 268 }
268 register_hotcpu_notifier(&msr_class_cpu_notifier); 269 __register_hotcpu_notifier(&msr_class_cpu_notifier);
269 put_online_cpus(); 270 cpu_notifier_register_done();
270 271
271 err = 0; 272 err = 0;
272 goto out; 273 goto out;
@@ -275,7 +276,7 @@ out_class:
275 i = 0; 276 i = 0;
276 for_each_online_cpu(i) 277 for_each_online_cpu(i)
277 msr_device_destroy(i); 278 msr_device_destroy(i);
278 put_online_cpus(); 279 cpu_notifier_register_done();
279 class_destroy(msr_class); 280 class_destroy(msr_class);
280out_chrdev: 281out_chrdev:
281 __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); 282 __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
@@ -286,13 +287,14 @@ out:
286static void __exit msr_exit(void) 287static void __exit msr_exit(void)
287{ 288{
288 int cpu = 0; 289 int cpu = 0;
289 get_online_cpus(); 290
291 cpu_notifier_register_begin();
290 for_each_online_cpu(cpu) 292 for_each_online_cpu(cpu)
291 msr_device_destroy(cpu); 293 msr_device_destroy(cpu);
292 class_destroy(msr_class); 294 class_destroy(msr_class);
293 __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr"); 295 __unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
294 unregister_hotcpu_notifier(&msr_class_cpu_notifier); 296 __unregister_hotcpu_notifier(&msr_class_cpu_notifier);
295 put_online_cpus(); 297 cpu_notifier_register_done();
296} 298}
297 299
298module_init(msr_init); 300module_init(msr_init);