aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2014-03-10 16:38:29 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-20 08:43:43 -0400
commita8c17c2951f3e198982dd2416b068183fc9fcc7e (patch)
tree17e5a4bca9b3413dc68978ba5c81d6ac9eaac792 /arch/x86
parentfd537e56f65c61bb4cece99ac3a1a1bef6676df9 (diff)
x86, amd, uncore: 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 amd-uncore code in x86 by using this latter form of callback registration. Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Cc: Thomas Gleixner <tglx@linutronix.de> 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')
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd_uncore.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_amd_uncore.c b/arch/x86/kernel/cpu/perf_event_amd_uncore.c
index 754291adec33..3bbdf4cd38b9 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_uncore.c
@@ -531,15 +531,16 @@ static int __init amd_uncore_init(void)
531 if (ret) 531 if (ret)
532 return -ENODEV; 532 return -ENODEV;
533 533
534 get_online_cpus(); 534 cpu_notifier_register_begin();
535
535 /* init cpus already online before registering for hotplug notifier */ 536 /* init cpus already online before registering for hotplug notifier */
536 for_each_online_cpu(cpu) { 537 for_each_online_cpu(cpu) {
537 amd_uncore_cpu_up_prepare(cpu); 538 amd_uncore_cpu_up_prepare(cpu);
538 smp_call_function_single(cpu, init_cpu_already_online, NULL, 1); 539 smp_call_function_single(cpu, init_cpu_already_online, NULL, 1);
539 } 540 }
540 541
541 register_cpu_notifier(&amd_uncore_cpu_notifier_block); 542 __register_cpu_notifier(&amd_uncore_cpu_notifier_block);
542 put_online_cpus(); 543 cpu_notifier_register_done();
543 544
544 return 0; 545 return 0;
545} 546}