diff options
Diffstat (limited to 'arch/x86/kernel/smpboot.c')
-rw-r--r-- | arch/x86/kernel/smpboot.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 036604d3daed..bf0833487455 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -816,6 +816,43 @@ static void __cpuinit do_fork_idle(struct work_struct *work) | |||
816 | complete(&c_idle->done); | 816 | complete(&c_idle->done); |
817 | } | 817 | } |
818 | 818 | ||
819 | /* | ||
820 | * Allocate node local memory for the AP pda. | ||
821 | * | ||
822 | * Must be called after the _cpu_pda pointer table is initialized. | ||
823 | */ | ||
824 | static int __cpuinit get_local_pda(int cpu) | ||
825 | { | ||
826 | struct x8664_pda *oldpda, *newpda; | ||
827 | unsigned long size = sizeof(struct x8664_pda); | ||
828 | int node = cpu_to_node(cpu); | ||
829 | |||
830 | if (cpu_pda(cpu) && !cpu_pda(cpu)->in_bootmem) | ||
831 | return 0; | ||
832 | |||
833 | oldpda = cpu_pda(cpu); | ||
834 | newpda = kmalloc_node(size, GFP_ATOMIC, node); | ||
835 | if (!newpda) { | ||
836 | printk(KERN_ERR "Could not allocate node local PDA " | ||
837 | "for CPU %d on node %d\n", cpu, node); | ||
838 | |||
839 | if (oldpda) | ||
840 | return 0; /* have a usable pda */ | ||
841 | else | ||
842 | return -1; | ||
843 | } | ||
844 | |||
845 | if (oldpda) { | ||
846 | memcpy(newpda, oldpda, size); | ||
847 | if (!after_bootmem) | ||
848 | free_bootmem((unsigned long)oldpda, size); | ||
849 | } | ||
850 | |||
851 | newpda->in_bootmem = 0; | ||
852 | cpu_pda(cpu) = newpda; | ||
853 | return 0; | ||
854 | } | ||
855 | |||
819 | static int __cpuinit do_boot_cpu(int apicid, int cpu) | 856 | static int __cpuinit do_boot_cpu(int apicid, int cpu) |
820 | /* | 857 | /* |
821 | * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad | 858 | * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad |
@@ -841,19 +878,11 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) | |||
841 | } | 878 | } |
842 | 879 | ||
843 | /* Allocate node local memory for AP pdas */ | 880 | /* Allocate node local memory for AP pdas */ |
844 | if (cpu_pda(cpu) == &boot_cpu_pda[cpu]) { | 881 | if (cpu > 0) { |
845 | struct x8664_pda *newpda, *pda; | 882 | boot_error = get_local_pda(cpu); |
846 | int node = cpu_to_node(cpu); | 883 | if (boot_error) |
847 | pda = cpu_pda(cpu); | 884 | goto restore_state; |
848 | newpda = kmalloc_node(sizeof(struct x8664_pda), GFP_ATOMIC, | 885 | /* if can't get pda memory, can't start cpu */ |
849 | node); | ||
850 | if (newpda) { | ||
851 | memcpy(newpda, pda, sizeof(struct x8664_pda)); | ||
852 | cpu_pda(cpu) = newpda; | ||
853 | } else | ||
854 | printk(KERN_ERR | ||
855 | "Could not allocate node local PDA for CPU %d on node %d\n", | ||
856 | cpu, node); | ||
857 | } | 886 | } |
858 | #endif | 887 | #endif |
859 | 888 | ||
@@ -972,6 +1001,8 @@ do_rest: | |||
972 | } | 1001 | } |
973 | } | 1002 | } |
974 | 1003 | ||
1004 | restore_state: | ||
1005 | |||
975 | if (boot_error) { | 1006 | if (boot_error) { |
976 | /* Try to put things back the way they were before ... */ | 1007 | /* Try to put things back the way they were before ... */ |
977 | unmap_cpu_to_logical_apicid(cpu); | 1008 | unmap_cpu_to_logical_apicid(cpu); |
@@ -1347,6 +1378,8 @@ __init void prefill_possible_map(void) | |||
1347 | 1378 | ||
1348 | for (i = 0; i < possible; i++) | 1379 | for (i = 0; i < possible; i++) |
1349 | cpu_set(i, cpu_possible_map); | 1380 | cpu_set(i, cpu_possible_map); |
1381 | |||
1382 | nr_cpu_ids = possible; | ||
1350 | } | 1383 | } |
1351 | 1384 | ||
1352 | static void __ref remove_cpu_from_maps(int cpu) | 1385 | static void __ref remove_cpu_from_maps(int cpu) |