diff options
Diffstat (limited to 'arch/x86/kernel/acpi/boot.c')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 133 |
1 files changed, 85 insertions, 48 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index cd40aba6aa95..9a5ed58f09dc 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -94,6 +94,53 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; | |||
94 | 94 | ||
95 | 95 | ||
96 | /* | 96 | /* |
97 | * ISA irqs by default are the first 16 gsis but can be | ||
98 | * any gsi as specified by an interrupt source override. | ||
99 | */ | ||
100 | static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = { | ||
101 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 | ||
102 | }; | ||
103 | |||
104 | static unsigned int gsi_to_irq(unsigned int gsi) | ||
105 | { | ||
106 | unsigned int irq = gsi + NR_IRQS_LEGACY; | ||
107 | unsigned int i; | ||
108 | |||
109 | for (i = 0; i < NR_IRQS_LEGACY; i++) { | ||
110 | if (isa_irq_to_gsi[i] == gsi) { | ||
111 | return i; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* Provide an identity mapping of gsi == irq | ||
116 | * except on truly weird platforms that have | ||
117 | * non isa irqs in the first 16 gsis. | ||
118 | */ | ||
119 | if (gsi >= NR_IRQS_LEGACY) | ||
120 | irq = gsi; | ||
121 | else | ||
122 | irq = gsi_end + 1 + gsi; | ||
123 | |||
124 | return irq; | ||
125 | } | ||
126 | |||
127 | static u32 irq_to_gsi(int irq) | ||
128 | { | ||
129 | unsigned int gsi; | ||
130 | |||
131 | if (irq < NR_IRQS_LEGACY) | ||
132 | gsi = isa_irq_to_gsi[irq]; | ||
133 | else if (irq <= gsi_end) | ||
134 | gsi = irq; | ||
135 | else if (irq <= (gsi_end + NR_IRQS_LEGACY)) | ||
136 | gsi = irq - gsi_end; | ||
137 | else | ||
138 | gsi = 0xffffffff; | ||
139 | |||
140 | return gsi; | ||
141 | } | ||
142 | |||
143 | /* | ||
97 | * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, | 144 | * 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() | 145 | * 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 | 146 | * provides a single page, and it is possible that the page is not |
@@ -313,7 +360,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) | |||
313 | /* | 360 | /* |
314 | * Parse Interrupt Source Override for the ACPI SCI | 361 | * Parse Interrupt Source Override for the ACPI SCI |
315 | */ | 362 | */ |
316 | static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) | 363 | static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, u32 gsi) |
317 | { | 364 | { |
318 | if (trigger == 0) /* compatible SCI trigger is level */ | 365 | if (trigger == 0) /* compatible SCI trigger is level */ |
319 | trigger = 3; | 366 | trigger = 3; |
@@ -333,7 +380,7 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) | |||
333 | * If GSI is < 16, this will update its flags, | 380 | * If GSI is < 16, this will update its flags, |
334 | * else it will create a new mp_irqs[] entry. | 381 | * else it will create a new mp_irqs[] entry. |
335 | */ | 382 | */ |
336 | mp_override_legacy_irq(gsi, polarity, trigger, gsi); | 383 | mp_override_legacy_irq(bus_irq, polarity, trigger, gsi); |
337 | 384 | ||
338 | /* | 385 | /* |
339 | * stash over-ride to indicate we've been here | 386 | * stash over-ride to indicate we've been here |
@@ -357,9 +404,10 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, | |||
357 | acpi_table_print_madt_entry(header); | 404 | acpi_table_print_madt_entry(header); |
358 | 405 | ||
359 | if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { | 406 | if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { |
360 | acpi_sci_ioapic_setup(intsrc->global_irq, | 407 | acpi_sci_ioapic_setup(intsrc->source_irq, |
361 | intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, | 408 | intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, |
362 | (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2); | 409 | (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2, |
410 | intsrc->global_irq); | ||
363 | return 0; | 411 | return 0; |
364 | } | 412 | } |
365 | 413 | ||
@@ -448,7 +496,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) | |||
448 | 496 | ||
449 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | 497 | int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) |
450 | { | 498 | { |
451 | *irq = gsi; | 499 | *irq = gsi_to_irq(gsi); |
452 | 500 | ||
453 | #ifdef CONFIG_X86_IO_APIC | 501 | #ifdef CONFIG_X86_IO_APIC |
454 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) | 502 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) |
@@ -458,6 +506,14 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | |||
458 | return 0; | 506 | return 0; |
459 | } | 507 | } |
460 | 508 | ||
509 | int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) | ||
510 | { | ||
511 | if (isa_irq >= 16) | ||
512 | return -1; | ||
513 | *gsi = irq_to_gsi(isa_irq); | ||
514 | return 0; | ||
515 | } | ||
516 | |||
461 | /* | 517 | /* |
462 | * success: return IRQ number (>=0) | 518 | * success: return IRQ number (>=0) |
463 | * failure: return < 0 | 519 | * failure: return < 0 |
@@ -482,7 +538,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
482 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); | 538 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); |
483 | } | 539 | } |
484 | #endif | 540 | #endif |
485 | irq = plat_gsi; | 541 | irq = gsi_to_irq(plat_gsi); |
486 | 542 | ||
487 | return irq; | 543 | return irq; |
488 | } | 544 | } |
@@ -867,29 +923,6 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
867 | extern int es7000_plat; | 923 | extern int es7000_plat; |
868 | #endif | 924 | #endif |
869 | 925 | ||
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, | 926 | static void assign_to_mp_irq(struct mpc_intsrc *m, |
894 | struct mpc_intsrc *mp_irq) | 927 | struct mpc_intsrc *mp_irq) |
895 | { | 928 | { |
@@ -947,13 +980,13 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) | |||
947 | mp_irq.dstirq = pin; /* INTIN# */ | 980 | mp_irq.dstirq = pin; /* INTIN# */ |
948 | 981 | ||
949 | save_mp_irq(&mp_irq); | 982 | save_mp_irq(&mp_irq); |
983 | |||
984 | isa_irq_to_gsi[bus_irq] = gsi; | ||
950 | } | 985 | } |
951 | 986 | ||
952 | void __init mp_config_acpi_legacy_irqs(void) | 987 | void __init mp_config_acpi_legacy_irqs(void) |
953 | { | 988 | { |
954 | int i; | 989 | int i; |
955 | int ioapic; | ||
956 | unsigned int dstapic; | ||
957 | struct mpc_intsrc mp_irq; | 990 | struct mpc_intsrc mp_irq; |
958 | 991 | ||
959 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) | 992 | #if defined (CONFIG_MCA) || defined (CONFIG_EISA) |
@@ -974,19 +1007,27 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
974 | #endif | 1007 | #endif |
975 | 1008 | ||
976 | /* | 1009 | /* |
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 | 1010 | * Use the default configuration for the IRQs 0-15. Unless |
986 | * overridden by (MADT) interrupt source override entries. | 1011 | * overridden by (MADT) interrupt source override entries. |
987 | */ | 1012 | */ |
988 | for (i = 0; i < 16; i++) { | 1013 | for (i = 0; i < 16; i++) { |
1014 | int ioapic, pin; | ||
1015 | unsigned int dstapic; | ||
989 | int idx; | 1016 | int idx; |
1017 | u32 gsi; | ||
1018 | |||
1019 | /* Locate the gsi that irq i maps to. */ | ||
1020 | if (acpi_isa_irq_to_gsi(i, &gsi)) | ||
1021 | continue; | ||
1022 | |||
1023 | /* | ||
1024 | * Locate the IOAPIC that manages the ISA IRQ. | ||
1025 | */ | ||
1026 | ioapic = mp_find_ioapic(gsi); | ||
1027 | if (ioapic < 0) | ||
1028 | continue; | ||
1029 | pin = mp_find_ioapic_pin(ioapic, gsi); | ||
1030 | dstapic = mp_ioapics[ioapic].apicid; | ||
990 | 1031 | ||
991 | for (idx = 0; idx < mp_irq_entries; idx++) { | 1032 | for (idx = 0; idx < mp_irq_entries; idx++) { |
992 | struct mpc_intsrc *irq = mp_irqs + idx; | 1033 | struct mpc_intsrc *irq = mp_irqs + idx; |
@@ -996,7 +1037,7 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
996 | break; | 1037 | break; |
997 | 1038 | ||
998 | /* Do we already have a mapping for this IOAPIC pin */ | 1039 | /* Do we already have a mapping for this IOAPIC pin */ |
999 | if (irq->dstapic == dstapic && irq->dstirq == i) | 1040 | if (irq->dstapic == dstapic && irq->dstirq == pin) |
1000 | break; | 1041 | break; |
1001 | } | 1042 | } |
1002 | 1043 | ||
@@ -1011,7 +1052,7 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
1011 | mp_irq.dstapic = dstapic; | 1052 | mp_irq.dstapic = dstapic; |
1012 | mp_irq.irqtype = mp_INT; | 1053 | mp_irq.irqtype = mp_INT; |
1013 | mp_irq.srcbusirq = i; /* Identity mapped */ | 1054 | mp_irq.srcbusirq = i; /* Identity mapped */ |
1014 | mp_irq.dstirq = i; | 1055 | mp_irq.dstirq = pin; |
1015 | 1056 | ||
1016 | save_mp_irq(&mp_irq); | 1057 | save_mp_irq(&mp_irq); |
1017 | } | 1058 | } |
@@ -1076,11 +1117,6 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | |||
1076 | 1117 | ||
1077 | ioapic_pin = mp_find_ioapic_pin(ioapic, gsi); | 1118 | ioapic_pin = mp_find_ioapic_pin(ioapic, gsi); |
1078 | 1119 | ||
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) { | 1120 | if (ioapic_pin > MP_MAX_IOAPIC_PIN) { |
1085 | printk(KERN_ERR "Invalid reference to IOAPIC pin " | 1121 | printk(KERN_ERR "Invalid reference to IOAPIC pin " |
1086 | "%d-%d\n", mp_ioapics[ioapic].apicid, | 1122 | "%d-%d\n", mp_ioapics[ioapic].apicid, |
@@ -1094,7 +1130,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, | 1130 | set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin, |
1095 | trigger == ACPI_EDGE_SENSITIVE ? 0 : 1, | 1131 | trigger == ACPI_EDGE_SENSITIVE ? 0 : 1, |
1096 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | 1132 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); |
1097 | io_apic_set_pci_routing(dev, gsi, &irq_attr); | 1133 | io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr); |
1098 | 1134 | ||
1099 | return gsi; | 1135 | return gsi; |
1100 | } | 1136 | } |
@@ -1154,7 +1190,8 @@ static int __init acpi_parse_madt_ioapic_entries(void) | |||
1154 | * pretend we got one so we can set the SCI flags. | 1190 | * pretend we got one so we can set the SCI flags. |
1155 | */ | 1191 | */ |
1156 | if (!acpi_sci_override_gsi) | 1192 | if (!acpi_sci_override_gsi) |
1157 | acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0); | 1193 | acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0, |
1194 | acpi_gbl_FADT.sci_interrupt); | ||
1158 | 1195 | ||
1159 | /* Fill in identity legacy mappings where no override */ | 1196 | /* Fill in identity legacy mappings where no override */ |
1160 | mp_config_acpi_legacy_irqs(); | 1197 | mp_config_acpi_legacy_irqs(); |