aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel/smp.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-09-10 07:13:13 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-10 13:15:11 -0400
commit31139971b3dc9fbb2e8a8572fb81e6e8470f363a (patch)
tree644fc6833fe6e18d00dbc8b6b281f77e7b923d35 /arch/ppc/kernel/smp.c
parentbb0bb3b6596cdb08adb0b72453cc67d48e139c2c (diff)
[PATCH] ppc32: support hotplug cpu on powermacs
This allows cpus to be off-lined on 32-bit SMP powermacs. When a cpu is off-lined, it is put into sleep mode with interrupts disabled. It can be on-lined again by asserting its soft-reset pin, which is connected to a GPIO pin. With this I can off-line the second cpu in my dual G4 powermac, which means that I can then suspend the machine (the suspend/resume code refuses to suspend if more than one cpu is online, and making it cope with multiple cpus is surprisingly messy). Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ppc/kernel/smp.c')
-rw-r--r--arch/ppc/kernel/smp.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index e70b587b9e51..726fe7ce1747 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -45,6 +45,7 @@ cpumask_t cpu_online_map;
45cpumask_t cpu_possible_map; 45cpumask_t cpu_possible_map;
46int smp_hw_index[NR_CPUS]; 46int smp_hw_index[NR_CPUS];
47struct thread_info *secondary_ti; 47struct thread_info *secondary_ti;
48static struct task_struct *idle_tasks[NR_CPUS];
48 49
49EXPORT_SYMBOL(cpu_online_map); 50EXPORT_SYMBOL(cpu_online_map);
50EXPORT_SYMBOL(cpu_possible_map); 51EXPORT_SYMBOL(cpu_possible_map);
@@ -286,7 +287,8 @@ static void __devinit smp_store_cpu_info(int id)
286 287
287void __init smp_prepare_cpus(unsigned int max_cpus) 288void __init smp_prepare_cpus(unsigned int max_cpus)
288{ 289{
289 int num_cpus, i; 290 int num_cpus, i, cpu;
291 struct task_struct *p;
290 292
291 /* Fixup boot cpu */ 293 /* Fixup boot cpu */
292 smp_store_cpu_info(smp_processor_id()); 294 smp_store_cpu_info(smp_processor_id());
@@ -308,6 +310,17 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
308 310
309 if (smp_ops->space_timers) 311 if (smp_ops->space_timers)
310 smp_ops->space_timers(num_cpus); 312 smp_ops->space_timers(num_cpus);
313
314 for_each_cpu(cpu) {
315 if (cpu == smp_processor_id())
316 continue;
317 /* create a process for the processor */
318 p = fork_idle(cpu);
319 if (IS_ERR(p))
320 panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
321 p->thread_info->cpu = cpu;
322 idle_tasks[cpu] = p;
323 }
311} 324}
312 325
313void __devinit smp_prepare_boot_cpu(void) 326void __devinit smp_prepare_boot_cpu(void)
@@ -334,12 +347,17 @@ int __devinit start_secondary(void *unused)
334 set_dec(tb_ticks_per_jiffy); 347 set_dec(tb_ticks_per_jiffy);
335 cpu_callin_map[cpu] = 1; 348 cpu_callin_map[cpu] = 1;
336 349
337 printk("CPU %i done callin...\n", cpu); 350 printk("CPU %d done callin...\n", cpu);
338 smp_ops->setup_cpu(cpu); 351 smp_ops->setup_cpu(cpu);
339 printk("CPU %i done setup...\n", cpu); 352 printk("CPU %d done setup...\n", cpu);
340 local_irq_enable();
341 smp_ops->take_timebase(); 353 smp_ops->take_timebase();
342 printk("CPU %i done timebase take...\n", cpu); 354 printk("CPU %d done timebase take...\n", cpu);
355
356 spin_lock(&call_lock);
357 cpu_set(cpu, cpu_online_map);
358 spin_unlock(&call_lock);
359
360 local_irq_enable();
343 361
344 cpu_idle(); 362 cpu_idle();
345 return 0; 363 return 0;
@@ -347,17 +365,11 @@ int __devinit start_secondary(void *unused)
347 365
348int __cpu_up(unsigned int cpu) 366int __cpu_up(unsigned int cpu)
349{ 367{
350 struct task_struct *p;
351 char buf[32]; 368 char buf[32];
352 int c; 369 int c;
353 370
354 /* create a process for the processor */ 371 secondary_ti = idle_tasks[cpu]->thread_info;
355 /* only regs.msr is actually used, and 0 is OK for it */ 372 mb();
356 p = fork_idle(cpu);
357 if (IS_ERR(p))
358 panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
359 secondary_ti = p->thread_info;
360 p->thread_info->cpu = cpu;
361 373
362 /* 374 /*
363 * There was a cache flush loop here to flush the cache 375 * There was a cache flush loop here to flush the cache
@@ -389,7 +401,11 @@ int __cpu_up(unsigned int cpu)
389 printk("Processor %d found.\n", cpu); 401 printk("Processor %d found.\n", cpu);
390 402
391 smp_ops->give_timebase(); 403 smp_ops->give_timebase();
392 cpu_set(cpu, cpu_online_map); 404
405 /* Wait until cpu puts itself in the online map */
406 while (!cpu_online(cpu))
407 cpu_relax();
408
393 return 0; 409 return 0;
394} 410}
395 411