summary refs log tree commit diff
path: root/drivers/oprofile/nmi_timer_int.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-11-27 00:13:33 +0100
committerThomas Gleixner <tglx@linutronix.de>2016-12-02 00:52:34 +0100
commit14660b7ea3ca628410bb999d53926ca77973892b (patch)
treeb90ee3b6578ef63ce61a0283ec3d607f71cff028 /drivers/oprofile/nmi_timer_int.c
parent9c6bafab03dec222237b6eb8b5adf5c18ec76264 (diff)
downloadlinux-14660b7ea3ca628410bb999d53926ca77973892b.tar.gz
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: Sebastian 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: Thomas Gleixner <tglx@linutronix.de>

Diffstat (limited to 'drivers/oprofile/nmi_timer_int.c')
-rw-r--r--drivers/oprofile/nmi_timer_int.c58
1 files changed, 19 insertions, 39 deletions
diff --git a/drivers/oprofile/nmi_timer_int.c b/drivers/oprofile/nmi_timer_int.c
index 9559829fb234..e65a576e4032 100644
--- a/drivers/oprofile/nmi_timer_int.c
+++ b/drivers/oprofile/nmi_timer_int.c
@@ -59,25 +59,16 @@ static void nmi_timer_stop_cpu(int cpu)
 		perf_event_disable(event);
 }
 
-static int nmi_timer_cpu_notifier(struct notifier_block *b, unsigned long action,
-				  void *data)
+static int nmi_timer_cpu_online(unsigned int cpu)
 {
-	int cpu = (unsigned long)data;
-	switch (action) {
-	case CPU_DOWN_FAILED:
-	case CPU_ONLINE:
-		nmi_timer_start_cpu(cpu);
-		break;
-	case CPU_DOWN_PREPARE:
-		nmi_timer_stop_cpu(cpu);
-		break;
-	}
-	return NOTIFY_DONE;
+	nmi_timer_start_cpu(cpu);
+	return 0;
+}
+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)
 {
@@ -103,13 +94,14 @@ static void nmi_timer_stop(void)
 	put_online_cpus();
 }
 
+static enum cpuhp_state hp_online;
+
 static void nmi_timer_shutdown(void)
 {
 	struct perf_event *event;
 	int cpu;
 
-	cpu_notifier_register_begin();
-	__unregister_cpu_notifier(&nmi_timer_cpu_nb);
+	cpuhp_remove_state(hp_online);
 	for_each_possible_cpu(cpu) {
 		event = per_cpu(nmi_timer_events, cpu);
 		if (!event)
@@ -118,13 +110,11 @@ static void nmi_timer_shutdown(void)
 		per_cpu(nmi_timer_events, cpu) = NULL;
 		perf_event_release_kernel(event);
 	}
-
-	cpu_notifier_register_done();
 }
 
 static int nmi_timer_setup(void)
 {
-	int cpu, err;
+	int err;
 	u64 period;
 
 	/* clock cycles per tick: */
@@ -132,24 +122,14 @@ static int nmi_timer_setup(void)
 	do_div(period, HZ);
 	nmi_timer_attr.sample_period = period;
 
-	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) {
-			cpu_notifier_register_done();
-			nmi_timer_shutdown();
-			return err;
-		}
+	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "oprofile/nmi:online",
+				nmi_timer_cpu_online, nmi_timer_cpu_predown);
+	if (err < 0) {
+		nmi_timer_shutdown();
+		return err;
 	}
-
-out:
-	cpu_notifier_register_done();
-	return err;
+	hp_online = err;
+	return 0;
 }
 
 int __init op_nmi_timer_init(struct oprofile_operations *ops)