Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 467a9e16 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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 93ae4f97 ("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
  ...
parents b8780c36 a0e247a8
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -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
+7 −1
Original line number Diff line number Diff line
@@ -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
@@ -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;
	}

@@ -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;
}
+6 −1
Original line number Diff line number Diff line
@@ -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;
}

+5 −1
Original line number Diff line number Diff line
@@ -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);
+6 −1
Original line number Diff line number Diff line
@@ -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.
@@ -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);

Loading