Skip to content

Commit

Permalink
Merge tag 'cpu-hotplug-3.15-rc1' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/rafael/linux-pm

Pull CPU hotplug notifiers registration fixes from Rafael Wysocki:
 "The purpose of this single series of commits from Srivatsa S Bhat
  (with a small piece from Gautham R Shenoy) touching multiple
  subsystems that use CPU hotplug notifiers is to provide a way to
  register them that will not lead to deadlocks with CPU online/offline
  operations as described in the changelog of commit 93ae4f9 ("CPU
  hotplug: Provide lockless versions of callback registration
  functions").

  The first three commits in the series introduce the API and document
  it and the rest simply goes through the users of CPU hotplug notifiers
  and converts them to using the new method"

* tag 'cpu-hotplug-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (52 commits)
  net/iucv/iucv.c: Fix CPU hotplug callback registration
  net/core/flow.c: Fix CPU hotplug callback registration
  mm, zswap: Fix CPU hotplug callback registration
  mm, vmstat: Fix CPU hotplug callback registration
  profile: Fix CPU hotplug callback registration
  trace, ring-buffer: Fix CPU hotplug callback registration
  xen, balloon: Fix CPU hotplug callback registration
  hwmon, via-cputemp: Fix CPU hotplug callback registration
  hwmon, coretemp: Fix CPU hotplug callback registration
  thermal, x86-pkg-temp: Fix CPU hotplug callback registration
  octeon, watchdog: Fix CPU hotplug callback registration
  oprofile, nmi-timer: Fix CPU hotplug callback registration
  intel-idle: Fix CPU hotplug callback registration
  clocksource, dummy-timer: Fix CPU hotplug callback registration
  drivers/base/topology.c: Fix CPU hotplug callback registration
  acpi-cpufreq: Fix CPU hotplug callback registration
  zsmalloc: Fix CPU hotplug callback registration
  scsi, fcoe: Fix CPU hotplug callback registration
  scsi, bnx2fc: Fix CPU hotplug callback registration
  scsi, bnx2i: Fix CPU hotplug callback registration
  ...
  • Loading branch information
torvalds committed Apr 7, 2014
2 parents b8780c3 + a0e247a commit 467a9e1
Show file tree
Hide file tree
Showing 51 changed files with 550 additions and 226 deletions.
45 changes: 45 additions & 0 deletions Documentation/cpu-hotplug.txt
Original file line number Diff line number Diff line change
Expand Up @@ -312,12 +312,57 @@ things will happen if a notifier in path sent a BAD notify code.
Q: I don't see my action being called for all CPUs already up and running?
A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined.
If you need to perform some action for each cpu already in the system, then
do this:

for_each_online_cpu(i) {
foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i);
foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i);
}

However, if you want to register a hotplug callback, as well as perform
some initialization for CPUs that are already online, then do this:

Version 1: (Correct)
---------

cpu_notifier_register_begin();

for_each_online_cpu(i) {
foobar_cpu_callback(&foobar_cpu_notifier,
CPU_UP_PREPARE, i);
foobar_cpu_callback(&foobar_cpu_notifier,
CPU_ONLINE, i);
}

/* Note the use of the double underscored version of the API */
__register_cpu_notifier(&foobar_cpu_notifier);

cpu_notifier_register_done();

Note that the following code is *NOT* the right way to achieve this,
because it is prone to an ABBA deadlock between the cpu_add_remove_lock
and the cpu_hotplug.lock.

Version 2: (Wrong!)
---------

get_online_cpus();

for_each_online_cpu(i) {
foobar_cpu_callback(&foobar_cpu_notifier,
CPU_UP_PREPARE, i);
foobar_cpu_callback(&foobar_cpu_notifier,
CPU_ONLINE, i);
}

register_cpu_notifier(&foobar_cpu_notifier);

put_online_cpus();

So always use the first version shown above when you want to register
callbacks as well as initialize the already online CPUs.


Q: If i would like to develop cpu hotplug support for a new architecture,
what do i need at a minimum?
A: The following are what is required for CPU hotplug infrastructure to work
Expand Down
8 changes: 7 additions & 1 deletion arch/arm/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,8 @@ static int __init arch_hw_breakpoint_init(void)
core_num_brps = get_num_brps();
core_num_wrps = get_num_wrps();

cpu_notifier_register_begin();

/*
* We need to tread carefully here because DBGSWENABLE may be
* driven low on this core and there isn't an architected way to
Expand All @@ -1089,6 +1091,7 @@ static int __init arch_hw_breakpoint_init(void)
if (!cpumask_empty(&debug_err_mask)) {
core_num_brps = 0;
core_num_wrps = 0;
cpu_notifier_register_done();
return 0;
}

Expand All @@ -1108,7 +1111,10 @@ static int __init arch_hw_breakpoint_init(void)
TRAP_HWBKPT, "breakpoint debug exception");

/* Register hotplug and PM notifiers. */
register_cpu_notifier(&dbg_reset_nb);
__register_cpu_notifier(&dbg_reset_nb);

cpu_notifier_register_done();

pm_init();
return 0;
}
Expand Down
7 changes: 6 additions & 1 deletion arch/arm/kvm/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,21 +1051,26 @@ int kvm_arch_init(void *opaque)
}
}

cpu_notifier_register_begin();

err = init_hyp_mode();
if (err)
goto out_err;

err = register_cpu_notifier(&hyp_init_cpu_nb);
err = __register_cpu_notifier(&hyp_init_cpu_nb);
if (err) {
kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
goto out_err;
}

cpu_notifier_register_done();

hyp_cpu_pm_init();

kvm_coproc_table_init();
return 0;
out_err:
cpu_notifier_register_done();
return err;
}

Expand Down
6 changes: 5 additions & 1 deletion arch/arm64/kernel/debug-monitors.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,17 @@ static struct notifier_block os_lock_nb = {

static int debug_monitors_init(void)
{
cpu_notifier_register_begin();

/* Clear the OS lock. */
on_each_cpu(clear_os_lock, NULL, 1);
isb();
local_dbg_enable();

/* Register hotplug handler. */
register_cpu_notifier(&os_lock_nb);
__register_cpu_notifier(&os_lock_nb);

cpu_notifier_register_done();
return 0;
}
postcore_initcall(debug_monitors_init);
Expand Down
7 changes: 6 additions & 1 deletion arch/arm64/kernel/hw_breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,8 @@ static int __init arch_hw_breakpoint_init(void)
pr_info("found %d breakpoint and %d watchpoint registers.\n",
core_num_brps, core_num_wrps);

cpu_notifier_register_begin();

/*
* Reset the breakpoint resources. We assume that a halting
* debugger will leave the world in a nice state for us.
Expand All @@ -927,7 +929,10 @@ static int __init arch_hw_breakpoint_init(void)
TRAP_HWBKPT, "hw-watchpoint handler");

/* Register hotplug notifier. */
register_cpu_notifier(&hw_breakpoint_reset_nb);
__register_cpu_notifier(&hw_breakpoint_reset_nb);

cpu_notifier_register_done();

/* Register cpu_suspend hw breakpoint restore hook */
cpu_suspend_set_dbg_restorer(hw_breakpoint_reset);

Expand Down
15 changes: 13 additions & 2 deletions arch/ia64/kernel/err_inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,17 @@ err_inject_init(void)
#ifdef ERR_INJ_DEBUG
printk(KERN_INFO "Enter error injection driver.\n");
#endif

cpu_notifier_register_begin();

for_each_online_cpu(i) {
err_inject_cpu_callback(&err_inject_cpu_notifier, CPU_ONLINE,
(void *)(long)i);
}

register_hotcpu_notifier(&err_inject_cpu_notifier);
__register_hotcpu_notifier(&err_inject_cpu_notifier);

cpu_notifier_register_done();

return 0;
}
Expand All @@ -288,11 +293,17 @@ err_inject_exit(void)
#ifdef ERR_INJ_DEBUG
printk(KERN_INFO "Exit error injection driver.\n");
#endif

cpu_notifier_register_begin();

for_each_online_cpu(i) {
sys_dev = get_cpu_device(i);
sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
}
unregister_hotcpu_notifier(&err_inject_cpu_notifier);

__unregister_hotcpu_notifier(&err_inject_cpu_notifier);

cpu_notifier_register_done();
}

module_init(err_inject_init);
Expand Down
6 changes: 5 additions & 1 deletion arch/ia64/kernel/palinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -996,13 +996,17 @@ palinfo_init(void)
if (!palinfo_dir)
return -ENOMEM;

cpu_notifier_register_begin();

/* Create palinfo dirs in /proc for all online cpus */
for_each_online_cpu(i) {
create_palinfo_proc_entries(i);
}

/* Register for future delivery via notify registration */
register_hotcpu_notifier(&palinfo_cpu_notifier);
__register_hotcpu_notifier(&palinfo_cpu_notifier);

cpu_notifier_register_done();

return 0;
}
Expand Down
6 changes: 5 additions & 1 deletion arch/ia64/kernel/salinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ salinfo_init(void)
(void *)salinfo_entries[i].feature);
}

cpu_notifier_register_begin();

for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
data = salinfo_data + i;
data->type = i;
Expand Down Expand Up @@ -669,7 +671,9 @@ salinfo_init(void)
salinfo_timer.function = &salinfo_timeout;
add_timer(&salinfo_timer);

register_hotcpu_notifier(&salinfo_cpu_notifier);
__register_hotcpu_notifier(&salinfo_cpu_notifier);

cpu_notifier_register_done();

return 0;
}
Expand Down
6 changes: 5 additions & 1 deletion arch/ia64/kernel/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,12 +454,16 @@ static int __init cache_sysfs_init(void)
{
int i;

cpu_notifier_register_begin();

for_each_online_cpu(i) {
struct device *sys_dev = get_cpu_device((unsigned int)i);
cache_add_dev(sys_dev);
}

register_hotcpu_notifier(&cache_cpu_notifier);
__register_hotcpu_notifier(&cache_cpu_notifier);

cpu_notifier_register_done();

return 0;
}
Expand Down
8 changes: 7 additions & 1 deletion arch/powerpc/kernel/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,8 @@ static int __init topology_init(void)
int cpu;

register_nodes();
register_cpu_notifier(&sysfs_cpu_nb);

cpu_notifier_register_begin();

for_each_possible_cpu(cpu) {
struct cpu *c = &per_cpu(cpu_devices, cpu);
Expand All @@ -999,6 +1000,11 @@ static int __init topology_init(void)
if (cpu_online(cpu))
register_cpu_online(cpu);
}

__register_cpu_notifier(&sysfs_cpu_nb);

cpu_notifier_register_done();

#ifdef CONFIG_PPC64
sysfs_create_dscr_default();
#endif /* CONFIG_PPC64 */
Expand Down
5 changes: 4 additions & 1 deletion arch/s390/kernel/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,9 +378,12 @@ static int __init cache_init(void)
if (!test_facility(34))
return 0;
cache_build_info();

cpu_notifier_register_begin();
for_each_online_cpu(cpu)
cache_add_cpu(cpu);
hotcpu_notifier(cache_hotplug, 0);
__hotcpu_notifier(cache_hotplug, 0);
cpu_notifier_register_done();
return 0;
}
device_initcall(cache_init);
13 changes: 9 additions & 4 deletions arch/s390/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,19 +1057,24 @@ static DEVICE_ATTR(rescan, 0200, NULL, rescan_store);

static int __init s390_smp_init(void)
{
int cpu, rc;
int cpu, rc = 0;

hotcpu_notifier(smp_cpu_notify, 0);
#ifdef CONFIG_HOTPLUG_CPU
rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan);
if (rc)
return rc;
#endif
cpu_notifier_register_begin();
for_each_present_cpu(cpu) {
rc = smp_add_present_cpu(cpu);
if (rc)
return rc;
goto out;
}
return 0;

__hotcpu_notifier(smp_cpu_notify, 0);

out:
cpu_notifier_register_done();
return rc;
}
subsys_initcall(s390_smp_init);
6 changes: 5 additions & 1 deletion arch/sparc/kernel/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ static int __init topology_init(void)

check_mmu_stats();

register_cpu_notifier(&sysfs_cpu_nb);
cpu_notifier_register_begin();

for_each_possible_cpu(cpu) {
struct cpu *c = &per_cpu(cpu_devices, cpu);
Expand All @@ -310,6 +310,10 @@ static int __init topology_init(void)
register_cpu_online(cpu);
}

__register_cpu_notifier(&sysfs_cpu_nb);

cpu_notifier_register_done();

return 0;
}

Expand Down
13 changes: 8 additions & 5 deletions arch/x86/kernel/cpu/intel_cacheinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -1225,21 +1225,24 @@ static struct notifier_block cacheinfo_cpu_notifier = {

static int __init cache_sysfs_init(void)
{
int i;
int i, err = 0;

if (num_cache_leaves == 0)
return 0;

cpu_notifier_register_begin();
for_each_online_cpu(i) {
int err;
struct device *dev = get_cpu_device(i);

err = cache_add_dev(dev);
if (err)
return err;
goto out;
}
register_hotcpu_notifier(&cacheinfo_cpu_notifier);
return 0;
__register_hotcpu_notifier(&cacheinfo_cpu_notifier);

out:
cpu_notifier_register_done();
return err;
}

device_initcall(cache_sysfs_init);
Expand Down
8 changes: 6 additions & 2 deletions arch/x86/kernel/cpu/mcheck/mce.c
Original file line number Diff line number Diff line change
Expand Up @@ -2434,14 +2434,18 @@ static __init int mcheck_init_device(void)
if (err)
return err;

cpu_notifier_register_begin();
for_each_online_cpu(i) {
err = mce_device_create(i);
if (err)
if (err) {
cpu_notifier_register_done();
return err;
}
}

register_syscore_ops(&mce_syscore_ops);
register_hotcpu_notifier(&mce_cpu_notifier);
__register_hotcpu_notifier(&mce_cpu_notifier);
cpu_notifier_register_done();

/* register character device /dev/mcelog */
misc_register(&mce_chrdev_device);
Expand Down
Loading

0 comments on commit 467a9e1

Please sign in to comment.