Commit 73fea175303926055440c06bc8894f0c5c58afc8
Committed by
Andi Kleen
1 parent
40bee2ee73
Exists in
master
and in
4 other branches
[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; |