diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-06-01 18:13:02 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-06-01 18:25:31 -0400 |
commit | 48b1fddbb100a64f3983ca9768b8ea629a09aa20 (patch) | |
tree | 7cf552c623cb0aa0dd945df55b7eaf5a0697e277 /arch/x86/kernel/acpi/boot.c | |
parent | 38736072d45488fd45f076388b6570419bbbc682 (diff) | |
parent | ee4c24a5c9b530481394132c8dbc10572d57c075 (diff) |
Merge branch 'irq/numa' into x86/mce3
Merge reason: arch/x86/kernel/irqinit_{32,64}.c unified in irq/numa
and modified in x86/mce3; this merge resolves the conflict.
Conflicts:
arch/x86/kernel/irqinit.c
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/acpi/boot.c')
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 151 |
1 files changed, 52 insertions, 99 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 723989d7f80..844e5e25213 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/irq.h> | 33 | #include <linux/irq.h> |
34 | #include <linux/bootmem.h> | 34 | #include <linux/bootmem.h> |
35 | #include <linux/ioport.h> | 35 | #include <linux/ioport.h> |
36 | #include <linux/pci.h> | ||
36 | 37 | ||
37 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
38 | #include <asm/io_apic.h> | 39 | #include <asm/io_apic.h> |
@@ -522,7 +523,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) | |||
522 | * success: return IRQ number (>=0) | 523 | * success: return IRQ number (>=0) |
523 | * failure: return < 0 | 524 | * failure: return < 0 |
524 | */ | 525 | */ |
525 | int acpi_register_gsi(u32 gsi, int triggering, int polarity) | 526 | int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) |
526 | { | 527 | { |
527 | unsigned int irq; | 528 | unsigned int irq; |
528 | unsigned int plat_gsi = gsi; | 529 | unsigned int plat_gsi = gsi; |
@@ -532,14 +533,14 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity) | |||
532 | * Make sure all (legacy) PCI IRQs are set as level-triggered. | 533 | * Make sure all (legacy) PCI IRQs are set as level-triggered. |
533 | */ | 534 | */ |
534 | if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { | 535 | if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) { |
535 | if (triggering == ACPI_LEVEL_SENSITIVE) | 536 | if (trigger == ACPI_LEVEL_SENSITIVE) |
536 | eisa_set_level_irq(gsi); | 537 | eisa_set_level_irq(gsi); |
537 | } | 538 | } |
538 | #endif | 539 | #endif |
539 | 540 | ||
540 | #ifdef CONFIG_X86_IO_APIC | 541 | #ifdef CONFIG_X86_IO_APIC |
541 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { | 542 | if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) { |
542 | plat_gsi = mp_register_gsi(gsi, triggering, polarity); | 543 | plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); |
543 | } | 544 | } |
544 | #endif | 545 | #endif |
545 | acpi_gsi_to_irq(plat_gsi, &irq); | 546 | acpi_gsi_to_irq(plat_gsi, &irq); |
@@ -903,10 +904,8 @@ extern int es7000_plat; | |||
903 | #endif | 904 | #endif |
904 | 905 | ||
905 | static struct { | 906 | static struct { |
906 | int apic_id; | ||
907 | int gsi_base; | 907 | int gsi_base; |
908 | int gsi_end; | 908 | int gsi_end; |
909 | DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); | ||
910 | } mp_ioapic_routing[MAX_IO_APICS]; | 909 | } mp_ioapic_routing[MAX_IO_APICS]; |
911 | 910 | ||
912 | int mp_find_ioapic(int gsi) | 911 | int mp_find_ioapic(int gsi) |
@@ -995,7 +994,6 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) | |||
995 | * Build basic GSI lookup table to facilitate gsi->io_apic lookups | 994 | * Build basic GSI lookup table to facilitate gsi->io_apic lookups |
996 | * and to prevent reprogramming of IOAPIC pins (PCI GSIs). | 995 | * and to prevent reprogramming of IOAPIC pins (PCI GSIs). |
997 | */ | 996 | */ |
998 | mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid; | ||
999 | mp_ioapic_routing[idx].gsi_base = gsi_base; | 997 | mp_ioapic_routing[idx].gsi_base = gsi_base; |
1000 | mp_ioapic_routing[idx].gsi_end = gsi_base + | 998 | mp_ioapic_routing[idx].gsi_end = gsi_base + |
1001 | io_apic_get_redir_entries(idx); | 999 | io_apic_get_redir_entries(idx); |
@@ -1158,26 +1156,52 @@ void __init mp_config_acpi_legacy_irqs(void) | |||
1158 | } | 1156 | } |
1159 | } | 1157 | } |
1160 | 1158 | ||
1161 | int mp_register_gsi(u32 gsi, int triggering, int polarity) | 1159 | static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger, |
1160 | int polarity) | ||
1162 | { | 1161 | { |
1162 | #ifdef CONFIG_X86_MPPARSE | ||
1163 | struct mpc_intsrc mp_irq; | ||
1164 | struct pci_dev *pdev; | ||
1165 | unsigned char number; | ||
1166 | unsigned int devfn; | ||
1163 | int ioapic; | 1167 | int ioapic; |
1164 | int ioapic_pin; | 1168 | u8 pin; |
1165 | #ifdef CONFIG_X86_32 | ||
1166 | #define MAX_GSI_NUM 4096 | ||
1167 | #define IRQ_COMPRESSION_START 64 | ||
1168 | 1169 | ||
1169 | static int pci_irq = IRQ_COMPRESSION_START; | 1170 | if (!acpi_ioapic) |
1170 | /* | 1171 | return 0; |
1171 | * Mapping between Global System Interrupts, which | 1172 | if (!dev) |
1172 | * represent all possible interrupts, and IRQs | 1173 | return 0; |
1173 | * assigned to actual devices. | 1174 | if (dev->bus != &pci_bus_type) |
1174 | */ | 1175 | return 0; |
1175 | static int gsi_to_irq[MAX_GSI_NUM]; | 1176 | |
1176 | #else | 1177 | pdev = to_pci_dev(dev); |
1178 | number = pdev->bus->number; | ||
1179 | devfn = pdev->devfn; | ||
1180 | pin = pdev->pin; | ||
1181 | /* print the entry should happen on mptable identically */ | ||
1182 | mp_irq.type = MP_INTSRC; | ||
1183 | mp_irq.irqtype = mp_INT; | ||
1184 | mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) | | ||
1185 | (polarity == ACPI_ACTIVE_HIGH ? 1 : 3); | ||
1186 | mp_irq.srcbus = number; | ||
1187 | mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); | ||
1188 | ioapic = mp_find_ioapic(gsi); | ||
1189 | mp_irq.dstapic = mp_ioapics[ioapic].apicid; | ||
1190 | mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); | ||
1191 | |||
1192 | save_mp_irq(&mp_irq); | ||
1193 | #endif | ||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) | ||
1198 | { | ||
1199 | int ioapic; | ||
1200 | int ioapic_pin; | ||
1201 | struct io_apic_irq_attr irq_attr; | ||
1177 | 1202 | ||
1178 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) | 1203 | if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC) |
1179 | return gsi; | 1204 | return gsi; |
1180 | #endif | ||
1181 | 1205 | ||
1182 | /* Don't set up the ACPI SCI because it's already set up */ | 1206 | /* Don't set up the ACPI SCI because it's already set up */ |
1183 | if (acpi_gbl_FADT.sci_interrupt == gsi) | 1207 | if (acpi_gbl_FADT.sci_interrupt == gsi) |
@@ -1196,93 +1220,22 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
1196 | gsi = ioapic_renumber_irq(ioapic, gsi); | 1220 | gsi = ioapic_renumber_irq(ioapic, gsi); |
1197 | #endif | 1221 | #endif |
1198 | 1222 | ||
1199 | /* | ||
1200 | * Avoid pin reprogramming. PRTs typically include entries | ||
1201 | * with redundant pin->gsi mappings (but unique PCI devices); | ||
1202 | * we only program the IOAPIC on the first. | ||
1203 | */ | ||
1204 | if (ioapic_pin > MP_MAX_IOAPIC_PIN) { | 1223 | if (ioapic_pin > MP_MAX_IOAPIC_PIN) { |
1205 | printk(KERN_ERR "Invalid reference to IOAPIC pin " | 1224 | printk(KERN_ERR "Invalid reference to IOAPIC pin " |
1206 | "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, | 1225 | "%d-%d\n", mp_ioapics[ioapic].apicid, |
1207 | ioapic_pin); | 1226 | ioapic_pin); |
1208 | return gsi; | 1227 | return gsi; |
1209 | } | 1228 | } |
1210 | if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) { | ||
1211 | pr_debug("Pin %d-%d already programmed\n", | ||
1212 | mp_ioapic_routing[ioapic].apic_id, ioapic_pin); | ||
1213 | #ifdef CONFIG_X86_32 | ||
1214 | return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]); | ||
1215 | #else | ||
1216 | return gsi; | ||
1217 | #endif | ||
1218 | } | ||
1219 | |||
1220 | set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed); | ||
1221 | #ifdef CONFIG_X86_32 | ||
1222 | /* | ||
1223 | * For GSI >= 64, use IRQ compression | ||
1224 | */ | ||
1225 | if ((gsi >= IRQ_COMPRESSION_START) | ||
1226 | && (triggering == ACPI_LEVEL_SENSITIVE)) { | ||
1227 | /* | ||
1228 | * For PCI devices assign IRQs in order, avoiding gaps | ||
1229 | * due to unused I/O APIC pins. | ||
1230 | */ | ||
1231 | int irq = gsi; | ||
1232 | if (gsi < MAX_GSI_NUM) { | ||
1233 | /* | ||
1234 | * Retain the VIA chipset work-around (gsi > 15), but | ||
1235 | * avoid a problem where the 8254 timer (IRQ0) is setup | ||
1236 | * via an override (so it's not on pin 0 of the ioapic), | ||
1237 | * and at the same time, the pin 0 interrupt is a PCI | ||
1238 | * type. The gsi > 15 test could cause these two pins | ||
1239 | * to be shared as IRQ0, and they are not shareable. | ||
1240 | * So test for this condition, and if necessary, avoid | ||
1241 | * the pin collision. | ||
1242 | */ | ||
1243 | gsi = pci_irq++; | ||
1244 | /* | ||
1245 | * Don't assign IRQ used by ACPI SCI | ||
1246 | */ | ||
1247 | if (gsi == acpi_gbl_FADT.sci_interrupt) | ||
1248 | gsi = pci_irq++; | ||
1249 | gsi_to_irq[irq] = gsi; | ||
1250 | } else { | ||
1251 | printk(KERN_ERR "GSI %u is too high\n", gsi); | ||
1252 | return gsi; | ||
1253 | } | ||
1254 | } | ||
1255 | #endif | ||
1256 | io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, | ||
1257 | triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, | ||
1258 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); | ||
1259 | return gsi; | ||
1260 | } | ||
1261 | |||
1262 | int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, | ||
1263 | u32 gsi, int triggering, int polarity) | ||
1264 | { | ||
1265 | #ifdef CONFIG_X86_MPPARSE | ||
1266 | struct mpc_intsrc mp_irq; | ||
1267 | int ioapic; | ||
1268 | 1229 | ||
1269 | if (!acpi_ioapic) | 1230 | if (enable_update_mptable) |
1270 | return 0; | 1231 | mp_config_acpi_gsi(dev, gsi, trigger, polarity); |
1271 | 1232 | ||
1272 | /* print the entry should happen on mptable identically */ | 1233 | set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin, |
1273 | mp_irq.type = MP_INTSRC; | 1234 | trigger == ACPI_EDGE_SENSITIVE ? 0 : 1, |
1274 | mp_irq.irqtype = mp_INT; | 1235 | polarity == ACPI_ACTIVE_HIGH ? 0 : 1); |
1275 | mp_irq.irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) | | 1236 | io_apic_set_pci_routing(dev, gsi, &irq_attr); |
1276 | (polarity == ACPI_ACTIVE_HIGH ? 1 : 3); | ||
1277 | mp_irq.srcbus = number; | ||
1278 | mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3); | ||
1279 | ioapic = mp_find_ioapic(gsi); | ||
1280 | mp_irq.dstapic = mp_ioapic_routing[ioapic].apic_id; | ||
1281 | mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi); | ||
1282 | 1237 | ||
1283 | save_mp_irq(&mp_irq); | 1238 | return gsi; |
1284 | #endif | ||
1285 | return 0; | ||
1286 | } | 1239 | } |
1287 | 1240 | ||
1288 | /* | 1241 | /* |