From 14660b7ea3ca628410bb999d53926ca77973892b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 27 Nov 2016 00:13:33 +0100 Subject: [PATCH] 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 Cc: oprofile-list@lists.sf.net Cc: Robert Richter Cc: rt@linutronix.de Link: http://lkml.kernel.org/r/20161126231350.10321-6-bigeasy@linutronix.de Signed-off-by: Thomas Gleixner --- drivers/oprofile/nmi_timer_int.c | 58 +++++++++++--------------------- 1 file 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)