Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sebastian Andrzej Siewior and committed by
Thomas Gleixner
14660b7e 9c6bafab

+19 -39
+19 -39
drivers/oprofile/nmi_timer_int.c
··· 59 59 perf_event_disable(event); 60 60 } 61 61 62 - static int nmi_timer_cpu_notifier(struct notifier_block *b, unsigned long action, 63 - void *data) 62 + static int nmi_timer_cpu_online(unsigned int cpu) 64 63 { 65 - int cpu = (unsigned long)data; 66 - switch (action) { 67 - case CPU_DOWN_FAILED: 68 - case CPU_ONLINE: 69 - nmi_timer_start_cpu(cpu); 70 - break; 71 - case CPU_DOWN_PREPARE: 72 - nmi_timer_stop_cpu(cpu); 73 - break; 74 - } 75 - return NOTIFY_DONE; 64 + nmi_timer_start_cpu(cpu); 65 + return 0; 76 66 } 77 - 78 - static struct notifier_block nmi_timer_cpu_nb = { 79 - .notifier_call = nmi_timer_cpu_notifier 80 - }; 67 + static int nmi_timer_cpu_predown(unsigned int cpu) 68 + { 69 + nmi_timer_stop_cpu(cpu); 70 + return 0; 71 + } 81 72 82 73 static int nmi_timer_start(void) 83 74 { ··· 94 103 put_online_cpus(); 95 104 } 96 105 106 + static enum cpuhp_state hp_online; 107 + 97 108 static void nmi_timer_shutdown(void) 98 109 { 99 110 struct perf_event *event; 100 111 int cpu; 101 112 102 - cpu_notifier_register_begin(); 103 - __unregister_cpu_notifier(&nmi_timer_cpu_nb); 113 + cpuhp_remove_state(hp_online); 104 114 for_each_possible_cpu(cpu) { 105 115 event = per_cpu(nmi_timer_events, cpu); 106 116 if (!event) ··· 110 118 per_cpu(nmi_timer_events, cpu) = NULL; 111 119 perf_event_release_kernel(event); 112 120 } 113 - 114 - cpu_notifier_register_done(); 115 121 } 116 122 117 123 static int nmi_timer_setup(void) 118 124 { 119 - int cpu, err; 125 + int err; 120 126 u64 period; 121 127 122 128 /* clock cycles per tick: */ ··· 122 132 do_div(period, HZ); 123 133 nmi_timer_attr.sample_period = period; 124 134 125 - cpu_notifier_register_begin(); 126 - err = __register_cpu_notifier(&nmi_timer_cpu_nb); 127 - if (err) 128 - goto out; 129 - 130 - /* can't attach events to offline cpus: */ 131 - for_each_online_cpu(cpu) { 132 - err = nmi_timer_start_cpu(cpu); 133 - if (err) { 134 - cpu_notifier_register_done(); 135 - nmi_timer_shutdown(); 136 - return err; 137 - } 135 + err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "oprofile/nmi:online", 136 + nmi_timer_cpu_online, nmi_timer_cpu_predown); 137 + if (err < 0) { 138 + nmi_timer_shutdown(); 139 + return err; 138 140 } 139 - 140 - out: 141 - cpu_notifier_register_done(); 142 - return err; 141 + hp_online = err; 142 + return 0; 143 143 } 144 144 145 145 int __init op_nmi_timer_init(struct oprofile_operations *ops)