Commit 73fea175303926055440c06bc8894f0c5c58afc8

Authored by Ashok Raj
Committed by Andi Kleen
1 parent 40bee2ee73

[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>

Showing 3 changed files with 67 additions and 5 deletions Side-by-side Diff

arch/i386/kernel/acpi/boot.c
... ... @@ -26,6 +26,7 @@
26 26 #include <linux/init.h>
27 27 #include <linux/acpi.h>
28 28 #include <linux/efi.h>
  29 +#include <linux/cpumask.h>
29 30 #include <linux/module.h>
30 31 #include <linux/dmi.h>
31 32 #include <linux/irq.h>
32 33  
... ... @@ -512,16 +513,76 @@
512 513 #ifdef CONFIG_ACPI_HOTPLUG_CPU
513 514 int acpi_map_lsapic(acpi_handle handle, int *pcpu)
514 515 {
515   - /* TBD */
516   - return -EINVAL;
  516 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  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 569 EXPORT_SYMBOL(acpi_map_lsapic);
520 570  
521 571 int acpi_unmap_lsapic(int cpu)
522 572 {
523   - /* TBD */
524   - return -EINVAL;
  573 + int i;
  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 588 EXPORT_SYMBOL(acpi_unmap_lsapic);
arch/i386/kernel/mpparse.c
... ... @@ -69,7 +69,7 @@
69 69 /* Processor that is doing the boot up */
70 70 unsigned int boot_cpu_physical_apicid = -1U;
71 71 /* Internal processor count */
72   -static unsigned int __devinitdata num_processors;
  72 +unsigned int __cpuinitdata num_processors;
73 73  
74 74 /* Bitmask of physically existing CPUs */
75 75 physid_mask_t phys_cpu_present_map;
include/asm-i386/smp.h
... ... @@ -84,6 +84,7 @@
84 84  
85 85 extern int __cpu_disable(void);
86 86 extern void __cpu_die(unsigned int cpu);
  87 +extern unsigned int num_processors;
87 88  
88 89 #endif /* !__ASSEMBLY__ */
89 90