diff options
Diffstat (limited to 'arch/ia64/kernel/smpboot.c')
-rw-r--r-- | arch/ia64/kernel/smpboot.c | 81 |
1 files changed, 50 insertions, 31 deletions
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 5318f0cbfc26..ca1536db3394 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * 02/07/31 David Mosberger <davidm@hpl.hp.com> Switch over to hotplug-CPU boot-sequence. | 9 | * 02/07/31 David Mosberger <davidm@hpl.hp.com> Switch over to hotplug-CPU boot-sequence. |
10 | * smp_boot_cpus()/smp_commence() is replaced by | 10 | * smp_boot_cpus()/smp_commence() is replaced by |
11 | * smp_prepare_cpus()/__cpu_up()/smp_cpus_done(). | 11 | * smp_prepare_cpus()/__cpu_up()/smp_cpus_done(). |
12 | * 04/06/21 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support | ||
12 | */ | 13 | */ |
13 | #include <linux/config.h> | 14 | #include <linux/config.h> |
14 | 15 | ||
@@ -58,6 +59,37 @@ | |||
58 | #define Dprintk(x...) | 59 | #define Dprintk(x...) |
59 | #endif | 60 | #endif |
60 | 61 | ||
62 | #ifdef CONFIG_HOTPLUG_CPU | ||
63 | /* | ||
64 | * Store all idle threads, this can be reused instead of creating | ||
65 | * a new thread. Also avoids complicated thread destroy functionality | ||
66 | * for idle threads. | ||
67 | */ | ||
68 | struct task_struct *idle_thread_array[NR_CPUS]; | ||
69 | |||
70 | /* | ||
71 | * Global array allocated for NR_CPUS at boot time | ||
72 | */ | ||
73 | struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS]; | ||
74 | |||
75 | /* | ||
76 | * start_ap in head.S uses this to store current booting cpu | ||
77 | * info. | ||
78 | */ | ||
79 | struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0]; | ||
80 | |||
81 | #define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]); | ||
82 | |||
83 | #define get_idle_for_cpu(x) (idle_thread_array[(x)]) | ||
84 | #define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p)) | ||
85 | |||
86 | #else | ||
87 | |||
88 | #define get_idle_for_cpu(x) (NULL) | ||
89 | #define set_idle_for_cpu(x,p) | ||
90 | #define set_brendez_area(x) | ||
91 | #endif | ||
92 | |||
61 | 93 | ||
62 | /* | 94 | /* |
63 | * ITC synchronization related stuff: | 95 | * ITC synchronization related stuff: |
@@ -345,7 +377,6 @@ start_secondary (void *unused) | |||
345 | { | 377 | { |
346 | /* Early console may use I/O ports */ | 378 | /* Early console may use I/O ports */ |
347 | ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase)); | 379 | ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase)); |
348 | |||
349 | Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id()); | 380 | Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id()); |
350 | efi_map_pal_code(); | 381 | efi_map_pal_code(); |
351 | cpu_init(); | 382 | cpu_init(); |
@@ -384,6 +415,13 @@ do_boot_cpu (int sapicid, int cpu) | |||
384 | .done = COMPLETION_INITIALIZER(c_idle.done), | 415 | .done = COMPLETION_INITIALIZER(c_idle.done), |
385 | }; | 416 | }; |
386 | DECLARE_WORK(work, do_fork_idle, &c_idle); | 417 | DECLARE_WORK(work, do_fork_idle, &c_idle); |
418 | |||
419 | c_idle.idle = get_idle_for_cpu(cpu); | ||
420 | if (c_idle.idle) { | ||
421 | init_idle(c_idle.idle, cpu); | ||
422 | goto do_rest; | ||
423 | } | ||
424 | |||
387 | /* | 425 | /* |
388 | * We can't use kernel_thread since we must avoid to reschedule the child. | 426 | * We can't use kernel_thread since we must avoid to reschedule the child. |
389 | */ | 427 | */ |
@@ -396,10 +434,15 @@ do_boot_cpu (int sapicid, int cpu) | |||
396 | 434 | ||
397 | if (IS_ERR(c_idle.idle)) | 435 | if (IS_ERR(c_idle.idle)) |
398 | panic("failed fork for CPU %d", cpu); | 436 | panic("failed fork for CPU %d", cpu); |
437 | |||
438 | set_idle_for_cpu(cpu, c_idle.idle); | ||
439 | |||
440 | do_rest: | ||
399 | task_for_booting_cpu = c_idle.idle; | 441 | task_for_booting_cpu = c_idle.idle; |
400 | 442 | ||
401 | Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); | 443 | Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); |
402 | 444 | ||
445 | set_brendez_area(cpu); | ||
403 | platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); | 446 | platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0); |
404 | 447 | ||
405 | /* | 448 | /* |
@@ -555,16 +598,6 @@ void __devinit smp_prepare_boot_cpu(void) | |||
555 | #ifdef CONFIG_HOTPLUG_CPU | 598 | #ifdef CONFIG_HOTPLUG_CPU |
556 | extern void fixup_irqs(void); | 599 | extern void fixup_irqs(void); |
557 | /* must be called with cpucontrol mutex held */ | 600 | /* must be called with cpucontrol mutex held */ |
558 | static int __devinit cpu_enable(unsigned int cpu) | ||
559 | { | ||
560 | per_cpu(cpu_state,cpu) = CPU_UP_PREPARE; | ||
561 | wmb(); | ||
562 | |||
563 | while (!cpu_online(cpu)) | ||
564 | cpu_relax(); | ||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | int __cpu_disable(void) | 601 | int __cpu_disable(void) |
569 | { | 602 | { |
570 | int cpu = smp_processor_id(); | 603 | int cpu = smp_processor_id(); |
@@ -577,7 +610,7 @@ int __cpu_disable(void) | |||
577 | 610 | ||
578 | fixup_irqs(); | 611 | fixup_irqs(); |
579 | local_flush_tlb_all(); | 612 | local_flush_tlb_all(); |
580 | printk ("Disabled cpu %u\n", smp_processor_id()); | 613 | cpu_clear(cpu, cpu_callin_map); |
581 | return 0; | 614 | return 0; |
582 | } | 615 | } |
583 | 616 | ||
@@ -589,12 +622,7 @@ void __cpu_die(unsigned int cpu) | |||
589 | /* They ack this in play_dead by setting CPU_DEAD */ | 622 | /* They ack this in play_dead by setting CPU_DEAD */ |
590 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) | 623 | if (per_cpu(cpu_state, cpu) == CPU_DEAD) |
591 | { | 624 | { |
592 | /* | 625 | printk ("CPU %d is now offline\n", cpu); |
593 | * TBD: Enable this when physical removal | ||
594 | * or when we put the processor is put in | ||
595 | * SAL_BOOT_RENDEZ mode | ||
596 | * cpu_clear(cpu, cpu_callin_map); | ||
597 | */ | ||
598 | return; | 626 | return; |
599 | } | 627 | } |
600 | msleep(100); | 628 | msleep(100); |
@@ -602,11 +630,6 @@ void __cpu_die(unsigned int cpu) | |||
602 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); | 630 | printk(KERN_ERR "CPU %u didn't die...\n", cpu); |
603 | } | 631 | } |
604 | #else /* !CONFIG_HOTPLUG_CPU */ | 632 | #else /* !CONFIG_HOTPLUG_CPU */ |
605 | static int __devinit cpu_enable(unsigned int cpu) | ||
606 | { | ||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | int __cpu_disable(void) | 633 | int __cpu_disable(void) |
611 | { | 634 | { |
612 | return -ENOSYS; | 635 | return -ENOSYS; |
@@ -648,16 +671,12 @@ __cpu_up (unsigned int cpu) | |||
648 | return -EINVAL; | 671 | return -EINVAL; |
649 | 672 | ||
650 | /* | 673 | /* |
651 | * Already booted.. just enable and get outa idle lool | 674 | * Already booted cpu? not valid anymore since we dont |
675 | * do idle loop tightspin anymore. | ||
652 | */ | 676 | */ |
653 | if (cpu_isset(cpu, cpu_callin_map)) | 677 | if (cpu_isset(cpu, cpu_callin_map)) |
654 | { | 678 | return -EINVAL; |
655 | cpu_enable(cpu); | 679 | |
656 | local_irq_enable(); | ||
657 | while (!cpu_isset(cpu, cpu_online_map)) | ||
658 | mb(); | ||
659 | return 0; | ||
660 | } | ||
661 | /* Processor goes to start_secondary(), sets online flag */ | 680 | /* Processor goes to start_secondary(), sets online flag */ |
662 | ret = do_boot_cpu(sapicid, cpu); | 681 | ret = do_boot_cpu(sapicid, cpu); |
663 | if (ret < 0) | 682 | if (ret < 0) |