diff options
Diffstat (limited to 'arch/i386/kernel/acpi/boot.c')
-rw-r--r-- | arch/i386/kernel/acpi/boot.c | 69 |
1 files changed, 65 insertions, 4 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); |