Commit d7f6169a0d32002657886fee561c641acddb9a75

Authored by Stefan Assmann
Committed by Len Brown
1 parent 1765a367a3

ACPI: fix CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS

The following was observed by Steve Rostedt on 3.0.0-rc5
Backtrace:
irq 16: nobody cared (try booting with the "irqpoll" option)
Pid: 65, comm: irq/16-uhci_hcd Not tainted 3.0.0-rc5-test+ #94
Call Trace:
 [<ffffffff810aa643>] __report_bad_irq+0x37/0xc1
 [<ffffffff810aaa2d>] note_interrupt+0x14e/0x1c9
 [<ffffffff810a9a05>] ? irq_thread_fn+0x3c/0x3c
 [<ffffffff810a990e>] irq_thread+0xf6/0x1b1
 [<ffffffff810a9818>] ? irq_finalize_oneshot+0xb3/0xb3
 [<ffffffff8106b4d6>] kthread+0x9f/0xa7
 [<ffffffff814f1f04>] kernel_thread_helper+0x4/0x10
 [<ffffffff8103ca09>] ? finish_task_switch+0x7b/0xc0
 [<ffffffff814eac78>] ? retint_restore_args+0x13/0x13
 [<ffffffff8106b437>] ? __init_kthread_worker+0x5a/0x5a
 [<ffffffff814f1f00>] ? gs_change+0x13/0x13
handlers:
[<ffffffff810a912d>] irq_default_primary_handler threaded [<ffffffff8135eaa6>] usb_hcd_irq
[<ffffffff810a912d>] irq_default_primary_handler threaded [<ffffffff8135eaa6>] usb_hcd_irq
Disabling IRQ #16

The problem being that a device triggers boot interrupts (due to threaded
interrupt handling and masking of the IO-APIC), which are forwarded
to the PIRQ line of the device. These interrupts are not handled on the PIRQ
line because the interrupt handler is not present there.
This should have already been fixed by CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS.
However some parts of the quirk got lost in the ACPI merge. This is a resent of
the patch proposed in 2009.
See http://lkml.org/lkml/2009/9/7/192

Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
Tested-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Len Brown <len.brown@intel.com>

Showing 1 changed file with 58 additions and 0 deletions Side-by-side Diff

drivers/acpi/pci_irq.c
... ... @@ -303,6 +303,61 @@
303 303 /* --------------------------------------------------------------------------
304 304 PCI Interrupt Routing Support
305 305 -------------------------------------------------------------------------- */
  306 +#ifdef CONFIG_X86_IO_APIC
  307 +extern int noioapicquirk;
  308 +extern int noioapicreroute;
  309 +
  310 +static 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 + */
  330 +static 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 +
306 361 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
307 362 {
308 363 struct acpi_prt_entry *entry;
... ... @@ -311,6 +366,9 @@
311 366  
312 367 entry = acpi_pci_irq_find_prt_entry(dev, pin);
313 368 if (entry) {
  369 +#ifdef CONFIG_X86_IO_APIC
  370 + acpi_reroute_boot_interrupt(dev, entry);
  371 +#endif /* CONFIG_X86_IO_APIC */
314 372 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
315 373 pci_name(dev), pin_name(pin)));
316 374 return entry;