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

Commit 14660b7e authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Thomas Gleixner
Browse files

oprofile/nmi timer: Convert to hotplug state machine



Install the callbacks via the state machine and let the core invoke
the callbacks on the already online CPUs.

Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: oprofile-list@lists.sf.net
Cc: Robert Richter <rric@kernel.org>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20161126231350.10321-6-bigeasy@linutronix.de


Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 9c6bafab
Loading
Loading
Loading
Loading
+19 −39
Original line number Original line Diff line number Diff line
@@ -59,26 +59,17 @@ static void nmi_timer_stop_cpu(int cpu)
		perf_event_disable(event);
		perf_event_disable(event);
}
}


static int nmi_timer_cpu_notifier(struct notifier_block *b, unsigned long action,
static int nmi_timer_cpu_online(unsigned int cpu)
				  void *data)
{
{
	int cpu = (unsigned long)data;
	switch (action) {
	case CPU_DOWN_FAILED:
	case CPU_ONLINE:
	nmi_timer_start_cpu(cpu);
	nmi_timer_start_cpu(cpu);
		break;
	return 0;
	case CPU_DOWN_PREPARE:
		nmi_timer_stop_cpu(cpu);
		break;
}
}
	return NOTIFY_DONE;
static int nmi_timer_cpu_predown(unsigned int cpu)
{
	nmi_timer_stop_cpu(cpu);
	return 0;
}
}


static struct notifier_block nmi_timer_cpu_nb = {
	.notifier_call = nmi_timer_cpu_notifier
};

static int nmi_timer_start(void)
static int nmi_timer_start(void)
{
{
	int cpu;
	int cpu;
@@ -103,13 +94,14 @@ static void nmi_timer_stop(void)
	put_online_cpus();
	put_online_cpus();
}
}


static enum cpuhp_state hp_online;

static void nmi_timer_shutdown(void)
static void nmi_timer_shutdown(void)
{
{
	struct perf_event *event;
	struct perf_event *event;
	int cpu;
	int cpu;


	cpu_notifier_register_begin();
	cpuhp_remove_state(hp_online);
	__unregister_cpu_notifier(&nmi_timer_cpu_nb);
	for_each_possible_cpu(cpu) {
	for_each_possible_cpu(cpu) {
		event = per_cpu(nmi_timer_events, cpu);
		event = per_cpu(nmi_timer_events, cpu);
		if (!event)
		if (!event)
@@ -118,13 +110,11 @@ static void nmi_timer_shutdown(void)
		per_cpu(nmi_timer_events, cpu) = NULL;
		per_cpu(nmi_timer_events, cpu) = NULL;
		perf_event_release_kernel(event);
		perf_event_release_kernel(event);
	}
	}

	cpu_notifier_register_done();
}
}


static int nmi_timer_setup(void)
static int nmi_timer_setup(void)
{
{
	int cpu, err;
	int err;
	u64 period;
	u64 period;


	/* clock cycles per tick: */
	/* clock cycles per tick: */
@@ -132,24 +122,14 @@ static int nmi_timer_setup(void)
	do_div(period, HZ);
	do_div(period, HZ);
	nmi_timer_attr.sample_period = period;
	nmi_timer_attr.sample_period = period;


	cpu_notifier_register_begin();
	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "oprofile/nmi:online",
	err = __register_cpu_notifier(&nmi_timer_cpu_nb);
				nmi_timer_cpu_online, nmi_timer_cpu_predown);
	if (err)
	if (err < 0) {
		goto out;

	/* can't attach events to offline cpus: */
	for_each_online_cpu(cpu) {
		err = nmi_timer_start_cpu(cpu);
		if (err) {
			cpu_notifier_register_done();
		nmi_timer_shutdown();
		nmi_timer_shutdown();
		return err;
		return err;
	}
	}
	}
	hp_online = err;

	return 0;
out:
	cpu_notifier_register_done();
	return err;
}
}


int __init op_nmi_timer_init(struct oprofile_operations *ops)
int __init op_nmi_timer_init(struct oprofile_operations *ops)