aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r--kernel/cpu.c42
1 files changed, 25 insertions, 17 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c
index f6e726f18491..12b7458f23b1 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -126,7 +126,7 @@ static void cpu_hotplug_done(void)
126#else /* #if CONFIG_HOTPLUG_CPU */ 126#else /* #if CONFIG_HOTPLUG_CPU */
127static void cpu_hotplug_begin(void) {} 127static void cpu_hotplug_begin(void) {}
128static void cpu_hotplug_done(void) {} 128static void cpu_hotplug_done(void) {}
129#endif /* #esle #if CONFIG_HOTPLUG_CPU */ 129#endif /* #else #if CONFIG_HOTPLUG_CPU */
130 130
131/* Need to know about CPUs going up/down? */ 131/* Need to know about CPUs going up/down? */
132int __ref register_cpu_notifier(struct notifier_block *nb) 132int __ref register_cpu_notifier(struct notifier_block *nb)
@@ -160,7 +160,6 @@ static void cpu_notify_nofail(unsigned long val, void *v)
160{ 160{
161 BUG_ON(cpu_notify(val, v)); 161 BUG_ON(cpu_notify(val, v));
162} 162}
163
164EXPORT_SYMBOL(register_cpu_notifier); 163EXPORT_SYMBOL(register_cpu_notifier);
165 164
166void __ref unregister_cpu_notifier(struct notifier_block *nb) 165void __ref unregister_cpu_notifier(struct notifier_block *nb)
@@ -189,7 +188,6 @@ static inline void check_for_tasks(int cpu)
189} 188}
190 189
191struct take_cpu_down_param { 190struct take_cpu_down_param {
192 struct task_struct *caller;
193 unsigned long mod; 191 unsigned long mod;
194 void *hcpu; 192 void *hcpu;
195}; 193};
@@ -198,7 +196,6 @@ struct take_cpu_down_param {
198static int __ref take_cpu_down(void *_param) 196static int __ref take_cpu_down(void *_param)
199{ 197{
200 struct take_cpu_down_param *param = _param; 198 struct take_cpu_down_param *param = _param;
201 unsigned int cpu = (unsigned long)param->hcpu;
202 int err; 199 int err;
203 200
204 /* Ensure this CPU doesn't handle any more interrupts. */ 201 /* Ensure this CPU doesn't handle any more interrupts. */
@@ -207,12 +204,6 @@ static int __ref take_cpu_down(void *_param)
207 return err; 204 return err;
208 205
209 cpu_notify(CPU_DYING | param->mod, param->hcpu); 206 cpu_notify(CPU_DYING | param->mod, param->hcpu);
210
211 if (task_cpu(param->caller) == cpu)
212 move_task_off_dead_cpu(cpu, param->caller);
213 /* Force idle task to run as soon as we yield: it should
214 immediately notice cpu is offline and die quickly. */
215 sched_idle_next();
216 return 0; 207 return 0;
217} 208}
218 209
@@ -223,7 +214,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
223 void *hcpu = (void *)(long)cpu; 214 void *hcpu = (void *)(long)cpu;
224 unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; 215 unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
225 struct take_cpu_down_param tcd_param = { 216 struct take_cpu_down_param tcd_param = {
226 .caller = current,
227 .mod = mod, 217 .mod = mod,
228 .hcpu = hcpu, 218 .hcpu = hcpu,
229 }; 219 };
@@ -235,6 +225,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
235 return -EINVAL; 225 return -EINVAL;
236 226
237 cpu_hotplug_begin(); 227 cpu_hotplug_begin();
228
238 err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); 229 err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls);
239 if (err) { 230 if (err) {
240 nr_calls--; 231 nr_calls--;
@@ -253,9 +244,15 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
253 } 244 }
254 BUG_ON(cpu_online(cpu)); 245 BUG_ON(cpu_online(cpu));
255 246
256 /* Wait for it to sleep (leaving idle task). */ 247 /*
248 * The migration_call() CPU_DYING callback will have removed all
249 * runnable tasks from the cpu, there's only the idle task left now
250 * that the migration thread is done doing the stop_machine thing.
251 *
252 * Wait for the stop thread to go away.
253 */
257 while (!idle_cpu(cpu)) 254 while (!idle_cpu(cpu))
258 yield(); 255 cpu_relax();
259 256
260 /* This actually kills the CPU. */ 257 /* This actually kills the CPU. */
261 __cpu_die(cpu); 258 __cpu_die(cpu);
@@ -306,7 +303,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
306 ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); 303 ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls);
307 if (ret) { 304 if (ret) {
308 nr_calls--; 305 nr_calls--;
309 printk("%s: attempt to bring up CPU %u failed\n", 306 printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n",
310 __func__, cpu); 307 __func__, cpu);
311 goto out_notify; 308 goto out_notify;
312 } 309 }
@@ -386,6 +383,14 @@ out:
386#ifdef CONFIG_PM_SLEEP_SMP 383#ifdef CONFIG_PM_SLEEP_SMP
387static cpumask_var_t frozen_cpus; 384static cpumask_var_t frozen_cpus;
388 385
386void __weak arch_disable_nonboot_cpus_begin(void)
387{
388}
389
390void __weak arch_disable_nonboot_cpus_end(void)
391{
392}
393
389int disable_nonboot_cpus(void) 394int disable_nonboot_cpus(void)
390{ 395{
391 int cpu, first_cpu, error = 0; 396 int cpu, first_cpu, error = 0;
@@ -397,6 +402,7 @@ int disable_nonboot_cpus(void)
397 * with the userspace trying to use the CPU hotplug at the same time 402 * with the userspace trying to use the CPU hotplug at the same time
398 */ 403 */
399 cpumask_clear(frozen_cpus); 404 cpumask_clear(frozen_cpus);
405 arch_disable_nonboot_cpus_begin();
400 406
401 printk("Disabling non-boot CPUs ...\n"); 407 printk("Disabling non-boot CPUs ...\n");
402 for_each_online_cpu(cpu) { 408 for_each_online_cpu(cpu) {
@@ -412,6 +418,8 @@ int disable_nonboot_cpus(void)
412 } 418 }
413 } 419 }
414 420
421 arch_disable_nonboot_cpus_end();
422
415 if (!error) { 423 if (!error) {
416 BUG_ON(num_online_cpus() > 1); 424 BUG_ON(num_online_cpus() > 1);
417 /* Make sure the CPUs won't be enabled by someone else */ 425 /* Make sure the CPUs won't be enabled by someone else */
@@ -441,14 +449,14 @@ void __ref enable_nonboot_cpus(void)
441 if (cpumask_empty(frozen_cpus)) 449 if (cpumask_empty(frozen_cpus))
442 goto out; 450 goto out;
443 451
444 printk("Enabling non-boot CPUs ...\n"); 452 printk(KERN_INFO "Enabling non-boot CPUs ...\n");
445 453
446 arch_enable_nonboot_cpus_begin(); 454 arch_enable_nonboot_cpus_begin();
447 455
448 for_each_cpu(cpu, frozen_cpus) { 456 for_each_cpu(cpu, frozen_cpus) {
449 error = _cpu_up(cpu, 1); 457 error = _cpu_up(cpu, 1);
450 if (!error) { 458 if (!error) {
451 printk("CPU%d is up\n", cpu); 459 printk(KERN_INFO "CPU%d is up\n", cpu);
452 continue; 460 continue;
453 } 461 }
454 printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error); 462 printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error);
@@ -500,7 +508,7 @@ void __cpuinit notify_cpu_starting(unsigned int cpu)
500 */ 508 */
501 509
502/* cpu_bit_bitmap[0] is empty - so we can back into it */ 510/* cpu_bit_bitmap[0] is empty - so we can back into it */
503#define MASK_DECLARE_1(x) [x+1][0] = 1UL << (x) 511#define MASK_DECLARE_1(x) [x+1][0] = (1UL << (x))
504#define MASK_DECLARE_2(x) MASK_DECLARE_1(x), MASK_DECLARE_1(x+1) 512#define MASK_DECLARE_2(x) MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)
505#define MASK_DECLARE_4(x) MASK_DECLARE_2(x), MASK_DECLARE_2(x+2) 513#define MASK_DECLARE_4(x) MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)
506#define MASK_DECLARE_8(x) MASK_DECLARE_4(x), MASK_DECLARE_4(x+4) 514#define MASK_DECLARE_8(x) MASK_DECLARE_4(x), MASK_DECLARE_4(x+4)