aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/pci_irq.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index f907cfbfa13c..7f9eba9a0b02 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -303,6 +303,61 @@ void acpi_pci_irq_del_prt(struct pci_bus *bus)
303/* -------------------------------------------------------------------------- 303/* --------------------------------------------------------------------------
304 PCI Interrupt Routing Support 304 PCI Interrupt Routing Support
305 -------------------------------------------------------------------------- */ 305 -------------------------------------------------------------------------- */
306#ifdef CONFIG_X86_IO_APIC
307extern int noioapicquirk;
308extern int noioapicreroute;
309
310static int bridge_has_boot_interrupt_variant(struct pci_bus *bus)
311{
312 struct pci_bus *bus_it;
313
314 for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) {
315 if (!bus_it->self)
316 return 0;
317 if (bus_it->self->irq_reroute_variant)
318 return bus_it->self->irq_reroute_variant;
319 }
320 return 0;
321}
322
323/*
324 * Some chipsets (e.g. Intel 6700PXH) generate a legacy INTx when the IRQ
325 * entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel does
326 * during interrupt handling). When this INTx generation cannot be disabled,
327 * we reroute these interrupts to their legacy equivalent to get rid of
328 * spurious interrupts.
329 */
330static int acpi_reroute_boot_interrupt(struct pci_dev *dev,
331 struct acpi_prt_entry *entry)
332{
333 if (noioapicquirk || noioapicreroute) {
334 return 0;
335 } else {
336 switch (bridge_has_boot_interrupt_variant(dev->bus)) {
337 case 0:
338 /* no rerouting necessary */
339 return 0;
340 case INTEL_IRQ_REROUTE_VARIANT:
341 /*
342 * Remap according to INTx routing table in 6700PXH
343 * specs, intel order number 302628-002, section
344 * 2.15.2. Other chipsets (80332, ...) have the same
345 * mapping and are handled here as well.
346 */
347 dev_info(&dev->dev, "PCI IRQ %d -> rerouted to legacy "
348 "IRQ %d\n", entry->index,
349 (entry->index % 4) + 16);
350 entry->index = (entry->index % 4) + 16;
351 return 1;
352 default:
353 dev_warn(&dev->dev, "Cannot reroute IRQ %d to legacy "
354 "IRQ: unknown mapping\n", entry->index);
355 return -1;
356 }
357 }
358}
359#endif /* CONFIG_X86_IO_APIC */
360
306static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) 361static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
307{ 362{
308 struct acpi_prt_entry *entry; 363 struct acpi_prt_entry *entry;
@@ -311,6 +366,9 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
311 366
312 entry = acpi_pci_irq_find_prt_entry(dev, pin); 367 entry = acpi_pci_irq_find_prt_entry(dev, pin);
313 if (entry) { 368 if (entry) {
369#ifdef CONFIG_X86_IO_APIC
370 acpi_reroute_boot_interrupt(dev, entry);
371#endif /* CONFIG_X86_IO_APIC */
314 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", 372 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
315 pci_name(dev), pin_name(pin))); 373 pci_name(dev), pin_name(pin)));
316 return entry; 374 return entry;