From patchwork Sun Jan 2 23:24:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 1574657 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4JRwCz4168z9sR4 for ; Mon, 3 Jan 2022 10:33:03 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231174AbiABXc6 (ORCPT ); Sun, 2 Jan 2022 18:32:58 -0500 Received: from angie.orcam.me.uk ([78.133.224.34]:38432 "EHLO angie.orcam.me.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230128AbiABXc4 (ORCPT ); Sun, 2 Jan 2022 18:32:56 -0500 Received: by angie.orcam.me.uk (Postfix, from userid 500) id B25549200C4; Mon, 3 Jan 2022 00:24:23 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id A49749200C3; Sun, 2 Jan 2022 23:24:23 +0000 (GMT) Date: Sun, 2 Jan 2022 23:24:23 +0000 (GMT) From: "Maciej W. Rozycki" To: Bjorn Helgaas , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" cc: x86@kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/4] x86/PCI: Show the physical address of the $PIR table In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org It makes no sense to hide the address of the $PIR table in a debug dump: PCI: Interrupt Routing Table found at 0x(ptrval) let alone print its virtual address, given that this is a BIOS entity at a fixed location in the system's memory map. Show the physical address instead then, e.g.: PCI: Interrupt Routing Table found at 0xfde10 Signed-off-by: Maciej W. Rozycki --- No change from v1. --- arch/x86/pci/irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) linux-x86-debug-pirq-addr.diff Index: linux-macro/arch/x86/pci/irq.c =================================================================== --- linux-macro.orig/arch/x86/pci/irq.c +++ linux-macro/arch/x86/pci/irq.c @@ -84,8 +84,8 @@ static inline struct irq_routing_table * for (i = 0; i < rt->size; i++) sum += addr[i]; if (!sum) { - DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", - rt); + DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%lx\n", + __pa(rt)); return rt; } return NULL; From patchwork Sun Jan 2 23:24:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 1574655 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4JRwCx01Ymz9t0k for ; Mon, 3 Jan 2022 10:33:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231156AbiABXc5 (ORCPT ); Sun, 2 Jan 2022 18:32:57 -0500 Received: from angie.orcam.me.uk ([78.133.224.34]:38420 "EHLO angie.orcam.me.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230046AbiABXcz (ORCPT ); Sun, 2 Jan 2022 18:32:55 -0500 Received: by angie.orcam.me.uk (Postfix, from userid 500) id 200B39200C5; Mon, 3 Jan 2022 00:24:29 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 1A1399200C3; Sun, 2 Jan 2022 23:24:29 +0000 (GMT) Date: Sun, 2 Jan 2022 23:24:29 +0000 (GMT) From: "Maciej W. Rozycki" To: Bjorn Helgaas , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" cc: x86@kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/4] x86/PCI: Include function number in $PIR table dump In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Contrary to the PCI BIOS specification[1] some systems include the PCI function number for motherboard devices in their $PIR table, e.g. this is what the Tyan Tomcat IV S1564D board reports: 00:14 slot=01 0:60/deb8 1:61/deb8 2:62/deb8 3:63/deb8 00:13 slot=02 0:61/deb8 1:62/deb8 2:63/deb8 3:60/deb8 00:12 slot=03 0:62/deb8 1:63/deb8 2:60/deb8 3:61/deb8 00:11 slot=04 0:63/deb8 1:60/deb8 2:61/deb8 3:62/deb8 00:07 slot=00 0:00/deb8 1:00/deb8 2:00/deb8 3:00/deb8 00:07 slot=00 0:00/deb8 1:00/deb8 2:00/deb8 3:63/deb8 Print the function number then in the debug $PIR table dump: 00:14.0 slot=01 0:60/deb8 1:61/deb8 2:62/deb8 3:63/deb8 00:13.0 slot=02 0:61/deb8 1:62/deb8 2:63/deb8 3:60/deb8 00:12.0 slot=03 0:62/deb8 1:63/deb8 2:60/deb8 3:61/deb8 00:11.0 slot=04 0:63/deb8 1:60/deb8 2:61/deb8 3:62/deb8 00:07.1 slot=00 0:00/deb8 1:00/deb8 2:00/deb8 3:00/deb8 00:07.2 slot=00 0:00/deb8 1:00/deb8 2:00/deb8 3:63/deb8 References: [1] "PCI BIOS Specification", Revision 2.1, PCI Special Interest Group, August 26, 1994, Table 4-1 "Layout of IRQ routing table entry.", p. 12 Signed-off-by: Maciej W. Rozycki --- No change from v1. --- arch/x86/pci/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) linux-x86-debug-pirq-fn.diff Index: linux-macro/arch/x86/pci/irq.c =================================================================== --- linux-macro.orig/arch/x86/pci/irq.c +++ linux-macro/arch/x86/pci/irq.c @@ -135,7 +135,8 @@ static void __init pirq_peer_trick(void) #ifdef DEBUG { int j; - DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot); + DBG(KERN_DEBUG "%02x:%02x.%x slot=%02x", + e->bus, e->devfn / 8, e->devfn % 8, e->slot); for (j = 0; j < 4; j++) DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap); DBG("\n"); From patchwork Sun Jan 2 23:24:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 1574659 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4JRwD01gRqz9sR4 for ; Mon, 3 Jan 2022 10:33:04 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231185AbiABXdB (ORCPT ); Sun, 2 Jan 2022 18:33:01 -0500 Received: from angie.orcam.me.uk ([78.133.224.34]:38442 "EHLO angie.orcam.me.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231147AbiABXc4 (ORCPT ); Sun, 2 Jan 2022 18:32:56 -0500 Received: by angie.orcam.me.uk (Postfix, from userid 500) id EF3DE9200C7; Mon, 3 Jan 2022 00:24:35 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id E94399200C6; Sun, 2 Jan 2022 23:24:35 +0000 (GMT) Date: Sun, 2 Jan 2022 23:24:35 +0000 (GMT) From: "Maciej W. Rozycki" To: Bjorn Helgaas , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" cc: x86@kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/4] x86/PCI: Also match function number in $PIR table In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Contrary to the PCI BIOS specification[1] some systems include the PCI function number for onboard devices in their $PIR table. Consequently the wrong entry can be matched leading to interrupt routing failures. For example the Tyan Tomcat IV S1564D board has: 00:07.1 slot=00 0:00/deb8 1:00/deb8 2:00/deb8 3:00/deb8 00:07.2 slot=00 0:00/deb8 1:00/deb8 2:00/deb8 3:63/deb8 for its IDE interface and USB controller functions of the 82371SB PIIX3 southbridge. Consequently the first entry matches causing the inability to route the USB interrupt in the `noapic' mode, in which case we need to rely on the interrupt line set by the BIOS: uhci_hcd 0000:00:07.2: runtime IRQ mapping not provided by arch uhci_hcd 0000:00:07.2: PCI INT D not routed uhci_hcd 0000:00:07.2: enabling bus mastering uhci_hcd 0000:00:07.2: UHCI Host Controller uhci_hcd 0000:00:07.2: new USB bus registered, assigned bus number 1 uhci_hcd 0000:00:07.2: irq 11, io base 0x00006000 Try to match the PCI device and function combined then and if that fails move on to PCI device matching only. Compliant systems will only have a single $PIR table entry per PCI device, so this update does not change the semantics with them, while systems that have several entries for individual functions of a single PCI device each will match the correct entry: uhci_hcd 0000:00:07.2: runtime IRQ mapping not provided by arch uhci_hcd 0000:00:07.2: PCI INT D -> PIRQ 63, mask deb8, excl 0c20 uhci_hcd 0000:00:07.2: PCI INT D -> newirq 11 uhci_hcd 0000:00:07.2: found PCI INT D -> IRQ 11 uhci_hcd 0000:00:07.2: sharing IRQ 11 with 0000:00:11.0 uhci_hcd 0000:00:07.2: enabling bus mastering uhci_hcd 0000:00:07.2: UHCI Host Controller uhci_hcd 0000:00:07.2: new USB bus registered, assigned bus number 1 uhci_hcd 0000:00:07.2: irq 11, io base 0x00006000 [1] "PCI BIOS Specification", Revision 2.1, PCI Special Interest Group, August 26, 1994, Table 4-1 "Layout of IRQ routing table entry.", p. 12 Signed-off-by: Maciej W. Rozycki --- No change from v1. --- arch/x86/pci/irq.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) linux-x86-pirq-fn.diff Index: linux-macro/arch/x86/pci/irq.c =================================================================== --- linux-macro.orig/arch/x86/pci/irq.c +++ linux-macro/arch/x86/pci/irq.c @@ -1132,18 +1132,29 @@ static void __init pirq_find_router(stru /* The device remains referenced for the kernel lifetime */ } +/* + * We're supposed to match on the PCI device only and not the function, + * but some BIOSes build their tables with the PCI function included + * for motherboard devices, so if a complete match is found, then give + * it precedence over a slot match. + */ static struct irq_info *pirq_get_info(struct pci_dev *dev) { struct irq_routing_table *rt = pirq_table; int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); + struct irq_info *slotinfo = NULL; struct irq_info *info; for (info = rt->slots; entries--; info++) - if (info->bus == dev->bus->number && - PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn)) - return info; - return NULL; + if (info->bus == dev->bus->number) { + if (info->devfn == dev->devfn) + return info; + if (!slotinfo && + PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn)) + slotinfo = info; + } + return slotinfo; } static int pcibios_lookup_irq(struct pci_dev *dev, int assign) From patchwork Sun Jan 2 23:24:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 1574656 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4JRwCx2K1Zz9sR4 for ; Mon, 3 Jan 2022 10:33:01 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231166AbiABXc6 (ORCPT ); Sun, 2 Jan 2022 18:32:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41964 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231151AbiABXcz (ORCPT ); Sun, 2 Jan 2022 18:32:55 -0500 Received: from angie.orcam.me.uk (angie.orcam.me.uk [IPv6:2001:4190:8020::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2B431C061799 for ; Sun, 2 Jan 2022 15:32:55 -0800 (PST) Received: by angie.orcam.me.uk (Postfix, from userid 500) id EB4C49200C9; Mon, 3 Jan 2022 00:24:41 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id E571A9200C8; Sun, 2 Jan 2022 23:24:41 +0000 (GMT) Date: Sun, 2 Jan 2022 23:24:41 +0000 (GMT) From: "Maciej W. Rozycki" To: Bjorn Helgaas , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" cc: x86@kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 4/4] x86/PCI: Handle IRQ swizzling with PIRQ routers In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Similarly to MP-tables PIRQ routing tables may not list devices behind PCI-to-PCI bridges, leading to interrupt routing failures, e.g.: pci 0000:00:07.0: PIIX/ICH IRQ router [8086:7000] pci 0000:02:00.0: ignoring bogus IRQ 255 pci 0000:02:01.0: ignoring bogus IRQ 255 pci 0000:02:02.0: ignoring bogus IRQ 255 pci 0000:04:00.0: ignoring bogus IRQ 255 pci 0000:04:00.3: ignoring bogus IRQ 255 pci 0000:00:11.0: PCI INT A -> PIRQ 63, mask deb8, excl 0c20 pci 0000:00:11.0: PCI INT A -> newirq 0 PCI: setting IRQ 11 as level-triggered pci 0000:00:11.0: found PCI INT A -> IRQ 11 pci 0000:00:11.0: sharing IRQ 11 with 0000:00:07.2 pci 0000:02:00.0: PCI INT A not found in routing table pci 0000:02:01.0: PCI INT A not found in routing table pci 0000:02:02.0: PCI INT A not found in routing table pci 0000:04:00.0: PCI INT A not found in routing table pci 0000:04:00.3: PCI INT D not found in routing table pci 0000:06:05.0: PCI INT A not found in routing table pci 0000:06:08.0: PCI INT A not found in routing table pci 0000:06:08.1: PCI INT B not found in routing table pci 0000:06:08.2: PCI INT C not found in routing table and consequently non-working devices. Since PCI-to-PCI bridges have a standardised way of routing interrupts by the means of swizzling do it for configurations that use a PIRQ router as well, like with APIC-based setups, and use the determined corresponding topmost bridge's interrupt pin assignment to route a given device's interrupt: pci 0000:00:07.0: PIIX/ICH IRQ router [8086:7000] pci 0000:02:00.0: ignoring bogus IRQ 255 pci 0000:02:01.0: ignoring bogus IRQ 255 pci 0000:02:02.0: ignoring bogus IRQ 255 pci 0000:04:00.0: ignoring bogus IRQ 255 pci 0000:04:00.3: ignoring bogus IRQ 255 pci 0000:00:11.0: PCI INT A -> PIRQ 63, mask deb8, excl 0c20 pci 0000:00:11.0: PCI INT A -> newirq 0 PCI: setting IRQ 11 as level-triggered pci 0000:00:11.0: found PCI INT A -> IRQ 11 pci 0000:00:11.0: sharing IRQ 11 with 0000:00:07.2 pci 0000:02:00.0: using bridge 0000:00:11.0 INT A to get INT A pci 0000:00:11.0: sharing IRQ 11 with 0000:02:00.0 pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:04:00.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:04:00.3: using bridge 0000:00:11.0 INT A to get INT D pci 0000:00:11.0: sharing IRQ 11 with 0000:04:00.3 pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A pci 0000:06:08.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:06:08.1: using bridge 0000:00:11.0 INT D to get INT B pci 0000:06:08.2: using bridge 0000:00:11.0 INT A to get INT C pci 0000:00:11.0: sharing IRQ 11 with 0000:06:08.2 pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:02:01.0: PCI INT A -> PIRQ 60, mask deb8, excl 0c20 pci 0000:02:01.0: PCI INT A -> newirq 0 PCI: setting IRQ 10 as level-triggered pci 0000:02:01.0: found PCI INT A -> IRQ 10 pci 0000:02:01.0: sharing IRQ 10 with 0000:00:14.0 pci 0000:02:00.0: using bridge 0000:00:11.0 INT A to get INT A pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:04:00.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:02:01.0: sharing IRQ 10 with 0000:04:00.0 pci 0000:04:00.3: using bridge 0000:00:11.0 INT A to get INT D pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A pci 0000:06:08.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:06:08.1: using bridge 0000:00:11.0 INT D to get INT B pci 0000:06:08.2: using bridge 0000:00:11.0 INT A to get INT C pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:02:02.0: PCI INT A -> PIRQ 61, mask deb8, excl 0c20 pci 0000:02:02.0: PCI INT A -> newirq 0 PCI: setting IRQ 5 as level-triggered pci 0000:02:02.0: found PCI INT A -> IRQ 5 pci 0000:02:02.0: sharing IRQ 5 with 0000:00:13.0 pci 0000:02:00.0: using bridge 0000:00:11.0 INT A to get INT A pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:04:00.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:04:00.3: using bridge 0000:00:11.0 INT A to get INT D pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A pci 0000:06:08.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:02:02.0: sharing IRQ 5 with 0000:06:08.0 pci 0000:06:08.1: using bridge 0000:00:11.0 INT D to get INT B pci 0000:06:08.2: using bridge 0000:00:11.0 INT A to get INT C pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A pci 0000:06:05.0: PCI INT A -> PIRQ 62, mask deb8, excl 0c20 pci 0000:06:05.0: PCI INT A -> newirq 0 pci 0000:06:05.0: found PCI INT A -> IRQ 5 pci 0000:06:05.0: sharing IRQ 5 with 0000:00:12.0 pci 0000:02:00.0: using bridge 0000:00:11.0 INT A to get INT A pci 0000:02:01.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:02:02.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:04:00.0: using bridge 0000:00:11.0 INT B to get INT A pci 0000:04:00.3: using bridge 0000:00:11.0 INT A to get INT D pci 0000:06:05.0: using bridge 0000:00:11.0 INT D to get INT A pci 0000:06:08.0: using bridge 0000:00:11.0 INT C to get INT A pci 0000:06:08.1: using bridge 0000:00:11.0 INT D to get INT B pci 0000:06:05.0: sharing IRQ 5 with 0000:06:08.1 pci 0000:06:08.2: using bridge 0000:00:11.0 INT A to get INT C Adjust log messages accordingly. Signed-off-by: Maciej W. Rozycki --- New change in v2, imported from a discrete submission. --- arch/x86/pci/irq.c | 60 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 13 deletions(-) linux-x86-pirq-swizzle-irq.diff Index: linux-macro/arch/x86/pci/irq.c =================================================================== --- linux-macro.orig/arch/x86/pci/irq.c +++ linux-macro/arch/x86/pci/irq.c @@ -1138,7 +1138,7 @@ static void __init pirq_find_router(stru * for motherboard devices, so if a complete match is found, then give * it precedence over a slot match. */ -static struct irq_info *pirq_get_info(struct pci_dev *dev) +static struct irq_info *pirq_get_dev_info(struct pci_dev *dev) { struct irq_routing_table *rt = pirq_table; int entries = (rt->size - sizeof(struct irq_routing_table)) / @@ -1157,11 +1157,42 @@ static struct irq_info *pirq_get_info(st return slotinfo; } +/* + * Buses behind bridges are typically not listed in the PIRQ routing table. + * Do the usual dance then and walk the tree of bridges up adjusting the + * pin number accordingly on the way until the originating root bus device + * has been reached and then use its routing information. + */ +static struct irq_info *pirq_get_info(struct pci_dev *dev, u8 *pin) +{ + struct pci_dev *temp_dev = dev; + struct irq_info *info; + u8 temp_pin = *pin; + u8 dpin = temp_pin; + + info = pirq_get_dev_info(dev); + while (!info && temp_dev->bus->parent) { + struct pci_dev *bridge = temp_dev->bus->self; + + temp_pin = pci_swizzle_interrupt_pin(temp_dev, temp_pin); + info = pirq_get_dev_info(bridge); + if (info) + dev_warn(&dev->dev, + "using bridge %s INT %c to get INT %c\n", + pci_name(bridge), + 'A' + temp_pin - 1, 'A' + dpin - 1); + + temp_dev = bridge; + } + *pin = temp_pin; + return info; +} + static int pcibios_lookup_irq(struct pci_dev *dev, int assign) { - u8 pin; struct irq_info *info; int i, pirq, newirq; + u8 dpin, pin; int irq = 0; u32 mask; struct irq_router *r = &pirq_router; @@ -1169,8 +1200,8 @@ static int pcibios_lookup_irq(struct pci char *msg = NULL; /* Find IRQ pin */ - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (!pin) { + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &dpin); + if (!dpin) { dev_dbg(&dev->dev, "no interrupt pin\n"); return 0; } @@ -1183,20 +1214,21 @@ static int pcibios_lookup_irq(struct pci if (!pirq_table) return 0; - info = pirq_get_info(dev); + pin = dpin; + info = pirq_get_info(dev, &pin); if (!info) { dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n", - 'A' + pin - 1); + 'A' + dpin - 1); return 0; } pirq = info->irq[pin - 1].link; mask = info->irq[pin - 1].bitmap; if (!pirq) { - dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin - 1); + dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + dpin - 1); return 0; } dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x", - 'A' + pin - 1, pirq, mask, pirq_table->exclusive_irqs); + 'A' + dpin - 1, pirq, mask, pirq_table->exclusive_irqs); mask &= pcibios_irq_mask; /* Work around broken HP Pavilion Notebooks which assign USB to @@ -1238,7 +1270,7 @@ static int pcibios_lookup_irq(struct pci newirq = i; } } - dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin - 1, newirq); + dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + dpin - 1, newirq); /* Check if it is hardcoded */ if ((pirq & 0xf0) == 0xf0) { @@ -1272,15 +1304,17 @@ static int pcibios_lookup_irq(struct pci return 0; } } - dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq); + dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", + msg, 'A' + dpin - 1, irq); /* Update IRQ for all devices with the same pirq value */ for_each_pci_dev(dev2) { - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); - if (!pin) + pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &dpin); + if (!dpin) continue; - info = pirq_get_info(dev2); + pin = dpin; + info = pirq_get_info(dev2, &pin); if (!info) continue; if (info->irq[pin - 1].link == pirq) {