diff options
Diffstat (limited to 'arch/i386/kernel/acpi/boot.c')
-rw-r--r-- | arch/i386/kernel/acpi/boot.c | 181 |
1 files changed, 172 insertions, 9 deletions
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index ee003bc0e8b1..1aaea6ab8c46 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -26,9 +26,12 @@ | |||
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> |
33 | #include <linux/bootmem.h> | ||
34 | #include <linux/ioport.h> | ||
32 | 35 | ||
33 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
34 | #include <asm/io_apic.h> | 37 | #include <asm/io_apic.h> |
@@ -36,11 +39,17 @@ | |||
36 | #include <asm/io.h> | 39 | #include <asm/io.h> |
37 | #include <asm/mpspec.h> | 40 | #include <asm/mpspec.h> |
38 | 41 | ||
39 | #ifdef CONFIG_X86_64 | 42 | static int __initdata acpi_force = 0; |
40 | 43 | ||
41 | extern void __init clustered_apic_check(void); | 44 | #ifdef CONFIG_ACPI |
45 | int acpi_disabled = 0; | ||
46 | #else | ||
47 | int acpi_disabled = 1; | ||
48 | #endif | ||
49 | EXPORT_SYMBOL(acpi_disabled); | ||
50 | |||
51 | #ifdef CONFIG_X86_64 | ||
42 | 52 | ||
43 | extern int gsi_irq_sharing(int gsi); | ||
44 | #include <asm/proto.h> | 53 | #include <asm/proto.h> |
45 | 54 | ||
46 | static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; } | 55 | static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; } |
@@ -506,16 +515,76 @@ EXPORT_SYMBOL(acpi_register_gsi); | |||
506 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | 515 | #ifdef CONFIG_ACPI_HOTPLUG_CPU |
507 | int acpi_map_lsapic(acpi_handle handle, int *pcpu) | 516 | int acpi_map_lsapic(acpi_handle handle, int *pcpu) |
508 | { | 517 | { |
509 | /* TBD */ | 518 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
510 | return -EINVAL; | 519 | union acpi_object *obj; |
520 | struct acpi_table_lapic *lapic; | ||
521 | cpumask_t tmp_map, new_map; | ||
522 | u8 physid; | ||
523 | int cpu; | ||
524 | |||
525 | if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) | ||
526 | return -EINVAL; | ||
527 | |||
528 | if (!buffer.length || !buffer.pointer) | ||
529 | return -EINVAL; | ||
530 | |||
531 | obj = buffer.pointer; | ||
532 | if (obj->type != ACPI_TYPE_BUFFER || | ||
533 | obj->buffer.length < sizeof(*lapic)) { | ||
534 | kfree(buffer.pointer); | ||
535 | return -EINVAL; | ||
536 | } | ||
537 | |||
538 | lapic = (struct acpi_table_lapic *)obj->buffer.pointer; | ||
539 | |||
540 | if ((lapic->header.type != ACPI_MADT_LAPIC) || | ||
541 | (!lapic->flags.enabled)) { | ||
542 | kfree(buffer.pointer); | ||
543 | return -EINVAL; | ||
544 | } | ||
545 | |||
546 | physid = lapic->id; | ||
547 | |||
548 | kfree(buffer.pointer); | ||
549 | buffer.length = ACPI_ALLOCATE_BUFFER; | ||
550 | buffer.pointer = NULL; | ||
551 | |||
552 | tmp_map = cpu_present_map; | ||
553 | mp_register_lapic(physid, lapic->flags.enabled); | ||
554 | |||
555 | /* | ||
556 | * If mp_register_lapic successfully generates a new logical cpu | ||
557 | * number, then the following will get us exactly what was mapped | ||
558 | */ | ||
559 | cpus_andnot(new_map, cpu_present_map, tmp_map); | ||
560 | if (cpus_empty(new_map)) { | ||
561 | printk ("Unable to map lapic to logical cpu number\n"); | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | |||
565 | cpu = first_cpu(new_map); | ||
566 | |||
567 | *pcpu = cpu; | ||
568 | return 0; | ||
511 | } | 569 | } |
512 | 570 | ||
513 | EXPORT_SYMBOL(acpi_map_lsapic); | 571 | EXPORT_SYMBOL(acpi_map_lsapic); |
514 | 572 | ||
515 | int acpi_unmap_lsapic(int cpu) | 573 | int acpi_unmap_lsapic(int cpu) |
516 | { | 574 | { |
517 | /* TBD */ | 575 | int i; |
518 | return -EINVAL; | 576 | |
577 | for_each_possible_cpu(i) { | ||
578 | if (x86_acpiid_to_apicid[i] == x86_cpu_to_apicid[cpu]) { | ||
579 | x86_acpiid_to_apicid[i] = -1; | ||
580 | break; | ||
581 | } | ||
582 | } | ||
583 | x86_cpu_to_apicid[cpu] = -1; | ||
584 | cpu_clear(cpu, cpu_present_map); | ||
585 | num_processors--; | ||
586 | |||
587 | return (0); | ||
519 | } | 588 | } |
520 | 589 | ||
521 | EXPORT_SYMBOL(acpi_unmap_lsapic); | 590 | EXPORT_SYMBOL(acpi_unmap_lsapic); |
@@ -579,6 +648,8 @@ static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size) | |||
579 | static int __init acpi_parse_hpet(unsigned long phys, unsigned long size) | 648 | static int __init acpi_parse_hpet(unsigned long phys, unsigned long size) |
580 | { | 649 | { |
581 | struct acpi_table_hpet *hpet_tbl; | 650 | struct acpi_table_hpet *hpet_tbl; |
651 | struct resource *hpet_res; | ||
652 | resource_size_t res_start; | ||
582 | 653 | ||
583 | if (!phys || !size) | 654 | if (!phys || !size) |
584 | return -EINVAL; | 655 | return -EINVAL; |
@@ -594,12 +665,26 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size) | |||
594 | "memory.\n"); | 665 | "memory.\n"); |
595 | return -1; | 666 | return -1; |
596 | } | 667 | } |
668 | |||
669 | #define HPET_RESOURCE_NAME_SIZE 9 | ||
670 | hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE); | ||
671 | if (hpet_res) { | ||
672 | memset(hpet_res, 0, sizeof(*hpet_res)); | ||
673 | hpet_res->name = (void *)&hpet_res[1]; | ||
674 | hpet_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
675 | snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, | ||
676 | "HPET %u", hpet_tbl->number); | ||
677 | hpet_res->end = (1 * 1024) - 1; | ||
678 | } | ||
679 | |||
597 | #ifdef CONFIG_X86_64 | 680 | #ifdef CONFIG_X86_64 |
598 | vxtime.hpet_address = hpet_tbl->addr.addrl | | 681 | vxtime.hpet_address = hpet_tbl->addr.addrl | |
599 | ((long)hpet_tbl->addr.addrh << 32); | 682 | ((long)hpet_tbl->addr.addrh << 32); |
600 | 683 | ||
601 | printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", | 684 | printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", |
602 | hpet_tbl->id, vxtime.hpet_address); | 685 | hpet_tbl->id, vxtime.hpet_address); |
686 | |||
687 | res_start = vxtime.hpet_address; | ||
603 | #else /* X86 */ | 688 | #else /* X86 */ |
604 | { | 689 | { |
605 | extern unsigned long hpet_address; | 690 | extern unsigned long hpet_address; |
@@ -607,9 +692,17 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size) | |||
607 | hpet_address = hpet_tbl->addr.addrl; | 692 | hpet_address = hpet_tbl->addr.addrl; |
608 | printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", | 693 | printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n", |
609 | hpet_tbl->id, hpet_address); | 694 | hpet_tbl->id, hpet_address); |
695 | |||
696 | res_start = hpet_address; | ||
610 | } | 697 | } |
611 | #endif /* X86 */ | 698 | #endif /* X86 */ |
612 | 699 | ||
700 | if (hpet_res) { | ||
701 | hpet_res->start = res_start; | ||
702 | hpet_res->end += res_start; | ||
703 | insert_resource(&iomem_resource, hpet_res); | ||
704 | } | ||
705 | |||
613 | return 0; | 706 | return 0; |
614 | } | 707 | } |
615 | #else | 708 | #else |
@@ -860,8 +953,6 @@ static void __init acpi_process_madt(void) | |||
860 | return; | 953 | return; |
861 | } | 954 | } |
862 | 955 | ||
863 | extern int acpi_force; | ||
864 | |||
865 | #ifdef __i386__ | 956 | #ifdef __i386__ |
866 | 957 | ||
867 | static int __init disable_acpi_irq(struct dmi_system_id *d) | 958 | static int __init disable_acpi_irq(struct dmi_system_id *d) |
@@ -1163,3 +1254,75 @@ int __init acpi_boot_init(void) | |||
1163 | 1254 | ||
1164 | return 0; | 1255 | return 0; |
1165 | } | 1256 | } |
1257 | |||
1258 | static int __init parse_acpi(char *arg) | ||
1259 | { | ||
1260 | if (!arg) | ||
1261 | return -EINVAL; | ||
1262 | |||
1263 | /* "acpi=off" disables both ACPI table parsing and interpreter */ | ||
1264 | if (strcmp(arg, "off") == 0) { | ||
1265 | disable_acpi(); | ||
1266 | } | ||
1267 | /* acpi=force to over-ride black-list */ | ||
1268 | else if (strcmp(arg, "force") == 0) { | ||
1269 | acpi_force = 1; | ||
1270 | acpi_ht = 1; | ||
1271 | acpi_disabled = 0; | ||
1272 | } | ||
1273 | /* acpi=strict disables out-of-spec workarounds */ | ||
1274 | else if (strcmp(arg, "strict") == 0) { | ||
1275 | acpi_strict = 1; | ||
1276 | } | ||
1277 | /* Limit ACPI just to boot-time to enable HT */ | ||
1278 | else if (strcmp(arg, "ht") == 0) { | ||
1279 | if (!acpi_force) | ||
1280 | disable_acpi(); | ||
1281 | acpi_ht = 1; | ||
1282 | } | ||
1283 | /* "acpi=noirq" disables ACPI interrupt routing */ | ||
1284 | else if (strcmp(arg, "noirq") == 0) { | ||
1285 | acpi_noirq_set(); | ||
1286 | } else { | ||
1287 | /* Core will printk when we return error. */ | ||
1288 | return -EINVAL; | ||
1289 | } | ||
1290 | return 0; | ||
1291 | } | ||
1292 | early_param("acpi", parse_acpi); | ||
1293 | |||
1294 | /* FIXME: Using pci= for an ACPI parameter is a travesty. */ | ||
1295 | static int __init parse_pci(char *arg) | ||
1296 | { | ||
1297 | if (arg && strcmp(arg, "noacpi") == 0) | ||
1298 | acpi_disable_pci(); | ||
1299 | return 0; | ||
1300 | } | ||
1301 | early_param("pci", parse_pci); | ||
1302 | |||
1303 | #ifdef CONFIG_X86_IO_APIC | ||
1304 | static int __init parse_acpi_skip_timer_override(char *arg) | ||
1305 | { | ||
1306 | acpi_skip_timer_override = 1; | ||
1307 | return 0; | ||
1308 | } | ||
1309 | early_param("acpi_skip_timer_override", parse_acpi_skip_timer_override); | ||
1310 | #endif /* CONFIG_X86_IO_APIC */ | ||
1311 | |||
1312 | static int __init setup_acpi_sci(char *s) | ||
1313 | { | ||
1314 | if (!s) | ||
1315 | return -EINVAL; | ||
1316 | if (!strcmp(s, "edge")) | ||
1317 | acpi_sci_flags.trigger = 1; | ||
1318 | else if (!strcmp(s, "level")) | ||
1319 | acpi_sci_flags.trigger = 3; | ||
1320 | else if (!strcmp(s, "high")) | ||
1321 | acpi_sci_flags.polarity = 1; | ||
1322 | else if (!strcmp(s, "low")) | ||
1323 | acpi_sci_flags.polarity = 3; | ||
1324 | else | ||
1325 | return -EINVAL; | ||
1326 | return 0; | ||
1327 | } | ||
1328 | early_param("acpi_sci", setup_acpi_sci); | ||