diff options
Diffstat (limited to 'arch/x86/kernel/acpi/boot.c')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 156 |
1 files changed, 92 insertions, 64 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index cd40aba6aa95..60cc4058ed5f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -63,7 +63,6 @@ EXPORT_SYMBOL(acpi_disabled); | |||
63 | int acpi_noirq; /* skip ACPI IRQ initialization */ | 63 | int acpi_noirq; /* skip ACPI IRQ initialization */ |
64 | int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ | 64 | int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ |
65 | EXPORT_SYMBOL(acpi_pci_disabled); | 65 | EXPORT_SYMBOL(acpi_pci_disabled); |
66 | int acpi_ht __initdata = 1; /* enable HT */ | ||
67 | 66 | ||
68 | int acpi_lapic; | 67 | int acpi_lapic; |
69 | int acpi_ioapic; | 68 | int acpi_ioapic; |
@@ -94,6 +93,53 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; | |||
94 | 93 | ||
95 | 94 | ||
96 | /* | 95 | /* |
96 | * ISA irqs by default are the first 16 gsis but can be | ||
97 | * any gsi as specified by an interrupt source override. | ||
98 | */ | ||
99 | static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = { | ||
100 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 | ||
101 | }; | ||
102 | |||
103 | static unsigned int gsi_to_irq(unsigned int gsi) | ||
104 | { | ||
105 | unsigned int irq = gsi + NR_IRQS_LEGACY; | ||
106 | unsigned int i; | ||
107 | |||
108 | for (i = 0; i < NR_IRQS_LEGACY; i++) { | ||
109 | if (isa_irq_to_gsi[i] == gsi) { | ||
110 | return i; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | /* Provide an identity mapping of gsi == irq | ||
115 | * except on truly weird platforms that have | ||
116 | * non isa irqs in the first 16 gsis. | ||
117 | */ | ||
118 | if (gsi >= NR_IRQS_LEGACY) | ||
119 | irq = gsi; | ||
120 | else | ||
121 | irq = gsi_end + 1 + gsi; | ||
122 | |||
123 | return irq; | ||
124 | } | ||
125 | |||
126 | static u32 irq_to_gsi(int irq) | ||
127 | { | ||
128 | unsigned int gsi; | ||
129 | |||
130 | if (irq < NR_IRQS_LEGACY) | ||
131 | gsi = isa_irq_to_gsi[irq]; | ||
132 | else if (irq <= gsi_end) | ||
133 | gsi = irq; | ||
134 | else if (irq <= (gsi_end + NR_IRQS_LEGACY)) | ||
135 | gsi = irq - gsi_end; | ||
136 | else | ||
137 | gsi = 0xffffffff; | ||
138 | |||
139 | return gsi; | ||
140 | } | ||
141 | |||
142 | /* | ||
97 | * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, | 143 | * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, |
98 | * to map the target physical address. The problem is that set_fixmap() | 144 | * to map the target physical address. The problem is that set_fixmap() |
99 | * provides a single page, and it is possible that the page is not | 145 | * provides a single page, and it is possible that the page is not |
@@ -313,7 +359,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) | |||
313 | /* | 359 | /* |
314 | * Parse Interrupt Source Override for the ACPI SCI | 360 | * Parse Interrupt Source Override for the ACPI SCI |
315 | */ | 361 | */ |
316 | static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) | 362 | static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, u32 gsi) |
317 | { | 363 | { |
318 | if (trigger == 0) /* compatible SCI trigger is level */ | 364 | if (trigger == 0) /* compatible SCI trigger is level */ |
319 | trigger = 3; | 365 | trigger = 3; |
@@ -333,7 +379,7 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) | |||
333 | * If GSI is < 16, this will update its flags, | 379 | * If GSI is < 16, this will update its flags, |
334 | * else it will create a new mp_irqs[] entry. | 380 | * else it will create a new mp_irqs[] entry. |
335 | */ | 381 | */ |
336 | mp_override_legacy_irq(gsi, polarity, trigger, gsi); | 382 | mp_override_legacy_irq(bus_irq, polarity, trigger, gsi); |
337 | 383 | ||
338 | /* | 384 | /* |
339 | * stash over-ride to indicate we've been here | 385 | * stash over-ride to indicate we've been here |
@@ -357,9 +403,10 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, | |||
357 | acpi_table_print_madt_entry(header); | 403 | acpi_table_print_madt_entry(header); |
358 | 404 | ||
359 | if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { | 405 | if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { |
360 | acpi_sci_ioapic_setup(intsrc->global_irq, | 406 | acpi_sci_ioapic_setup(intsrc->source_irq, |
361 | intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, | 407 | intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, |
362 | (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2); | 408 | (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2, |
409 | intsrc->global_irq); | ||
363 | return 0; | 410 | return 0; |
364 | } | 411 | } |
365 | 412 | ||
@@ -448,7 +495,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) | |||
448 | 495 | ||
449 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | 496 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) |
450 | { | 497 | { |
451 | *irq = gsi; | 498 | *irq = gsi_to_irq(gsi); |
452 | 499 | ||
453 | #ifdef CONFIG_X86_IO_APIC | 500 | #ifdef CONFIG_X86_IO_APIC |
454 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) | 501 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) |
@@ -458,6 +505,14 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | |||
458 | return 0; | 505 | return 0; |
459 | } | 506 | } |
460 | 507 | ||
508 | int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) | ||
509 | { | ||
510 | if (isa_irq >= 16) | ||
511 | return -1; | ||
512 | *gsi = irq_to_gsi(isa_irq); | ||
513 | return 0; | ||
514 | } | ||
515 | |||
461 | /* | 516 | /* |
462 | * success: return IRQ number (>=0) | 517 | * success: return IRQ number (>=0) |
463 | * failure: return < 0 | 518 | * failure: return < 0 |
@@ -482,7 +537,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
482 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); | 537 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); |
483 | } | 538 | } |
484 | #endif | 539 | #endif |
485 | irq = plat_gsi; | 540 | irq = gsi_to_irq(plat_gsi); |
486 | 541 | ||
487 | return irq; | 542 | return irq; |
488 | } | 543 | } |
@@ -867,29 +922,6 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
867 | extern int es7000_plat; | 922 | extern int es7000_plat; |
868 | #endif | 923 | #endif |
869 | 924 | ||
870 | int __init acpi_probe_gsi(void) | ||
871 | { | ||
872 | int idx; | ||
873 | int gsi; | ||
874 | int max_gsi = 0; | ||
875 | |||
876 | if (acpi_disabled) | ||
877 | return 0; | ||
878 | |||
879 | if (!acpi_ioapic) | ||
880 | return 0; | ||
881 | |||
882 | max_gsi = 0; | ||
883 | for (idx = 0; idx < nr_ioapics; idx++) { | ||
884 | gsi = mp_gsi_routing[idx].gsi_end; | ||
885 | |||
886 | if (gsi > max_gsi) | ||
887 | max_gsi = gsi; | ||
888 | } | ||
889 | |||
890 | return max_gsi + 1; | ||
891 | } | ||
892 | |||
893 | static void assign_to_mp_irq(struct mpc_intsrc *m, | 925 | static void assign_to_mp_irq(struct mpc_intsrc *m, |
894 | struct mpc_intsrc *mp_irq) | 926 | struct mpc_intsrc *mp_irq) |
895 | { | 927 | { |
@@ -947,13 +979,13 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | |||
947 | mp_irq.dstirq = pin; /* INTIN# */ | 979 | mp_irq.dstirq = pin; /* INTIN# */ |
948 | 980 | ||
949 | save_mp_irq(&mp_irq); | 981 | save_mp_irq(&mp_irq); |
982 | |||
983 | isa_irq_to_gsi[bus_irq] = gsi; | ||
950 | } | 984 | } |
951 | 985 | ||
952 | void __init mp_config_acpi_legacy_irqs(void) | 986 | void __init mp_config_acpi_legacy_irqs(void) |
953 | { | 987 | { |
954 | int i; | 988 | int i; |
955 | int ioapic; | ||
956 | unsigned int dstapic; | ||
957 | struct mpc_intsrc mp_irq; | 989 | struct mpc_intsrc mp_irq; |
958 | 990 | ||
959 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) | 991 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) |
@@ -974,19 +1006,27 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
974 | #endif | 1006 | #endif |
975 | 1007 | ||
976 | /* | 1008 | /* |
977 | * Locate the IOAPIC that manages the ISA IRQs (0-15). | ||
978 | */ | ||
979 | ioapic = mp_find_ioapic(0); | ||
980 | if (ioapic < 0) | ||
981 | return; | ||
982 | dstapic = mp_ioapics[ioapic].apicid; | ||
983 | |||
984 | /* | ||
985 | * Use the default configuration for the IRQs 0-15. Unless | 1009 | * Use the default configuration for the IRQs 0-15. Unless |
986 | * overridden by (MADT) interrupt source override entries. | 1010 | * overridden by (MADT) interrupt source override entries. |
987 | */ | 1011 | */ |
988 | for (i = 0; i < 16; i++) { | 1012 | for (i = 0; i < 16; i++) { |
1013 | int ioapic, pin; | ||
1014 | unsigned int dstapic; | ||
989 | int idx; | 1015 | int idx; |
1016 | u32 gsi; | ||
1017 | |||
1018 | /* Locate the gsi that irq i maps to. */ | ||
1019 | if (acpi_isa_irq_to_gsi(i, &gsi)) | ||
1020 | continue; | ||
1021 | |||
1022 | /* | ||
1023 | * Locate the IOAPIC that manages the ISA IRQ. | ||
1024 | */ | ||
1025 | ioapic = mp_find_ioapic(gsi); | ||
1026 | if (ioapic < 0) | ||
1027 | continue; | ||
1028 | pin = mp_find_ioapic_pin(ioapic, gsi); | ||
1029 | dstapic = mp_ioapics[ioapic].apicid; | ||
990 | 1030 | ||
991 | for (idx = 0; idx < mp_irq_entries; idx++) { | 1031 | for (idx = 0; idx < mp_irq_entries; idx++) { |
992 | struct mpc_intsrc *irq = mp_irqs + idx; | 1032 | struct mpc_intsrc *irq = mp_irqs + idx; |
@@ -996,7 +1036,7 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
996 | break; | 1036 | break; |
997 | 1037 | ||
998 | /* Do we already have a mapping for this IOAPIC pin */ | 1038 | /* Do we already have a mapping for this IOAPIC pin */ |
999 | if (irq->dstapic == dstapic && irq->dstirq == i) | 1039 | if (irq->dstapic == dstapic && irq->dstirq == pin) |
1000 | break; | 1040 | break; |
1001 | } | 1041 | } |
1002 | 1042 | ||
@@ -1011,7 +1051,7 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
1011 | mp_irq.dstapic = dstapic; | 1051 | mp_irq.dstapic = dstapic; |
1012 | mp_irq.irqtype = mp_INT; | 1052 | mp_irq.irqtype = mp_INT; |
1013 | mp_irq.srcbusirq = i; /* Identity mapped */ | 1053 | mp_irq.srcbusirq = i; /* Identity mapped */ |
1014 | mp_irq.dstirq = i; | 1054 | mp_irq.dstirq = pin; |
1015 | 1055 | ||
1016 | save_mp_irq(&mp_irq); | 1056 | save_mp_irq(&mp_irq); |
1017 | } | 1057 | } |
@@ -1076,11 +1116,6 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
1076 | 1116 | ||
1077 | ioapic_pin = mp_find_ioapic_pin(ioapic, gsi); | 1117 | ioapic_pin = mp_find_ioapic_pin(ioapic, gsi); |
1078 | 1118 | ||
1079 | #ifdef CONFIG_X86_32 | ||
1080 | if (ioapic_renumber_irq) | ||
1081 | gsi = ioapic_renumber_irq(ioapic, gsi); | ||
1082 | #endif | ||
1083 | |||
1084 | if (ioapic_pin > MP_MAX_IOAPIC_PIN) { | 1119 | if (ioapic_pin > MP_MAX_IOAPIC_PIN) { |
1085 | printk(KERN_ERR "Invalid reference to IOAPIC pin " | 1120 | printk(KERN_ERR "Invalid reference to IOAPIC pin " |
1086 | "%d-%d\n", mp_ioapics[ioapic].apicid, | 1121 | "%d-%d\n", mp_ioapics[ioapic].apicid, |
@@ -1094,7 +1129,7 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
1094 | set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin, | 1129 | set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin, |
1095 | trigger == ACPI_EDGE_SENSITIVE ? 0 : 1, | 1130 | trigger == ACPI_EDGE_SENSITIVE ? 0 : 1, |
1096 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | 1131 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); |
1097 | io_apic_set_pci_routing(dev, gsi, &irq_attr); | 1132 | io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr); |
1098 | 1133 | ||
1099 | return gsi; | 1134 | return gsi; |
1100 | } | 1135 | } |
@@ -1154,7 +1189,8 @@ static int __init acpi_parse_madt_ioapic_entries(void) | |||
1154 | * pretend we got one so we can set the SCI flags. | 1189 | * pretend we got one so we can set the SCI flags. |
1155 | */ | 1190 | */ |
1156 | if (!acpi_sci_override_gsi) | 1191 | if (!acpi_sci_override_gsi) |
1157 | acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0); | 1192 | acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0, |
1193 | acpi_gbl_FADT.sci_interrupt); | ||
1158 | 1194 | ||
1159 | /* Fill in identity legacy mappings where no override */ | 1195 | /* Fill in identity legacy mappings where no override */ |
1160 | mp_config_acpi_legacy_irqs(); | 1196 | mp_config_acpi_legacy_irqs(); |
@@ -1464,9 +1500,8 @@ void __init acpi_boot_table_init(void) | |||
1464 | 1500 | ||
1465 | /* | 1501 | /* |
1466 | * If acpi_disabled, bail out | 1502 | * If acpi_disabled, bail out |
1467 | * One exception: acpi=ht continues far enough to enumerate LAPICs | ||
1468 | */ | 1503 | */ |
1469 | if (acpi_disabled && !acpi_ht) | 1504 | if (acpi_disabled) |
1470 | return; | 1505 | return; |
1471 | 1506 | ||
1472 | /* | 1507 | /* |
@@ -1497,9 +1532,8 @@ int __init early_acpi_boot_init(void) | |||
1497 | { | 1532 | { |
1498 | /* | 1533 | /* |
1499 | * If acpi_disabled, bail out | 1534 | * If acpi_disabled, bail out |
1500 | * One exception: acpi=ht continues far enough to enumerate LAPICs | ||
1501 | */ | 1535 | */ |
1502 | if (acpi_disabled && !acpi_ht) | 1536 | if (acpi_disabled) |
1503 | return 1; | 1537 | return 1; |
1504 | 1538 | ||
1505 | /* | 1539 | /* |
@@ -1517,9 +1551,8 @@ int __init acpi_boot_init(void) | |||
1517 | 1551 | ||
1518 | /* | 1552 | /* |
1519 | * If acpi_disabled, bail out | 1553 | * If acpi_disabled, bail out |
1520 | * One exception: acpi=ht continues far enough to enumerate LAPICs | ||
1521 | */ | 1554 | */ |
1522 | if (acpi_disabled && !acpi_ht) | 1555 | if (acpi_disabled) |
1523 | return 1; | 1556 | return 1; |
1524 | 1557 | ||
1525 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); | 1558 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); |
@@ -1554,21 +1587,12 @@ static int __init parse_acpi(char *arg) | |||
1554 | /* acpi=force to over-ride black-list */ | 1587 | /* acpi=force to over-ride black-list */ |
1555 | else if (strcmp(arg, "force") == 0) { | 1588 | else if (strcmp(arg, "force") == 0) { |
1556 | acpi_force = 1; | 1589 | acpi_force = 1; |
1557 | acpi_ht = 1; | ||
1558 | acpi_disabled = 0; | 1590 | acpi_disabled = 0; |
1559 | } | 1591 | } |
1560 | /* acpi=strict disables out-of-spec workarounds */ | 1592 | /* acpi=strict disables out-of-spec workarounds */ |
1561 | else if (strcmp(arg, "strict") == 0) { | 1593 | else if (strcmp(arg, "strict") == 0) { |
1562 | acpi_strict = 1; | 1594 | acpi_strict = 1; |
1563 | } | 1595 | } |
1564 | /* Limit ACPI just to boot-time to enable HT */ | ||
1565 | else if (strcmp(arg, "ht") == 0) { | ||
1566 | if (!acpi_force) { | ||
1567 | printk(KERN_WARNING "acpi=ht will be removed in Linux-2.6.35\n"); | ||
1568 | disable_acpi(); | ||
1569 | } | ||
1570 | acpi_ht = 1; | ||
1571 | } | ||
1572 | /* acpi=rsdt use RSDT instead of XSDT */ | 1596 | /* acpi=rsdt use RSDT instead of XSDT */ |
1573 | else if (strcmp(arg, "rsdt") == 0) { | 1597 | else if (strcmp(arg, "rsdt") == 0) { |
1574 | acpi_rsdt_forced = 1; | 1598 | acpi_rsdt_forced = 1; |
@@ -1576,6 +1600,10 @@ static int __init parse_acpi(char *arg) | |||
1576 | /* "acpi=noirq" disables ACPI interrupt routing */ | 1600 | /* "acpi=noirq" disables ACPI interrupt routing */ |
1577 | else if (strcmp(arg, "noirq") == 0) { | 1601 | else if (strcmp(arg, "noirq") == 0) { |
1578 | acpi_noirq_set(); | 1602 | acpi_noirq_set(); |
1603 | } | ||
1604 | /* "acpi=copy_dsdt" copys DSDT */ | ||
1605 | else if (strcmp(arg, "copy_dsdt") == 0) { | ||
1606 | acpi_gbl_copy_dsdt_locally = 1; | ||
1579 | } else { | 1607 | } else { |
1580 | /* Core will printk when we return error. */ | 1608 | /* Core will printk when we return error. */ |
1581 | return -EINVAL; | 1609 | return -EINVAL; |