aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2014-03-10 16:37:57 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-20 08:43:43 -0400
commit8c60ea146499b9d2a81ceb5e3e0bd215ef0b6287 (patch)
tree1b1135663327d9910f0d83c738a8dc6f6805927a
parent047868ce2952bb6a86ccea3ecc6fd59faa9062a7 (diff)
x86, intel, cacheinfo: 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 intel cacheinfo code in x86 by using this latter form of callback registration. 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>
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 0641113e2965..a952e9c85b6f 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -1225,21 +1225,24 @@ static struct notifier_block cacheinfo_cpu_notifier = {
1225 1225
1226static int __init cache_sysfs_init(void) 1226static int __init cache_sysfs_init(void)
1227{ 1227{
1228 int i; 1228 int i, err = 0;
1229 1229
1230 if (num_cache_leaves == 0) 1230 if (num_cache_leaves == 0)
1231 return 0; 1231 return 0;
1232 1232
1233 cpu_notifier_register_begin();
1233 for_each_online_cpu(i) { 1234 for_each_online_cpu(i) {
1234 int err;
1235 struct device *dev = get_cpu_device(i); 1235 struct device *dev = get_cpu_device(i);
1236 1236
1237 err = cache_add_dev(dev); 1237 err = cache_add_dev(dev);
1238 if (err) 1238 if (err)
1239 return err; 1239 goto out;
1240 } 1240 }
1241 register_hotcpu_notifier(&cacheinfo_cpu_notifier); 1241 __register_hotcpu_notifier(&cacheinfo_cpu_notifier);
1242 return 0; 1242
1243out:
1244 cpu_notifier_register_done();
1245 return err;
1243} 1246}
1244 1247
1245device_initcall(cache_sysfs_init); 1248device_initcall(cache_sysfs_init);