From 009f225ef050d231ebb7b87264a21a7daac0f175 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:09:26 +0530 Subject: powercap, intel-rapl: 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-rapl code in the powercap driver by using this latter form of callback registration. But retain the calls to get/put_online_cpus(), since they also protect the function rapl_cleanup_data(). By nesting get/put_online_cpus() *inside* cpu_notifier_register_begin/done(), we avoid the ABBA deadlock possibility mentioned above. Cc: Srinivas Pandruvada Cc: Ingo Molnar Tested-by: Jacob Pan Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/powercap/intel_rapl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 3c6768378a94..d6c74c1b5ea7 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c @@ -1369,6 +1369,9 @@ static int __init rapl_init(void) return -ENODEV; } + + cpu_notifier_register_begin(); + /* prevent CPU hotplug during detection */ get_online_cpus(); ret = rapl_detect_topology(); @@ -1380,20 +1383,23 @@ static int __init rapl_init(void) ret = -ENODEV; goto done; } - register_hotcpu_notifier(&rapl_cpu_notifier); + __register_hotcpu_notifier(&rapl_cpu_notifier); done: put_online_cpus(); + cpu_notifier_register_done(); return ret; } static void __exit rapl_exit(void) { + cpu_notifier_register_begin(); get_online_cpus(); - unregister_hotcpu_notifier(&rapl_cpu_notifier); + __unregister_hotcpu_notifier(&rapl_cpu_notifier); rapl_unregister_powercap(); rapl_cleanup_data(); put_online_cpus(); + cpu_notifier_register_done(); } module_init(rapl_init); -- cgit From bc0003c93f0e68b5383fb36579f7efa267b7dc16 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:09:39 +0530 Subject: scsi, bnx2i: 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 bnx2i code in scsi by using this latter form of callback registration. Cc: Eddie Wai Cc: "James E.J. Bottomley" Cc: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/scsi/bnx2i/bnx2i_init.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 34c294b42c84..80c03b452d61 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -537,11 +537,15 @@ static int __init bnx2i_mod_init(void) p->iothread = NULL; } + cpu_notifier_register_begin(); + for_each_online_cpu(cpu) bnx2i_percpu_thread_create(cpu); /* Initialize per CPU interrupt thread */ - register_hotcpu_notifier(&bnx2i_cpu_notifier); + __register_hotcpu_notifier(&bnx2i_cpu_notifier); + + cpu_notifier_register_done(); return 0; @@ -581,11 +585,15 @@ static void __exit bnx2i_mod_exit(void) } mutex_unlock(&bnx2i_dev_lock); - unregister_hotcpu_notifier(&bnx2i_cpu_notifier); + cpu_notifier_register_begin(); for_each_online_cpu(cpu) bnx2i_percpu_thread_destroy(cpu); + __unregister_hotcpu_notifier(&bnx2i_cpu_notifier); + + cpu_notifier_register_done(); + iscsi_unregister_transport(&bnx2i_iscsi_transport); cnic_unregister_driver(CNIC_ULP_ISCSI); } -- cgit From 7229b6d0b2a9e62d5eb4886dcd0137664c735718 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:09:45 +0530 Subject: scsi, bnx2fc: 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 bnx2fc code in scsi by using this latter form of callback registration. Cc: Eddie Wai Cc: "James E.J. Bottomley" Cc: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 9b948505d118..c4ec235baead 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -2586,12 +2586,16 @@ static int __init bnx2fc_mod_init(void) spin_lock_init(&p->fp_work_lock); } + cpu_notifier_register_begin(); + for_each_online_cpu(cpu) { bnx2fc_percpu_thread_create(cpu); } /* Initialize per CPU interrupt thread */ - register_hotcpu_notifier(&bnx2fc_cpu_notifier); + __register_hotcpu_notifier(&bnx2fc_cpu_notifier); + + cpu_notifier_register_done(); cnic_register_driver(CNIC_ULP_FCOE, &bnx2fc_cnic_cb); @@ -2656,13 +2660,17 @@ static void __exit bnx2fc_mod_exit(void) if (l2_thread) kthread_stop(l2_thread); - unregister_hotcpu_notifier(&bnx2fc_cpu_notifier); + cpu_notifier_register_begin(); /* Destroy per cpu threads */ for_each_online_cpu(cpu) { bnx2fc_percpu_thread_destroy(cpu); } + __unregister_hotcpu_notifier(&bnx2fc_cpu_notifier); + + cpu_notifier_register_done(); + destroy_workqueue(bnx2fc_wq); /* * detach from scsi transport -- cgit From cd45ae38035d1b7f98dd92429b59bbc8ba9443e9 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:09:52 +0530 Subject: scsi, fcoe: 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 fcoe code in scsi by using this latter form of callback registration. Cc: Robert Love Cc: "James E.J. Bottomley" Cc: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/scsi/fcoe/fcoe.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index f3170008ae71..d5e105b173f0 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2633,14 +2633,18 @@ static int __init fcoe_init(void) skb_queue_head_init(&p->fcoe_rx_list); } + cpu_notifier_register_begin(); + for_each_online_cpu(cpu) fcoe_percpu_thread_create(cpu); /* Initialize per CPU interrupt thread */ - rc = register_hotcpu_notifier(&fcoe_cpu_notifier); + rc = __register_hotcpu_notifier(&fcoe_cpu_notifier); if (rc) goto out_free; + cpu_notifier_register_done(); + /* Setup link change notification */ fcoe_dev_setup(); @@ -2655,6 +2659,9 @@ out_free: for_each_online_cpu(cpu) { fcoe_percpu_thread_destroy(cpu); } + + cpu_notifier_register_done(); + mutex_unlock(&fcoe_config_mutex); destroy_workqueue(fcoe_wq); return rc; @@ -2687,11 +2694,15 @@ static void __exit fcoe_exit(void) } rtnl_unlock(); - unregister_hotcpu_notifier(&fcoe_cpu_notifier); + cpu_notifier_register_begin(); for_each_online_cpu(cpu) fcoe_percpu_thread_destroy(cpu); + __unregister_hotcpu_notifier(&fcoe_cpu_notifier); + + cpu_notifier_register_done(); + mutex_unlock(&fcoe_config_mutex); /* -- cgit From 0197fbd212461f25666272b9e4654f2ccd94cff8 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:10:06 +0530 Subject: acpi-cpufreq: 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 acpi-cpufreq code by using this latter form of callback registration. Cc: Ingo Molnar Acked-by: Viresh Kumar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/acpi-cpufreq.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 18448a7e9f86..245ae078e68e 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -907,15 +907,16 @@ static void __init acpi_cpufreq_boost_init(void) acpi_cpufreq_driver.boost_supported = true; acpi_cpufreq_driver.boost_enabled = boost_state(0); - get_online_cpus(); + + cpu_notifier_register_begin(); /* Force all MSRs to the same value */ boost_set_msrs(acpi_cpufreq_driver.boost_enabled, cpu_online_mask); - register_cpu_notifier(&boost_nb); + __register_cpu_notifier(&boost_nb); - put_online_cpus(); + cpu_notifier_register_done(); } } -- cgit From e12b711196a158a475350ee67876a1e9e2601661 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:10:12 +0530 Subject: drivers/base/topology.c: 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 topology code by using this latter form of callback registration. Cc: Ingo Molnar Acked-by: Greg Kroah-Hartman Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/base/topology.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 94ffee378f10..a738d1069d6b 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -161,16 +161,20 @@ static int topology_cpu_callback(struct notifier_block *nfb, static int topology_sysfs_init(void) { int cpu; - int rc; + int rc = 0; + + cpu_notifier_register_begin(); for_each_online_cpu(cpu) { rc = topology_add_dev(cpu); if (rc) - return rc; + goto out; } - hotcpu_notifier(topology_cpu_callback, 0); + __hotcpu_notifier(topology_cpu_callback, 0); - return 0; +out: + cpu_notifier_register_done(); + return rc; } device_initcall(topology_sysfs_init); -- cgit From 8daa127f4e857427c66f365f650dda90f459aa54 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:10:23 +0530 Subject: clocksource, dummy-timer: 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 clocksource dummy-timer code by using this latter form of callback registration. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/clocksource/dummy_timer.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c index b3eb582d6a6f..ad3572541728 100644 --- a/drivers/clocksource/dummy_timer.c +++ b/drivers/clocksource/dummy_timer.c @@ -56,14 +56,19 @@ static struct notifier_block dummy_timer_cpu_nb = { static int __init dummy_timer_register(void) { - int err = register_cpu_notifier(&dummy_timer_cpu_nb); + int err = 0; + + cpu_notifier_register_begin(); + err = __register_cpu_notifier(&dummy_timer_cpu_nb); if (err) - return err; + goto out; /* We won't get a call on the boot CPU, so register immediately */ if (num_possible_cpus() > 1) dummy_timer_setup(); - return 0; +out: + cpu_notifier_register_done(); + return err; } early_initcall(dummy_timer_register); -- cgit From 07494d547e92bde6857522d2a92ff70896aecadb Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:10:30 +0530 Subject: intel-idle: 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-idle code by using this latter form of callback registration. Cc: Len Brown Cc: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/idle/intel_idle.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 8e1939f564f4..51493ed4643b 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -681,14 +681,19 @@ static int __init intel_idle_init(void) if (intel_idle_cpuidle_devices == NULL) return -ENOMEM; + cpu_notifier_register_begin(); + for_each_online_cpu(i) { retval = intel_idle_cpu_init(i); if (retval) { + cpu_notifier_register_done(); cpuidle_unregister_driver(&intel_idle_driver); return retval; } } - register_cpu_notifier(&cpu_hotplug_notifier); + __register_cpu_notifier(&cpu_hotplug_notifier); + + cpu_notifier_register_done(); return 0; } @@ -698,10 +703,13 @@ static void __exit intel_idle_exit(void) intel_idle_cpuidle_devices_uninit(); cpuidle_unregister_driver(&intel_idle_driver); + cpu_notifier_register_begin(); if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) on_each_cpu(__setup_broadcast_timer, (void *)false, 1); - unregister_cpu_notifier(&cpu_hotplug_notifier); + __unregister_cpu_notifier(&cpu_hotplug_notifier); + + cpu_notifier_register_done(); return; } -- cgit From 180d86463257812dc17e5df912f3bddcc96abb00 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:10:36 +0530 Subject: oprofile, nmi-timer: 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 nmi-timer code in oprofile by using this latter form of callback registration. Cc: Robert Richter Cc: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/oprofile/nmi_timer_int.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/oprofile/nmi_timer_int.c b/drivers/oprofile/nmi_timer_int.c index 76f1c9357f39..9559829fb234 100644 --- a/drivers/oprofile/nmi_timer_int.c +++ b/drivers/oprofile/nmi_timer_int.c @@ -108,8 +108,8 @@ static void nmi_timer_shutdown(void) struct perf_event *event; int cpu; - get_online_cpus(); - unregister_cpu_notifier(&nmi_timer_cpu_nb); + cpu_notifier_register_begin(); + __unregister_cpu_notifier(&nmi_timer_cpu_nb); for_each_possible_cpu(cpu) { event = per_cpu(nmi_timer_events, cpu); if (!event) @@ -119,7 +119,7 @@ static void nmi_timer_shutdown(void) perf_event_release_kernel(event); } - put_online_cpus(); + cpu_notifier_register_done(); } static int nmi_timer_setup(void) @@ -132,20 +132,23 @@ static int nmi_timer_setup(void) do_div(period, HZ); nmi_timer_attr.sample_period = period; - get_online_cpus(); - err = register_cpu_notifier(&nmi_timer_cpu_nb); + cpu_notifier_register_begin(); + err = __register_cpu_notifier(&nmi_timer_cpu_nb); if (err) goto out; + /* can't attach events to offline cpus: */ for_each_online_cpu(cpu) { err = nmi_timer_start_cpu(cpu); - if (err) - break; + if (err) { + cpu_notifier_register_done(); + nmi_timer_shutdown(); + return err; + } } - if (err) - nmi_timer_shutdown(); + out: - put_online_cpus(); + cpu_notifier_register_done(); return err; } -- cgit From 99c3bf361a4afd2ad331e767b3e5e6fa3488a096 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:10:43 +0530 Subject: octeon, watchdog: 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 watchdog code in octeon by using this latter form of callback registration. Cc: Wim Van Sebroeck Cc: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/watchdog/octeon-wdt-main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index 461208831428..4baf2d788920 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c @@ -708,10 +708,13 @@ static int __init octeon_wdt_init(void) cpumask_clear(&irq_enabled_cpus); + cpu_notifier_register_begin(); for_each_online_cpu(cpu) octeon_wdt_setup_interrupt(cpu); - register_hotcpu_notifier(&octeon_wdt_cpu_notifier); + __register_hotcpu_notifier(&octeon_wdt_cpu_notifier); + cpu_notifier_register_done(); + out: return ret; } @@ -725,7 +728,8 @@ static void __exit octeon_wdt_cleanup(void) misc_deregister(&octeon_wdt_miscdev); - unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier); + cpu_notifier_register_begin(); + __unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier); for_each_online_cpu(cpu) { int core = cpu2core(cpu); @@ -734,6 +738,9 @@ static void __exit octeon_wdt_cleanup(void) /* Free the interrupt handler */ free_irq(OCTEON_IRQ_WDOG0 + core, octeon_wdt_poke_irq); } + + cpu_notifier_register_done(); + /* * Disable the boot-bus memory, the code it points to is soon * to go missing. -- cgit From cf0485a2ac70acb1bc83f6310a7ebef3070f0333 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:10:54 +0530 Subject: thermal, x86-pkg-temp: 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 thermal x86-pkg-temp code by using this latter form of callback registration. Cc: Zhang Rui Cc: Eduardo Valentin Cc: Ingo Molnar Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/thermal/x86_pkg_temp_thermal.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index 081fd7e6a9f0..9ea3d9d49ffc 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -590,12 +590,12 @@ static int __init pkg_temp_thermal_init(void) platform_thermal_package_rate_control = pkg_temp_thermal_platform_thermal_rate_control; - get_online_cpus(); + cpu_notifier_register_begin(); for_each_online_cpu(i) if (get_core_online(i)) goto err_ret; - register_hotcpu_notifier(&pkg_temp_thermal_notifier); - put_online_cpus(); + __register_hotcpu_notifier(&pkg_temp_thermal_notifier); + cpu_notifier_register_done(); pkg_temp_debugfs_init(); /* Don't care if fails */ @@ -604,7 +604,7 @@ static int __init pkg_temp_thermal_init(void) err_ret: for_each_online_cpu(i) put_core_offline(i); - put_online_cpus(); + cpu_notifier_register_done(); kfree(pkg_work_scheduled); platform_thermal_package_notify = NULL; platform_thermal_package_rate_control = NULL; @@ -617,8 +617,8 @@ static void __exit pkg_temp_thermal_exit(void) struct phy_dev_entry *phdev, *n; int i; - get_online_cpus(); - unregister_hotcpu_notifier(&pkg_temp_thermal_notifier); + cpu_notifier_register_begin(); + __unregister_hotcpu_notifier(&pkg_temp_thermal_notifier); mutex_lock(&phy_dev_list_mutex); list_for_each_entry_safe(phdev, n, &phy_dev_list, list) { /* Retore old MSR value for package thermal interrupt */ @@ -636,7 +636,7 @@ static void __exit pkg_temp_thermal_exit(void) for_each_online_cpu(i) cancel_delayed_work_sync( &per_cpu(pkg_temp_thermal_threshold_work, i)); - put_online_cpus(); + cpu_notifier_register_done(); kfree(pkg_work_scheduled); -- cgit From 3289705fe2b429569f37730ecf660719b8924420 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:11:11 +0530 Subject: hwmon, coretemp: 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 hwmon coretemp code by using this latter form of callback registration. Cc: Fenghua Yu Cc: Jean Delvare Cc: Ingo Molnar Acked-by: Guenter Roeck Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/hwmon/coretemp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index bbb0b0d463f7..746a6ad8525f 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -849,20 +849,20 @@ static int __init coretemp_init(void) if (err) goto exit; - get_online_cpus(); + cpu_notifier_register_begin(); for_each_online_cpu(i) get_core_online(i); #ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { - put_online_cpus(); + cpu_notifier_register_done(); err = -ENODEV; goto exit_driver_unreg; } #endif - register_hotcpu_notifier(&coretemp_cpu_notifier); - put_online_cpus(); + __register_hotcpu_notifier(&coretemp_cpu_notifier); + cpu_notifier_register_done(); return 0; #ifndef CONFIG_HOTPLUG_CPU @@ -877,8 +877,8 @@ static void __exit coretemp_exit(void) { struct pdev_entry *p, *n; - get_online_cpus(); - unregister_hotcpu_notifier(&coretemp_cpu_notifier); + cpu_notifier_register_begin(); + __unregister_hotcpu_notifier(&coretemp_cpu_notifier); mutex_lock(&pdev_list_mutex); list_for_each_entry_safe(p, n, &pdev_list, list) { platform_device_unregister(p->pdev); @@ -886,7 +886,7 @@ static void __exit coretemp_exit(void) kfree(p); } mutex_unlock(&pdev_list_mutex); - put_online_cpus(); + cpu_notifier_register_done(); platform_driver_unregister(&coretemp_driver); } -- cgit From 2480b6a3e5e80d778455f8138ae6d6efb568cd59 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:11:33 +0530 Subject: hwmon, via-cputemp: 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 hwmon via-cputemp code by using this latter form of callback registration. Cc: Jean Delvare Cc: Ingo Molnar Acked-by: Guenter Roeck Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/hwmon/via-cputemp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 38944e94f65f..8df43c51de2c 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -319,7 +319,7 @@ static int __init via_cputemp_init(void) if (err) goto exit; - get_online_cpus(); + cpu_notifier_register_begin(); for_each_online_cpu(i) { struct cpuinfo_x86 *c = &cpu_data(i); @@ -339,14 +339,14 @@ static int __init via_cputemp_init(void) #ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { - put_online_cpus(); + cpu_notifier_register_done(); err = -ENODEV; goto exit_driver_unreg; } #endif - register_hotcpu_notifier(&via_cputemp_cpu_notifier); - put_online_cpus(); + __register_hotcpu_notifier(&via_cputemp_cpu_notifier); + cpu_notifier_register_done(); return 0; #ifndef CONFIG_HOTPLUG_CPU @@ -361,8 +361,8 @@ static void __exit via_cputemp_exit(void) { struct pdev_entry *p, *n; - get_online_cpus(); - unregister_hotcpu_notifier(&via_cputemp_cpu_notifier); + cpu_notifier_register_begin(); + __unregister_hotcpu_notifier(&via_cputemp_cpu_notifier); mutex_lock(&pdev_list_mutex); list_for_each_entry_safe(p, n, &pdev_list, list) { platform_device_unregister(p->pdev); @@ -370,7 +370,7 @@ static void __exit via_cputemp_exit(void) kfree(p); } mutex_unlock(&pdev_list_mutex); - put_online_cpus(); + cpu_notifier_register_done(); platform_driver_unregister(&via_cputemp_driver); } -- cgit From 43ea9536499e80d858e26cecb7abcc893f86d222 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 11 Mar 2014 02:11:45 +0530 Subject: xen, balloon: 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). The xen balloon driver doesn't take get/put_online_cpus() around this code, but that is also buggy, since it can miss CPU hotplug events in between the initialization and callback registration: for_each_online_cpu(cpu) init_cpu(cpu); ^ | Race window; Can miss CPU hotplug events here. v register_cpu_notifier(&foobar_cpu_notifier); Interestingly, the balloon code in xen can simply be reorganized as shown below, to have a race-free method to register hotplug callbacks, without even taking get/put_online_cpus(). This is because the initialization performed for already online CPUs is exactly the same as that performed for CPUs that come online later. Moreover, the code has checks in place to avoid double initialization. register_cpu_notifier(&foobar_cpu_notifier); get_online_cpus(); for_each_online_cpu(cpu) init_cpu(cpu); put_online_cpus(); A hotplug operation that occurs between registering the notifier and calling get_online_cpus(), won't disrupt anything, because the code takes care to perform the memory allocations only once. So reorganize the balloon code in xen this way to fix the issues with CPU hotplug callback registration. Cc: Konrad Rzeszutek Wilk Cc: David Vrabel Cc: Ingo Molnar Reviewed-by: Boris Ostrovsky Signed-off-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/xen/balloon.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 37d06ea624aa..dd7954922942 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -592,19 +592,29 @@ static void __init balloon_add_region(unsigned long start_pfn, } } +static int alloc_balloon_scratch_page(int cpu) +{ + if (per_cpu(balloon_scratch_page, cpu) != NULL) + return 0; + + per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL); + if (per_cpu(balloon_scratch_page, cpu) == NULL) { + pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu); + return -ENOMEM; + } + + return 0; +} + + static int balloon_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int cpu = (long)hcpu; switch (action) { case CPU_UP_PREPARE: - if (per_cpu(balloon_scratch_page, cpu) != NULL) - break; - per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL); - if (per_cpu(balloon_scratch_page, cpu) == NULL) { - pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu); + if (alloc_balloon_scratch_page(cpu)) return NOTIFY_BAD; - } break; default: break; @@ -624,15 +634,17 @@ static int __init balloon_init(void) return -ENODEV; if (!xen_feature(XENFEAT_auto_translated_physmap)) { - for_each_online_cpu(cpu) - { - per_cpu(balloon_scratch_page, cpu) = alloc_page(GFP_KERNEL); - if (per_cpu(balloon_scratch_page, cpu) == NULL) { - pr_warn("Failed to allocate balloon_scratch_page for cpu %d\n", cpu); + register_cpu_notifier(&balloon_cpu_notifier); + + get_online_cpus(); + for_each_online_cpu(cpu) { + if (alloc_balloon_scratch_page(cpu)) { + put_online_cpus(); + unregister_cpu_notifier(&balloon_cpu_notifier); return -ENOMEM; } } - register_cpu_notifier(&balloon_cpu_notifier); + put_online_cpus(); } pr_info("Initialising balloon driver\n"); -- cgit