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

Commit 4baa0afc authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

cpu/hotplug: Convert the hotplugged cpu work to a state machine



Move the functions which need to run on the hotplugged processor into
a state machine array and let the code iterate through these functions.

In a later state, this will grow synchronization points between the
control processor and the hotplugged processor, so we can move the
various architecture implementations of the synchronizations to the
core.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Rik van Riel <riel@redhat.com>
Cc: Rafael Wysocki <rafael.j.wysocki@intel.com>
Cc: "Srivatsa S. Bhat" <srivatsa@mit.edu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Sebastian Siewior <bigeasy@linutronix.de>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul Turner <pjt@google.com>
Link: http://lkml.kernel.org/r/20160226182340.770651526@linutronix.de


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent cff7d378
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -6,6 +6,10 @@ enum cpuhp_state {
	CPUHP_CREATE_THREADS,
	CPUHP_NOTIFY_PREPARE,
	CPUHP_BRINGUP_CPU,
	CPUHP_AP_OFFLINE,
	CPUHP_AP_NOTIFY_STARTING,
	CPUHP_AP_ONLINE,
	CPUHP_TEARDOWN_CPU,
	CPUHP_NOTIFY_ONLINE,
	CPUHP_ONLINE,
};
+66 −15
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ struct cpuhp_step {
};

static struct cpuhp_step cpuhp_bp_states[];
static struct cpuhp_step cpuhp_ap_states[];

/**
 * cpuhp_invoke_callback _ Invoke the callbacks for a given state
@@ -304,6 +305,12 @@ static int notify_online(unsigned int cpu)
	return 0;
}

static int notify_starting(unsigned int cpu)
{
	cpu_notify(CPU_STARTING, cpu);
	return 0;
}

static int bringup_cpu(unsigned int cpu)
{
	struct task_struct *idle = idle_thread_get(cpu);
@@ -421,9 +428,17 @@ static int notify_down_prepare(unsigned int cpu)
	return err;
}

static int notify_dying(unsigned int cpu)
{
	cpu_notify(CPU_DYING, cpu);
	return 0;
}

/* Take this CPU down. */
static int take_cpu_down(void *_param)
{
	struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
	enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE);
	int err, cpu = smp_processor_id();

	/* Ensure this CPU doesn't handle any more interrupts. */
@@ -431,7 +446,12 @@ static int take_cpu_down(void *_param)
	if (err < 0)
		return err;

	cpu_notify(CPU_DYING, cpu);
	/* Invoke the former CPU_DYING callbacks */
	for (; st->state > target; st->state--) {
		struct cpuhp_step *step = cpuhp_ap_states + st->state;

		cpuhp_invoke_callback(cpu, st->state, step->teardown);
	}
	/* Give up timekeeping duties */
	tick_handover_do_timer();
	/* Park the stopper thread */
@@ -512,6 +532,7 @@ static int notify_dead(unsigned int cpu)
#define notify_down_prepare	NULL
#define takedown_cpu		NULL
#define notify_dead		NULL
#define notify_dying		NULL
#endif

#ifdef CONFIG_HOTPLUG_CPU
@@ -615,6 +636,28 @@ void smpboot_thread_init(void)
	register_cpu_notifier(&smpboot_thread_notifier);
}

/**
 * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers
 * @cpu: cpu that just started
 *
 * This function calls the cpu_chain notifiers with CPU_STARTING.
 * It must be called by the arch code on the new cpu, before the new cpu
 * enables interrupts and before the "boot" cpu returns from __cpu_up().
 */
void notify_cpu_starting(unsigned int cpu)
{
	struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
	enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE);

	while (st->state < target) {
		struct cpuhp_step *step;

		st->state++;
		step = cpuhp_ap_states + st->state;
		cpuhp_invoke_callback(cpu, st->state, step->startup);
	}
}

static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
{
	for (st->state--; st->state > st->target; st->state--) {
@@ -842,19 +885,6 @@ core_initcall(cpu_hotplug_pm_sync_init);

#endif /* CONFIG_PM_SLEEP_SMP */

/**
 * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers
 * @cpu: cpu that just started
 *
 * This function calls the cpu_chain notifiers with CPU_STARTING.
 * It must be called by the arch code on the new cpu, before the new cpu
 * enables interrupts and before the "boot" cpu returns from __cpu_up().
 */
void notify_cpu_starting(unsigned int cpu)
{
	cpu_notify(CPU_STARTING, cpu);
}

#endif /* CONFIG_SMP */

/* Boot processor state steps */
@@ -879,8 +909,12 @@ static struct cpuhp_step cpuhp_bp_states[] = {
	[CPUHP_BRINGUP_CPU] = {
		.name			= "cpu:bringup",
		.startup		= bringup_cpu,
		.teardown		= NULL,
	},
	[CPUHP_TEARDOWN_CPU] = {
		.name			= "cpu:teardown",
		.startup		= NULL,
		.teardown		= takedown_cpu,
		.skip_onerr		= true,
	},
	[CPUHP_NOTIFY_ONLINE] = {
		.name			= "notify:online",
@@ -895,6 +929,23 @@ static struct cpuhp_step cpuhp_bp_states[] = {
	},
};

/* Application processor state steps */
static struct cpuhp_step cpuhp_ap_states[] = {
#ifdef CONFIG_SMP
	[CPUHP_AP_NOTIFY_STARTING] = {
		.name			= "notify:starting",
		.startup		= notify_starting,
		.teardown		= notify_dying,
		.skip_onerr		= true,
	},
#endif
	[CPUHP_ONLINE] = {
		.name			= "online",
		.startup		= NULL,
		.teardown		= NULL,
	},
};

/*
 * cpu_bit_bitmap[] is a special, "compressed" data structure that
 * represents all NR_CPUS bits binary values of 1<<nr.