diff options
author | Ashok Raj <ashok.raj@intel.com> | 2006-09-26 04:52:35 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:35 -0400 |
commit | 73fea175303926055440c06bc8894f0c5c58afc8 (patch) | |
tree | 466af16058837ab4f8a83210848ecddac20705d9 | |
parent | 40bee2ee73c745922e9b2d5595c46f19d1cf1b6f (diff) |
[PATCH] i386: Support physical cpu hotplug for x86_64
This patch enables ACPI based physical CPU hotplug support for x86_64.
Implements acpi_map_lsapic() and acpi_unmap_lsapic() to support physical cpu
hotplug.
Signed-off-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Cc: Andi Kleen <ak@muc.de>
Cc: "Brown, Len" <len.brown@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
-rw-r--r-- | arch/i386/kernel/acpi/boot.c | 69 | ||||
-rw-r--r-- | arch/i386/kernel/mpparse.c | 2 | ||||
-rw-r--r-- | include/asm-i386/smp.h | 1 |
3 files changed, 67 insertions, 5 deletions
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 0fba420d668a..8a6c5b412348 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/acpi.h> | 27 | #include <linux/acpi.h> |
28 | #include <linux/efi.h> | 28 | #include <linux/efi.h> |
29 | #include <linux/cpumask.h> | ||
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
30 | #include <linux/dmi.h> | 31 | #include <linux/dmi.h> |
31 | #include <linux/irq.h> | 32 | #include <linux/irq.h> |
@@ -512,16 +513,76 @@ EXPORT_SYMBOL(acpi_register_gsi); | |||
512 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | 513 | #ifdef CONFIG_ACPI_HOTPLUG_CPU |
513 | int acpi_map_lsapic(acpi_handle handle, int *pcpu) | 514 | int acpi_map_lsapic(acpi_handle handle, int *pcpu) |
514 | { | 515 | { |
515 | /* TBD */ | 516 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
516 | return -EINVAL; | 517 | union acpi_object *obj; |
518 | struct acpi_table_lapic *lapic; | ||
519 | cpumask_t tmp_map, new_map; | ||
520 | u8 physid; | ||
521 | int cpu; | ||
522 | |||
523 | if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) | ||
524 | return -EINVAL; | ||
525 | |||
526 | if (!buffer.length || !buffer.pointer) | ||
527 | return -EINVAL; | ||
528 | |||
529 | obj = buffer.pointer; | ||
530 | if (obj->type != ACPI_TYPE_BUFFER || | ||
531 | obj->buffer.length < sizeof(*lapic)) { | ||
532 | kfree(buffer.pointer); | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | lapic = (struct acpi_table_lapic *)obj->buffer.pointer; | ||
537 | |||
538 | if ((lapic->header.type != ACPI_MADT_LAPIC) || | ||
539 | (!lapic->flags.enabled)) { | ||
540 | kfree(buffer.pointer); | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | |||
544 | physid = lapic->id; | ||
545 | |||
546 | kfree(buffer.pointer); | ||
547 | buffer.length = ACPI_ALLOCATE_BUFFER; | ||
548 | buffer.pointer = NULL; | ||
549 | |||
550 | tmp_map = cpu_present_map; | ||
551 | mp_register_lapic(physid, lapic->flags.enabled); | ||
552 | |||
553 | /* | ||
554 | * If mp_register_lapic successfully generates a new logical cpu | ||
555 | * number, then the following will get us exactly what was mapped | ||
556 | */ | ||
557 | cpus_andnot(new_map, cpu_present_map, tmp_map); | ||
558 | if (cpus_empty(new_map)) { | ||
559 | printk ("Unable to map lapic to logical cpu number\n"); | ||
560 | return -EINVAL; | ||
561 | } | ||
562 | |||
563 | cpu = first_cpu(new_map); | ||
564 | |||
565 | *pcpu = cpu; | ||
566 | return 0; | ||
517 | } | 567 | } |
518 | 568 | ||
519 | EXPORT_SYMBOL(acpi_map_lsapic); | 569 | EXPORT_SYMBOL(acpi_map_lsapic); |
520 | 570 | ||
521 | int acpi_unmap_lsapic(int cpu) | 571 | int acpi_unmap_lsapic(int cpu) |
522 | { | 572 | { |
523 | /* TBD */ | 573 | int i; |
524 | return -EINVAL; | 574 | |
575 | for_each_possible_cpu(i) { | ||
576 | if (x86_acpiid_to_apicid[i] == x86_cpu_to_apicid[cpu]) { | ||
577 | x86_acpiid_to_apicid[i] = -1; | ||
578 | break; | ||
579 | } | ||
580 | } | ||
581 | x86_cpu_to_apicid[cpu] = -1; | ||
582 | cpu_clear(cpu, cpu_present_map); | ||
583 | num_processors--; | ||
584 | |||
585 | return (0); | ||
525 | } | 586 | } |
526 | 587 | ||
527 | EXPORT_SYMBOL(acpi_unmap_lsapic); | 588 | EXPORT_SYMBOL(acpi_unmap_lsapic); |
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 772a4233bfe6..442aaf8c77eb 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c | |||
@@ -69,7 +69,7 @@ unsigned int def_to_bigsmp = 0; | |||
69 | /* Processor that is doing the boot up */ | 69 | /* Processor that is doing the boot up */ |
70 | unsigned int boot_cpu_physical_apicid = -1U; | 70 | unsigned int boot_cpu_physical_apicid = -1U; |
71 | /* Internal processor count */ | 71 | /* Internal processor count */ |
72 | static unsigned int __devinitdata num_processors; | 72 | unsigned int __cpuinitdata num_processors; |
73 | 73 | ||
74 | /* Bitmask of physically existing CPUs */ | 74 | /* Bitmask of physically existing CPUs */ |
75 | physid_mask_t phys_cpu_present_map; | 75 | physid_mask_t phys_cpu_present_map; |
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h index f87826039a51..32ac8c91d5c5 100644 --- a/include/asm-i386/smp.h +++ b/include/asm-i386/smp.h | |||
@@ -84,6 +84,7 @@ static inline int hard_smp_processor_id(void) | |||
84 | 84 | ||
85 | extern int __cpu_disable(void); | 85 | extern int __cpu_disable(void); |
86 | extern void __cpu_die(unsigned int cpu); | 86 | extern void __cpu_die(unsigned int cpu); |
87 | extern unsigned int num_processors; | ||
87 | 88 | ||
88 | #endif /* !__ASSEMBLY__ */ | 89 | #endif /* !__ASSEMBLY__ */ |
89 | 90 | ||