diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/cpu.h | 27 | ||||
-rw-r--r-- | include/linux/cpuhotplug.h | 93 | ||||
-rw-r--r-- | include/linux/notifier.h | 2 | ||||
-rw-r--r-- | include/linux/rcupdate.h | 4 | ||||
-rw-r--r-- | include/trace/events/cpuhp.h | 66 |
5 files changed, 173 insertions, 19 deletions
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index d2ca8c38f9c4..f9b1fab4388a 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/node.h> | 16 | #include <linux/node.h> |
17 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
18 | #include <linux/cpumask.h> | 18 | #include <linux/cpumask.h> |
19 | #include <linux/cpuhotplug.h> | ||
19 | 20 | ||
20 | struct device; | 21 | struct device; |
21 | struct device_node; | 22 | struct device_node; |
@@ -27,6 +28,9 @@ struct cpu { | |||
27 | struct device dev; | 28 | struct device dev; |
28 | }; | 29 | }; |
29 | 30 | ||
31 | extern void boot_cpu_init(void); | ||
32 | extern void boot_cpu_state_init(void); | ||
33 | |||
30 | extern int register_cpu(struct cpu *cpu, int num); | 34 | extern int register_cpu(struct cpu *cpu, int num); |
31 | extern struct device *get_cpu_device(unsigned cpu); | 35 | extern struct device *get_cpu_device(unsigned cpu); |
32 | extern bool cpu_is_hotpluggable(unsigned cpu); | 36 | extern bool cpu_is_hotpluggable(unsigned cpu); |
@@ -74,7 +78,7 @@ enum { | |||
74 | /* migration should happen before other stuff but after perf */ | 78 | /* migration should happen before other stuff but after perf */ |
75 | CPU_PRI_PERF = 20, | 79 | CPU_PRI_PERF = 20, |
76 | CPU_PRI_MIGRATION = 10, | 80 | CPU_PRI_MIGRATION = 10, |
77 | CPU_PRI_SMPBOOT = 9, | 81 | |
78 | /* bring up workqueues before normal notifiers and down after */ | 82 | /* bring up workqueues before normal notifiers and down after */ |
79 | CPU_PRI_WORKQUEUE_UP = 5, | 83 | CPU_PRI_WORKQUEUE_UP = 5, |
80 | CPU_PRI_WORKQUEUE_DOWN = -5, | 84 | CPU_PRI_WORKQUEUE_DOWN = -5, |
@@ -97,9 +101,7 @@ enum { | |||
97 | * Called on the new cpu, just before | 101 | * Called on the new cpu, just before |
98 | * enabling interrupts. Must not sleep, | 102 | * enabling interrupts. Must not sleep, |
99 | * must not fail */ | 103 | * must not fail */ |
100 | #define CPU_DYING_IDLE 0x000B /* CPU (unsigned)v dying, reached | 104 | #define CPU_BROKEN 0x000B /* CPU (unsigned)v did not die properly, |
101 | * idle loop. */ | ||
102 | #define CPU_BROKEN 0x000C /* CPU (unsigned)v did not die properly, | ||
103 | * perhaps due to preemption. */ | 105 | * perhaps due to preemption. */ |
104 | 106 | ||
105 | /* Used for CPU hotplug events occurring while tasks are frozen due to a suspend | 107 | /* Used for CPU hotplug events occurring while tasks are frozen due to a suspend |
@@ -118,6 +120,7 @@ enum { | |||
118 | 120 | ||
119 | 121 | ||
120 | #ifdef CONFIG_SMP | 122 | #ifdef CONFIG_SMP |
123 | extern bool cpuhp_tasks_frozen; | ||
121 | /* Need to know about CPUs going up/down? */ | 124 | /* Need to know about CPUs going up/down? */ |
122 | #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) | 125 | #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) |
123 | #define cpu_notifier(fn, pri) { \ | 126 | #define cpu_notifier(fn, pri) { \ |
@@ -167,7 +170,6 @@ static inline void __unregister_cpu_notifier(struct notifier_block *nb) | |||
167 | } | 170 | } |
168 | #endif | 171 | #endif |
169 | 172 | ||
170 | void smpboot_thread_init(void); | ||
171 | int cpu_up(unsigned int cpu); | 173 | int cpu_up(unsigned int cpu); |
172 | void notify_cpu_starting(unsigned int cpu); | 174 | void notify_cpu_starting(unsigned int cpu); |
173 | extern void cpu_maps_update_begin(void); | 175 | extern void cpu_maps_update_begin(void); |
@@ -177,6 +179,7 @@ extern void cpu_maps_update_done(void); | |||
177 | #define cpu_notifier_register_done cpu_maps_update_done | 179 | #define cpu_notifier_register_done cpu_maps_update_done |
178 | 180 | ||
179 | #else /* CONFIG_SMP */ | 181 | #else /* CONFIG_SMP */ |
182 | #define cpuhp_tasks_frozen 0 | ||
180 | 183 | ||
181 | #define cpu_notifier(fn, pri) do { (void)(fn); } while (0) | 184 | #define cpu_notifier(fn, pri) do { (void)(fn); } while (0) |
182 | #define __cpu_notifier(fn, pri) do { (void)(fn); } while (0) | 185 | #define __cpu_notifier(fn, pri) do { (void)(fn); } while (0) |
@@ -215,10 +218,6 @@ static inline void cpu_notifier_register_done(void) | |||
215 | { | 218 | { |
216 | } | 219 | } |
217 | 220 | ||
218 | static inline void smpboot_thread_init(void) | ||
219 | { | ||
220 | } | ||
221 | |||
222 | #endif /* CONFIG_SMP */ | 221 | #endif /* CONFIG_SMP */ |
223 | extern struct bus_type cpu_subsys; | 222 | extern struct bus_type cpu_subsys; |
224 | 223 | ||
@@ -265,11 +264,6 @@ static inline int disable_nonboot_cpus(void) { return 0; } | |||
265 | static inline void enable_nonboot_cpus(void) {} | 264 | static inline void enable_nonboot_cpus(void) {} |
266 | #endif /* !CONFIG_PM_SLEEP_SMP */ | 265 | #endif /* !CONFIG_PM_SLEEP_SMP */ |
267 | 266 | ||
268 | enum cpuhp_state { | ||
269 | CPUHP_OFFLINE, | ||
270 | CPUHP_ONLINE, | ||
271 | }; | ||
272 | |||
273 | void cpu_startup_entry(enum cpuhp_state state); | 267 | void cpu_startup_entry(enum cpuhp_state state); |
274 | 268 | ||
275 | void cpu_idle_poll_ctrl(bool enable); | 269 | void cpu_idle_poll_ctrl(bool enable); |
@@ -280,14 +274,15 @@ void arch_cpu_idle_enter(void); | |||
280 | void arch_cpu_idle_exit(void); | 274 | void arch_cpu_idle_exit(void); |
281 | void arch_cpu_idle_dead(void); | 275 | void arch_cpu_idle_dead(void); |
282 | 276 | ||
283 | DECLARE_PER_CPU(bool, cpu_dead_idle); | ||
284 | |||
285 | int cpu_report_state(int cpu); | 277 | int cpu_report_state(int cpu); |
286 | int cpu_check_up_prepare(int cpu); | 278 | int cpu_check_up_prepare(int cpu); |
287 | void cpu_set_state_online(int cpu); | 279 | void cpu_set_state_online(int cpu); |
288 | #ifdef CONFIG_HOTPLUG_CPU | 280 | #ifdef CONFIG_HOTPLUG_CPU |
289 | bool cpu_wait_death(unsigned int cpu, int seconds); | 281 | bool cpu_wait_death(unsigned int cpu, int seconds); |
290 | bool cpu_report_death(void); | 282 | bool cpu_report_death(void); |
283 | void cpuhp_report_idle_dead(void); | ||
284 | #else | ||
285 | static inline void cpuhp_report_idle_dead(void) { } | ||
291 | #endif /* #ifdef CONFIG_HOTPLUG_CPU */ | 286 | #endif /* #ifdef CONFIG_HOTPLUG_CPU */ |
292 | 287 | ||
293 | #endif /* _LINUX_CPU_H_ */ | 288 | #endif /* _LINUX_CPU_H_ */ |
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h new file mode 100644 index 000000000000..5d68e15e46b7 --- /dev/null +++ b/include/linux/cpuhotplug.h | |||
@@ -0,0 +1,93 @@ | |||
1 | #ifndef __CPUHOTPLUG_H | ||
2 | #define __CPUHOTPLUG_H | ||
3 | |||
4 | enum cpuhp_state { | ||
5 | CPUHP_OFFLINE, | ||
6 | CPUHP_CREATE_THREADS, | ||
7 | CPUHP_NOTIFY_PREPARE, | ||
8 | CPUHP_BRINGUP_CPU, | ||
9 | CPUHP_AP_IDLE_DEAD, | ||
10 | CPUHP_AP_OFFLINE, | ||
11 | CPUHP_AP_NOTIFY_STARTING, | ||
12 | CPUHP_AP_ONLINE, | ||
13 | CPUHP_TEARDOWN_CPU, | ||
14 | CPUHP_AP_ONLINE_IDLE, | ||
15 | CPUHP_AP_SMPBOOT_THREADS, | ||
16 | CPUHP_AP_NOTIFY_ONLINE, | ||
17 | CPUHP_AP_ONLINE_DYN, | ||
18 | CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30, | ||
19 | CPUHP_ONLINE, | ||
20 | }; | ||
21 | |||
22 | int __cpuhp_setup_state(enum cpuhp_state state, const char *name, bool invoke, | ||
23 | int (*startup)(unsigned int cpu), | ||
24 | int (*teardown)(unsigned int cpu)); | ||
25 | |||
26 | /** | ||
27 | * cpuhp_setup_state - Setup hotplug state callbacks with calling the callbacks | ||
28 | * @state: The state for which the calls are installed | ||
29 | * @name: Name of the callback (will be used in debug output) | ||
30 | * @startup: startup callback function | ||
31 | * @teardown: teardown callback function | ||
32 | * | ||
33 | * Installs the callback functions and invokes the startup callback on | ||
34 | * the present cpus which have already reached the @state. | ||
35 | */ | ||
36 | static inline int cpuhp_setup_state(enum cpuhp_state state, | ||
37 | const char *name, | ||
38 | int (*startup)(unsigned int cpu), | ||
39 | int (*teardown)(unsigned int cpu)) | ||
40 | { | ||
41 | return __cpuhp_setup_state(state, name, true, startup, teardown); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * cpuhp_setup_state_nocalls - Setup hotplug state callbacks without calling the | ||
46 | * callbacks | ||
47 | * @state: The state for which the calls are installed | ||
48 | * @name: Name of the callback. | ||
49 | * @startup: startup callback function | ||
50 | * @teardown: teardown callback function | ||
51 | * | ||
52 | * Same as @cpuhp_setup_state except that no calls are executed are invoked | ||
53 | * during installation of this callback. NOP if SMP=n or HOTPLUG_CPU=n. | ||
54 | */ | ||
55 | static inline int cpuhp_setup_state_nocalls(enum cpuhp_state state, | ||
56 | const char *name, | ||
57 | int (*startup)(unsigned int cpu), | ||
58 | int (*teardown)(unsigned int cpu)) | ||
59 | { | ||
60 | return __cpuhp_setup_state(state, name, false, startup, teardown); | ||
61 | } | ||
62 | |||
63 | void __cpuhp_remove_state(enum cpuhp_state state, bool invoke); | ||
64 | |||
65 | /** | ||
66 | * cpuhp_remove_state - Remove hotplug state callbacks and invoke the teardown | ||
67 | * @state: The state for which the calls are removed | ||
68 | * | ||
69 | * Removes the callback functions and invokes the teardown callback on | ||
70 | * the present cpus which have already reached the @state. | ||
71 | */ | ||
72 | static inline void cpuhp_remove_state(enum cpuhp_state state) | ||
73 | { | ||
74 | __cpuhp_remove_state(state, true); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * cpuhp_remove_state_nocalls - Remove hotplug state callbacks without invoking | ||
79 | * teardown | ||
80 | * @state: The state for which the calls are removed | ||
81 | */ | ||
82 | static inline void cpuhp_remove_state_nocalls(enum cpuhp_state state) | ||
83 | { | ||
84 | __cpuhp_remove_state(state, false); | ||
85 | } | ||
86 | |||
87 | #ifdef CONFIG_SMP | ||
88 | void cpuhp_online_idle(enum cpuhp_state state); | ||
89 | #else | ||
90 | static inline void cpuhp_online_idle(enum cpuhp_state state) { } | ||
91 | #endif | ||
92 | |||
93 | #endif | ||
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index d14a4c362465..4149868de4e6 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
@@ -47,6 +47,8 @@ | |||
47 | * runtime initialization. | 47 | * runtime initialization. |
48 | */ | 48 | */ |
49 | 49 | ||
50 | struct notifier_block; | ||
51 | |||
50 | typedef int (*notifier_fn_t)(struct notifier_block *nb, | 52 | typedef int (*notifier_fn_t)(struct notifier_block *nb, |
51 | unsigned long action, void *data); | 53 | unsigned long action, void *data); |
52 | 54 | ||
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index b5d48bd56e3f..2657aff2725b 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h | |||
@@ -332,9 +332,7 @@ void rcu_init(void); | |||
332 | void rcu_sched_qs(void); | 332 | void rcu_sched_qs(void); |
333 | void rcu_bh_qs(void); | 333 | void rcu_bh_qs(void); |
334 | void rcu_check_callbacks(int user); | 334 | void rcu_check_callbacks(int user); |
335 | struct notifier_block; | 335 | void rcu_report_dead(unsigned int cpu); |
336 | int rcu_cpu_notify(struct notifier_block *self, | ||
337 | unsigned long action, void *hcpu); | ||
338 | 336 | ||
339 | #ifndef CONFIG_TINY_RCU | 337 | #ifndef CONFIG_TINY_RCU |
340 | void rcu_end_inkernel_boot(void); | 338 | void rcu_end_inkernel_boot(void); |
diff --git a/include/trace/events/cpuhp.h b/include/trace/events/cpuhp.h new file mode 100644 index 000000000000..a72bd93ec7e5 --- /dev/null +++ b/include/trace/events/cpuhp.h | |||
@@ -0,0 +1,66 @@ | |||
1 | #undef TRACE_SYSTEM | ||
2 | #define TRACE_SYSTEM cpuhp | ||
3 | |||
4 | #if !defined(_TRACE_CPUHP_H) || defined(TRACE_HEADER_MULTI_READ) | ||
5 | #define _TRACE_CPUHP_H | ||
6 | |||
7 | #include <linux/tracepoint.h> | ||
8 | |||
9 | TRACE_EVENT(cpuhp_enter, | ||
10 | |||
11 | TP_PROTO(unsigned int cpu, | ||
12 | int target, | ||
13 | int idx, | ||
14 | int (*fun)(unsigned int)), | ||
15 | |||
16 | TP_ARGS(cpu, target, idx, fun), | ||
17 | |||
18 | TP_STRUCT__entry( | ||
19 | __field( unsigned int, cpu ) | ||
20 | __field( int, target ) | ||
21 | __field( int, idx ) | ||
22 | __field( void *, fun ) | ||
23 | ), | ||
24 | |||
25 | TP_fast_assign( | ||
26 | __entry->cpu = cpu; | ||
27 | __entry->target = target; | ||
28 | __entry->idx = idx; | ||
29 | __entry->fun = fun; | ||
30 | ), | ||
31 | |||
32 | TP_printk("cpu: %04u target: %3d step: %3d (%pf)", | ||
33 | __entry->cpu, __entry->target, __entry->idx, __entry->fun) | ||
34 | ); | ||
35 | |||
36 | TRACE_EVENT(cpuhp_exit, | ||
37 | |||
38 | TP_PROTO(unsigned int cpu, | ||
39 | int state, | ||
40 | int idx, | ||
41 | int ret), | ||
42 | |||
43 | TP_ARGS(cpu, state, idx, ret), | ||
44 | |||
45 | TP_STRUCT__entry( | ||
46 | __field( unsigned int, cpu ) | ||
47 | __field( int, state ) | ||
48 | __field( int, idx ) | ||
49 | __field( int, ret ) | ||
50 | ), | ||
51 | |||
52 | TP_fast_assign( | ||
53 | __entry->cpu = cpu; | ||
54 | __entry->state = state; | ||
55 | __entry->idx = idx; | ||
56 | __entry->ret = ret; | ||
57 | ), | ||
58 | |||
59 | TP_printk(" cpu: %04u state: %3d step: %3d ret: %d", | ||
60 | __entry->cpu, __entry->state, __entry->idx, __entry->ret) | ||
61 | ); | ||
62 | |||
63 | #endif | ||
64 | |||
65 | /* This part must be outside protection */ | ||
66 | #include <trace/define_trace.h> | ||