diff options
-rw-r--r-- | include/linux/cpu.h | 47 | ||||
-rw-r--r-- | kernel/cpu.c | 21 |
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 |
129 | extern int register_cpu_notifier(struct notifier_block *nb); | 137 | extern int register_cpu_notifier(struct notifier_block *nb); |
138 | extern int __register_cpu_notifier(struct notifier_block *nb); | ||
130 | extern void unregister_cpu_notifier(struct notifier_block *nb); | 139 | extern void unregister_cpu_notifier(struct notifier_block *nb); |
140 | extern void __unregister_cpu_notifier(struct notifier_block *nb); | ||
131 | #else | 141 | #else |
132 | 142 | ||
133 | #ifndef MODULE | 143 | #ifndef MODULE |
134 | extern int register_cpu_notifier(struct notifier_block *nb); | 144 | extern int register_cpu_notifier(struct notifier_block *nb); |
145 | extern int __register_cpu_notifier(struct notifier_block *nb); | ||
135 | #else | 146 | #else |
136 | static inline int register_cpu_notifier(struct notifier_block *nb) | 147 | static inline int register_cpu_notifier(struct notifier_block *nb) |
137 | { | 148 | { |
138 | return 0; | 149 | return 0; |
139 | } | 150 | } |
151 | |||
152 | static inline int __register_cpu_notifier(struct notifier_block *nb) | ||
153 | { | ||
154 | return 0; | ||
155 | } | ||
140 | #endif | 156 | #endif |
141 | 157 | ||
142 | static inline void unregister_cpu_notifier(struct notifier_block *nb) | 158 | static inline void unregister_cpu_notifier(struct notifier_block *nb) |
143 | { | 159 | { |
144 | } | 160 | } |
161 | |||
162 | static inline void __unregister_cpu_notifier(struct notifier_block *nb) | ||
163 | { | ||
164 | } | ||
145 | #endif | 165 | #endif |
146 | 166 | ||
147 | int cpu_up(unsigned int cpu); | 167 | int cpu_up(unsigned int cpu); |
@@ -149,19 +169,32 @@ void notify_cpu_starting(unsigned int cpu); | |||
149 | extern void cpu_maps_update_begin(void); | 169 | extern void cpu_maps_update_begin(void); |
150 | extern void cpu_maps_update_done(void); | 170 | extern 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 | ||
156 | static inline int register_cpu_notifier(struct notifier_block *nb) | 180 | static inline int register_cpu_notifier(struct notifier_block *nb) |
157 | { | 181 | { |
158 | return 0; | 182 | return 0; |
159 | } | 183 | } |
160 | 184 | ||
185 | static inline int __register_cpu_notifier(struct notifier_block *nb) | ||
186 | { | ||
187 | return 0; | ||
188 | } | ||
189 | |||
161 | static inline void unregister_cpu_notifier(struct notifier_block *nb) | 190 | static inline void unregister_cpu_notifier(struct notifier_block *nb) |
162 | { | 191 | { |
163 | } | 192 | } |
164 | 193 | ||
194 | static inline void __unregister_cpu_notifier(struct notifier_block *nb) | ||
195 | { | ||
196 | } | ||
197 | |||
165 | static inline void cpu_maps_update_begin(void) | 198 | static 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 | ||
206 | static inline void cpu_notifier_register_begin(void) | ||
207 | { | ||
208 | } | ||
209 | |||
210 | static inline void cpu_notifier_register_done(void) | ||
211 | { | ||
212 | } | ||
213 | |||
173 | #endif /* CONFIG_SMP */ | 214 | #endif /* CONFIG_SMP */ |
174 | extern struct bus_type cpu_subsys; | 215 | extern struct bus_type cpu_subsys; |
175 | 216 | ||
@@ -183,8 +224,11 @@ extern void put_online_cpus(void); | |||
183 | extern void cpu_hotplug_disable(void); | 224 | extern void cpu_hotplug_disable(void); |
184 | extern void cpu_hotplug_enable(void); | 225 | extern 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) | ||
188 | void clear_tasks_mm_cpumask(int cpu); | 232 | void clear_tasks_mm_cpumask(int cpu); |
189 | int cpu_down(unsigned int cpu); | 233 | int 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 @@ | |||
28 | static DEFINE_MUTEX(cpu_add_remove_lock); | 28 | static 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 | */ |
34 | void cpu_maps_update_begin(void) | 37 | void cpu_maps_update_begin(void) |
35 | { | 38 | { |
36 | mutex_lock(&cpu_add_remove_lock); | 39 | mutex_lock(&cpu_add_remove_lock); |
37 | } | 40 | } |
41 | EXPORT_SYMBOL(cpu_notifier_register_begin); | ||
38 | 42 | ||
39 | void cpu_maps_update_done(void) | 43 | void cpu_maps_update_done(void) |
40 | { | 44 | { |
41 | mutex_unlock(&cpu_add_remove_lock); | 45 | mutex_unlock(&cpu_add_remove_lock); |
42 | } | 46 | } |
47 | EXPORT_SYMBOL(cpu_notifier_register_done); | ||
43 | 48 | ||
44 | static RAW_NOTIFIER_HEAD(cpu_chain); | 49 | static 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 | ||
191 | int __ref __register_cpu_notifier(struct notifier_block *nb) | ||
192 | { | ||
193 | return raw_notifier_chain_register(&cpu_chain, nb); | ||
194 | } | ||
195 | |||
186 | static int __cpu_notify(unsigned long val, void *v, int nr_to_call, | 196 | static 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 | } |
208 | EXPORT_SYMBOL(register_cpu_notifier); | 218 | EXPORT_SYMBOL(register_cpu_notifier); |
219 | EXPORT_SYMBOL(__register_cpu_notifier); | ||
209 | 220 | ||
210 | void __ref unregister_cpu_notifier(struct notifier_block *nb) | 221 | void __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 | } |
216 | EXPORT_SYMBOL(unregister_cpu_notifier); | 227 | EXPORT_SYMBOL(unregister_cpu_notifier); |
217 | 228 | ||
229 | void __ref __unregister_cpu_notifier(struct notifier_block *nb) | ||
230 | { | ||
231 | raw_notifier_chain_unregister(&cpu_chain, nb); | ||
232 | } | ||
233 | EXPORT_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 |