aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cpu.h47
-rw-r--r--kernel/cpu.c21
2 files changed, 66 insertions, 2 deletions
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 03e235ad1bba..488d6ebcf6a1 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -122,26 +122,46 @@ enum {
122 { .notifier_call = fn, .priority = pri }; \ 122 { .notifier_call = fn, .priority = pri }; \
123 register_cpu_notifier(&fn##_nb); \ 123 register_cpu_notifier(&fn##_nb); \
124} 124}
125
126#define __cpu_notifier(fn, pri) { \
127 static struct notifier_block fn##_nb = \
128 { .notifier_call = fn, .priority = pri }; \
129 __register_cpu_notifier(&fn##_nb); \
130}
125#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */ 131#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
126#define cpu_notifier(fn, pri) do { (void)(fn); } while (0) 132#define cpu_notifier(fn, pri) do { (void)(fn); } while (0)
133#define __cpu_notifier(fn, pri) do { (void)(fn); } while (0)
127#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */ 134#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
135
128#ifdef CONFIG_HOTPLUG_CPU 136#ifdef CONFIG_HOTPLUG_CPU
129extern int register_cpu_notifier(struct notifier_block *nb); 137extern int register_cpu_notifier(struct notifier_block *nb);
138extern int __register_cpu_notifier(struct notifier_block *nb);
130extern void unregister_cpu_notifier(struct notifier_block *nb); 139extern void unregister_cpu_notifier(struct notifier_block *nb);
140extern void __unregister_cpu_notifier(struct notifier_block *nb);
131#else 141#else
132 142
133#ifndef MODULE 143#ifndef MODULE
134extern int register_cpu_notifier(struct notifier_block *nb); 144extern int register_cpu_notifier(struct notifier_block *nb);
145extern int __register_cpu_notifier(struct notifier_block *nb);
135#else 146#else
136static inline int register_cpu_notifier(struct notifier_block *nb) 147static inline int register_cpu_notifier(struct notifier_block *nb)
137{ 148{
138 return 0; 149 return 0;
139} 150}
151
152static inline int __register_cpu_notifier(struct notifier_block *nb)
153{
154 return 0;
155}
140#endif 156#endif
141 157
142static inline void unregister_cpu_notifier(struct notifier_block *nb) 158static inline void unregister_cpu_notifier(struct notifier_block *nb)
143{ 159{
144} 160}
161
162static inline void __unregister_cpu_notifier(struct notifier_block *nb)
163{
164}
145#endif 165#endif
146 166
147int cpu_up(unsigned int cpu); 167int cpu_up(unsigned int cpu);
@@ -149,19 +169,32 @@ void notify_cpu_starting(unsigned int cpu);
149extern void cpu_maps_update_begin(void); 169extern void cpu_maps_update_begin(void);
150extern void cpu_maps_update_done(void); 170extern void cpu_maps_update_done(void);
151 171
172#define cpu_notifier_register_begin cpu_maps_update_begin
173#define cpu_notifier_register_done cpu_maps_update_done
174
152#else /* CONFIG_SMP */ 175#else /* CONFIG_SMP */
153 176
154#define cpu_notifier(fn, pri) do { (void)(fn); } while (0) 177#define cpu_notifier(fn, pri) do { (void)(fn); } while (0)
178#define __cpu_notifier(fn, pri) do { (void)(fn); } while (0)
155 179
156static inline int register_cpu_notifier(struct notifier_block *nb) 180static inline int register_cpu_notifier(struct notifier_block *nb)
157{ 181{
158 return 0; 182 return 0;
159} 183}
160 184
185static inline int __register_cpu_notifier(struct notifier_block *nb)
186{
187 return 0;
188}
189
161static inline void unregister_cpu_notifier(struct notifier_block *nb) 190static inline void unregister_cpu_notifier(struct notifier_block *nb)
162{ 191{
163} 192}
164 193
194static inline void __unregister_cpu_notifier(struct notifier_block *nb)
195{
196}
197
165static inline void cpu_maps_update_begin(void) 198static inline void cpu_maps_update_begin(void)
166{ 199{
167} 200}
@@ -170,6 +203,14 @@ static inline void cpu_maps_update_done(void)
170{ 203{
171} 204}
172 205
206static inline void cpu_notifier_register_begin(void)
207{
208}
209
210static inline void cpu_notifier_register_done(void)
211{
212}
213
173#endif /* CONFIG_SMP */ 214#endif /* CONFIG_SMP */
174extern struct bus_type cpu_subsys; 215extern struct bus_type cpu_subsys;
175 216
@@ -183,8 +224,11 @@ extern void put_online_cpus(void);
183extern void cpu_hotplug_disable(void); 224extern void cpu_hotplug_disable(void);
184extern void cpu_hotplug_enable(void); 225extern void cpu_hotplug_enable(void);
185#define hotcpu_notifier(fn, pri) cpu_notifier(fn, pri) 226#define hotcpu_notifier(fn, pri) cpu_notifier(fn, pri)
227#define __hotcpu_notifier(fn, pri) __cpu_notifier(fn, pri)
186#define register_hotcpu_notifier(nb) register_cpu_notifier(nb) 228#define register_hotcpu_notifier(nb) register_cpu_notifier(nb)
229#define __register_hotcpu_notifier(nb) __register_cpu_notifier(nb)
187#define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb) 230#define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb)
231#define __unregister_hotcpu_notifier(nb) __unregister_cpu_notifier(nb)
188void clear_tasks_mm_cpumask(int cpu); 232void clear_tasks_mm_cpumask(int cpu);
189int cpu_down(unsigned int cpu); 233int cpu_down(unsigned int cpu);
190 234
@@ -197,9 +241,12 @@ static inline void cpu_hotplug_done(void) {}
197#define cpu_hotplug_disable() do { } while (0) 241#define cpu_hotplug_disable() do { } while (0)
198#define cpu_hotplug_enable() do { } while (0) 242#define cpu_hotplug_enable() do { } while (0)
199#define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0) 243#define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0)
244#define __hotcpu_notifier(fn, pri) do { (void)(fn); } while (0)
200/* These aren't inline functions due to a GCC bug. */ 245/* These aren't inline functions due to a GCC bug. */
201#define register_hotcpu_notifier(nb) ({ (void)(nb); 0; }) 246#define register_hotcpu_notifier(nb) ({ (void)(nb); 0; })
247#define __register_hotcpu_notifier(nb) ({ (void)(nb); 0; })
202#define unregister_hotcpu_notifier(nb) ({ (void)(nb); }) 248#define unregister_hotcpu_notifier(nb) ({ (void)(nb); })
249#define __unregister_hotcpu_notifier(nb) ({ (void)(nb); })
203#endif /* CONFIG_HOTPLUG_CPU */ 250#endif /* CONFIG_HOTPLUG_CPU */
204 251
205#ifdef CONFIG_PM_SLEEP_SMP 252#ifdef CONFIG_PM_SLEEP_SMP
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 33caf5e97701..a9e710eef0e2 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -28,18 +28,23 @@
28static DEFINE_MUTEX(cpu_add_remove_lock); 28static DEFINE_MUTEX(cpu_add_remove_lock);
29 29
30/* 30/*
31 * The following two API's must be used when attempting 31 * The following two APIs (cpu_maps_update_begin/done) must be used when
32 * to serialize the updates to cpu_online_mask, cpu_present_mask. 32 * attempting to serialize the updates to cpu_online_mask & cpu_present_mask.
33 * The APIs cpu_notifier_register_begin/done() must be used to protect CPU
34 * hotplug callback (un)registration performed using __register_cpu_notifier()
35 * or __unregister_cpu_notifier().
33 */ 36 */
34void cpu_maps_update_begin(void) 37void cpu_maps_update_begin(void)
35{ 38{
36 mutex_lock(&cpu_add_remove_lock); 39 mutex_lock(&cpu_add_remove_lock);
37} 40}
41EXPORT_SYMBOL(cpu_notifier_register_begin);
38 42
39void cpu_maps_update_done(void) 43void cpu_maps_update_done(void)
40{ 44{
41 mutex_unlock(&cpu_add_remove_lock); 45 mutex_unlock(&cpu_add_remove_lock);
42} 46}
47EXPORT_SYMBOL(cpu_notifier_register_done);
43 48
44static RAW_NOTIFIER_HEAD(cpu_chain); 49static RAW_NOTIFIER_HEAD(cpu_chain);
45 50
@@ -183,6 +188,11 @@ int __ref register_cpu_notifier(struct notifier_block *nb)
183 return ret; 188 return ret;
184} 189}
185 190
191int __ref __register_cpu_notifier(struct notifier_block *nb)
192{
193 return raw_notifier_chain_register(&cpu_chain, nb);
194}
195
186static int __cpu_notify(unsigned long val, void *v, int nr_to_call, 196static int __cpu_notify(unsigned long val, void *v, int nr_to_call,
187 int *nr_calls) 197 int *nr_calls)
188{ 198{
@@ -206,6 +216,7 @@ static void cpu_notify_nofail(unsigned long val, void *v)
206 BUG_ON(cpu_notify(val, v)); 216 BUG_ON(cpu_notify(val, v));
207} 217}
208EXPORT_SYMBOL(register_cpu_notifier); 218EXPORT_SYMBOL(register_cpu_notifier);
219EXPORT_SYMBOL(__register_cpu_notifier);
209 220
210void __ref unregister_cpu_notifier(struct notifier_block *nb) 221void __ref unregister_cpu_notifier(struct notifier_block *nb)
211{ 222{
@@ -215,6 +226,12 @@ void __ref unregister_cpu_notifier(struct notifier_block *nb)
215} 226}
216EXPORT_SYMBOL(unregister_cpu_notifier); 227EXPORT_SYMBOL(unregister_cpu_notifier);
217 228
229void __ref __unregister_cpu_notifier(struct notifier_block *nb)
230{
231 raw_notifier_chain_unregister(&cpu_chain, nb);
232}
233EXPORT_SYMBOL(__unregister_cpu_notifier);
234
218/** 235/**
219 * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU 236 * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
220 * @cpu: a CPU id 237 * @cpu: a CPU id