From patchwork Thu Nov 18 13:52:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Assmann X-Patchwork-Id: 336191 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oAIDrEFe011030 for ; Thu, 18 Nov 2010 13:53:15 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757933Ab0KRNxN (ORCPT ); Thu, 18 Nov 2010 08:53:13 -0500 Received: from mx1.redhat.com ([209.132.183.28]:24085 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757866Ab0KRNxM (ORCPT ); Thu, 18 Nov 2010 08:53:12 -0500 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAIDqmdr017521 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 18 Nov 2010 08:52:49 -0500 Received: from localhost6.localdomain6 ([10.3.112.18]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oAIDqfB8021261; Thu, 18 Nov 2010 08:52:43 -0500 Date: Thu, 18 Nov 2010 08:52:41 -0500 From: Stefan Assmann To: linux-pci@vger.kernel.org Cc: lenb@kernel.org, JBeulich@novell.com, linux-acpi@vger.kernel.org, Stefan Assmann , mingo@elte.hu, Olaf.Dabrunz@gmx.net, tglx@linutronix.de, bjorn.helgaas@hp.com Message-Id: <20101118135249.2269.73369.sendpatchset@localhost6.localdomain6> In-Reply-To: <20101118135207.2269.2593.sendpatchset@localhost6.localdomain6> References: <20101118135207.2269.2593.sendpatchset@localhost6.localdomain6> Subject: [PATCH 4/4] PCI, ACPI: re-add boot interrupt reroute code in separate files X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 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.3 (demeter1.kernel.org [140.211.167.41]); Thu, 18 Nov 2010 13:53:15 +0000 (UTC) diff --git a/arch/x86/include/asm/boot_irq.h b/arch/x86/include/asm/boot_irq.h new file mode 100644 index 0000000..0cc35e1 --- /dev/null +++ b/arch/x86/include/asm/boot_irq.h @@ -0,0 +1,28 @@ +#ifndef _ASM_X86_BOOT_IRQ_H +#define _ASM_X86_BOOT_IRQ_H + +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Workaround for boot interrupts that cannot be disabled in hardware: makes + * affected devices always use the boot interrupt, the original interrupt line + * for the device remains disabled. + */ + +#include +#ifdef CONFIG_ACPI +#include +#endif /* CONFIG_ACPI */ + +#ifdef CONFIG_X86_IO_APIC +#ifdef CONFIG_ACPI +extern struct acpi_prt_entry *boot_irq_reroute (struct pci_dev *dev, struct acpi_prt_entry *entry); +#endif /* CONFIG_ACPI */ +#else +static inline struct acpi_prt_entry *boot_irq_reroute (struct pci_dev *dev, struct acpi_prt_entry *entry) + { return entry; } +#endif /* CONFIG_X86_IO_APIC */ + +#endif /* _ASM_X86_BOOT_IRQ_H */ diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile index 910f20b..4603b66 100644 --- a/arch/x86/kernel/apic/Makefile +++ b/arch/x86/kernel/apic/Makefile @@ -9,6 +9,9 @@ endif obj-$(CONFIG_HARDLOCKUP_DETECTOR) += hw_nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o +ifeq ($(CONFIG_ACPI),y) +obj-$(CONFIG_X86_IO_APIC) += boot_irq.o +endif obj-$(CONFIG_SMP) += ipi.o ifeq ($(CONFIG_X86_64),y) diff --git a/arch/x86/kernel/apic/boot_irq.c b/arch/x86/kernel/apic/boot_irq.c new file mode 100644 index 0000000..297d590 --- /dev/null +++ b/arch/x86/kernel/apic/boot_irq.c @@ -0,0 +1,63 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Workaround for boot interrupts that cannot be disabled in hardware: makes + * affected devices always use the boot interrupt, the original interrupt line + * for the device remains disabled. + */ + +#include +#include + +/* + * On it's way to the CPU a PCI IRQ might pass multiple PCI bridges therefore + * we need to inspect all of them. + */ +static int boot_irq_check_broken_bridge(struct pci_dev *pdev) +{ + struct pci_dev *tmp_pdev; + + tmp_pdev = pci_find_upstream_pcie_bridge(pdev); + + if (tmp_pdev) + return tmp_pdev->irq_reroute_variant; + else + 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. + */ +struct acpi_prt_entry *boot_irq_reroute(struct pci_dev *dev, struct acpi_prt_entry *entry) +{ + u32 orig_index; + + switch (boot_irq_check_broken_bridge(dev)) { + case 0: + break; /* no rerouting necessary */ + + 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. + */ + orig_index = entry->index; + entry->index = (entry->index % 4) + 16; + dev_info(&dev->dev, "PCI IRQ %d -> rerouted to legacy boot IRQ %d\n", orig_index, entry->index); + break; + + default: + dev_info(&dev->dev, "Not rerouting PCI IRQ %d: unknown mapping\n", entry->index); + break; + } + + return entry; +} diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index e1632b2..83eb5f6 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -39,6 +39,7 @@ #include #include #include +#include #define PREFIX "ACPI: " @@ -309,6 +310,9 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) if (entry) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", pci_name(dev), pin_name(pin))); + if (!noioapicquirk) + entry = boot_irq_reroute(dev, entry); + return entry; }