From patchwork Fri Jul 15 12:52:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Assmann X-Patchwork-Id: 978132 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p6FCreL0009233 for ; Fri, 15 Jul 2011 12:53:40 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750807Ab1GOMxi (ORCPT ); Fri, 15 Jul 2011 08:53:38 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44652 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750770Ab1GOMxi (ORCPT ); Fri, 15 Jul 2011 08:53:38 -0400 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p6FCqaTI027092 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 15 Jul 2011 08:52:36 -0400 Received: from T500.redhat.com (vpn1-4-243.ams2.redhat.com [10.36.4.243]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p6FCqVDH020965; Fri, 15 Jul 2011 08:52:31 -0400 From: Stefan Assmann To: linux-acpi@vger.kernel.org Cc: linux-kernel@vger.kernel.org, lenb@kernel.org, jeremy@goop.org, mingo@redhat.com, tglx@linutronix.de, rostedt@goodmis.org, sassmann@kpanic.de Subject: [PATCH] ACPI: fix CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS Date: Fri, 15 Jul 2011 14:52:30 +0200 Message-Id: <1310734350-15947-1-git-send-email-sassmann@kpanic.de> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 15 Jul 2011 12:53:40 +0000 (UTC) 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: [] __report_bad_irq+0x37/0xc1 [] note_interrupt+0x14e/0x1c9 [] ? irq_thread_fn+0x3c/0x3c [] irq_thread+0xf6/0x1b1 [] ? irq_finalize_oneshot+0xb3/0xb3 [] kthread+0x9f/0xa7 [] kernel_thread_helper+0x4/0x10 [] ? finish_task_switch+0x7b/0xc0 [] ? retint_restore_args+0x13/0x13 [] ? __init_kthread_worker+0x5a/0x5a [] ? gs_change+0x13/0x13 handlers: [] irq_default_primary_handler threaded [] usb_hcd_irq [] irq_default_primary_handler threaded [] 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 Tested-by: Steven Rostedt --- drivers/acpi/pci_irq.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 58 insertions(+), 0 deletions(-) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index f907cfb..7f9eba9 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) /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ +#ifdef CONFIG_X86_IO_APIC +extern int noioapicquirk; +extern int noioapicreroute; + +static int bridge_has_boot_interrupt_variant(struct pci_bus *bus) +{ + struct pci_bus *bus_it; + + for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) { + if (!bus_it->self) + return 0; + if (bus_it->self->irq_reroute_variant) + return bus_it->self->irq_reroute_variant; + } + return 0; +} + +/* + * Some chipsets (e.g. Intel 6700PXH) generate a legacy INTx when the IRQ + * entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel does + * during interrupt handling). When this INTx generation cannot be disabled, + * we reroute these interrupts to their legacy equivalent to get rid of + * spurious interrupts. + */ +static int acpi_reroute_boot_interrupt(struct pci_dev *dev, + struct acpi_prt_entry *entry) +{ + if (noioapicquirk || noioapicreroute) { + return 0; + } else { + switch (bridge_has_boot_interrupt_variant(dev->bus)) { + case 0: + /* no rerouting necessary */ + return 0; + case INTEL_IRQ_REROUTE_VARIANT: + /* + * Remap according to INTx routing table in 6700PXH + * specs, intel order number 302628-002, section + * 2.15.2. Other chipsets (80332, ...) have the same + * mapping and are handled here as well. + */ + dev_info(&dev->dev, "PCI IRQ %d -> rerouted to legacy " + "IRQ %d\n", entry->index, + (entry->index % 4) + 16); + entry->index = (entry->index % 4) + 16; + return 1; + default: + dev_warn(&dev->dev, "Cannot reroute IRQ %d to legacy " + "IRQ: unknown mapping\n", entry->index); + return -1; + } + } +} +#endif /* CONFIG_X86_IO_APIC */ + static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) { struct acpi_prt_entry *entry; @@ -311,6 +366,9 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) entry = acpi_pci_irq_find_prt_entry(dev, pin); if (entry) { +#ifdef CONFIG_X86_IO_APIC + acpi_reroute_boot_interrupt(dev, entry); +#endif /* CONFIG_X86_IO_APIC */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", pci_name(dev), pin_name(pin))); return entry;