From nobody Fri Jun 19 18:21:56 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B494C433F5 for ; Thu, 31 Mar 2022 07:10:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231724AbiCaHMF (ORCPT ); Thu, 31 Mar 2022 03:12:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231698AbiCaHMB (ORCPT ); Thu, 31 Mar 2022 03:12:01 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [IPv6:2001:4190:8020::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 6625B5BE50; Thu, 31 Mar 2022 00:10:13 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id 380D192009D; Thu, 31 Mar 2022 09:10:12 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 324F592009B; Thu, 31 Mar 2022 08:10:12 +0100 (BST) Date: Thu, 31 Mar 2022 08:10:12 +0100 (BST) 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: [RESEND][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-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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=20 a fixed location in the system's memory map. Show the physical address=20 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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 =3D 0; i < rt->size; i++) sum +=3D 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 nobody Fri Jun 19 18:21:56 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 248CFC433F5 for ; Thu, 31 Mar 2022 07:10:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231748AbiCaHMK (ORCPT ); Thu, 31 Mar 2022 03:12:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38758 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231701AbiCaHME (ORCPT ); Thu, 31 Mar 2022 03:12:04 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [IPv6:2001:4190:8020::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 304435AEDD; Thu, 31 Mar 2022 00:10:18 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id 8EBFC92009C; Thu, 31 Mar 2022 09:10:17 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 87E7C92009B; Thu, 31 Mar 2022 08:10:17 +0100 (BST) Date: Thu, 31 Mar 2022 08:10:17 +0100 (BST) 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: [RESEND][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-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Contrary to the PCI BIOS specification[1] some systems include the PCI=20 function number for motherboard devices in their $PIR table, e.g. this=20 is what the Tyan Tomcat IV S1564D board reports: 00:14 slot=3D01 0:60/deb8 1:61/deb8 2:62/deb8 3:63/deb8 00:13 slot=3D02 0:61/deb8 1:62/deb8 2:63/deb8 3:60/deb8 00:12 slot=3D03 0:62/deb8 1:63/deb8 2:60/deb8 3:61/deb8 00:11 slot=3D04 0:63/deb8 1:60/deb8 2:61/deb8 3:62/deb8 00:07 slot=3D00 0:00/deb8 1:00/deb8 2:00/deb8 3:00/deb8 00:07 slot=3D00 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=3D01 0:60/deb8 1:61/deb8 2:62/deb8 3:63/deb8 00:13.0 slot=3D02 0:61/deb8 1:62/deb8 2:63/deb8 3:60/deb8 00:12.0 slot=3D03 0:62/deb8 1:63/deb8 2:60/deb8 3:61/deb8 00:11.0 slot=3D04 0:63/deb8 1:60/deb8 2:61/deb8 3:62/deb8 00:07.1 slot=3D00 0:00/deb8 1:00/deb8 2:00/deb8 3:00/deb8 00:07.2 slot=3D00 0:00/deb8 1:00/deb8 2:00/deb8 3:63/deb8 References: [1] "PCI BIOS Specification", Revision 2.1, PCI Special Interest Group,=20 August 26, 1994, Table 4-1 "Layout of IRQ routing table entry.", p.=20 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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=3D%02x", e->bus, e->devfn/8, e->slot); + DBG(KERN_DEBUG "%02x:%02x.%x slot=3D%02x", + e->bus, e->devfn / 8, e->devfn % 8, e->slot); for (j =3D 0; j < 4; j++) DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap); DBG("\n"); From nobody Fri Jun 19 18:21:56 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4FC26C433F5 for ; Thu, 31 Mar 2022 07:10:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231725AbiCaHMW (ORCPT ); Thu, 31 Mar 2022 03:12:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39028 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231757AbiCaHMR (ORCPT ); Thu, 31 Mar 2022 03:12:17 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [78.133.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 776686A048; Thu, 31 Mar 2022 00:10:22 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id C2EA992009D; Thu, 31 Mar 2022 09:10:21 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id BCDA692009B; Thu, 31 Mar 2022 08:10:21 +0100 (BST) Date: Thu, 31 Mar 2022 08:10:21 +0100 (BST) 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: [RESEND][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-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Contrary to the PCI BIOS specification[1] some systems include the PCI=20 function number for onboard devices in their $PIR table. Consequently=20 the wrong entry can be matched leading to interrupt routing failures. For example the Tyan Tomcat IV S1564D board has: 00:07.1 slot=3D00 0:00/deb8 1:00/deb8 2:00/deb8 3:00/deb8 00:07.2 slot=3D00 0:00/deb8 1:00/deb8 2:00/deb8 3:63/deb8 for its IDE interface and USB controller functions of the 82371SB PIIX3=20 southbridge. Consequently the first entry matches causing the inability=20 to route the USB interrupt in the `noapic' mode, in which case we need=20 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=20 move on to PCI device matching only. Compliant systems will only have a=20 single $PIR table entry per PCI device, so this update does not change=20 the semantics with them, while systems that have several entries for=20 individual functions of a single PCI device each will match the correct=20 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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 */ } =20 +/* + * 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 =3D pirq_table; int entries =3D (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); + struct irq_info *slotinfo =3D NULL; struct irq_info *info; =20 for (info =3D rt->slots; entries--; info++) - if (info->bus =3D=3D dev->bus->number && - PCI_SLOT(info->devfn) =3D=3D PCI_SLOT(dev->devfn)) - return info; - return NULL; + if (info->bus =3D=3D dev->bus->number) { + if (info->devfn =3D=3D dev->devfn) + return info; + if (!slotinfo && + PCI_SLOT(info->devfn) =3D=3D PCI_SLOT(dev->devfn)) + slotinfo =3D info; + } + return slotinfo; } =20 static int pcibios_lookup_irq(struct pci_dev *dev, int assign) From nobody Fri Jun 19 18:21:56 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B51DFC433F5 for ; Thu, 31 Mar 2022 07:10:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231824AbiCaHMa (ORCPT ); Thu, 31 Mar 2022 03:12:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40012 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231761AbiCaHMU (ORCPT ); Thu, 31 Mar 2022 03:12:20 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [78.133.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id CD53FA76FB; Thu, 31 Mar 2022 00:10:26 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id 9B3B59200B4; Thu, 31 Mar 2022 09:10:25 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 9506F9200B3; Thu, 31 Mar 2022 08:10:25 +0100 (BST) Date: Thu, 31 Mar 2022 08:10:25 +0100 (BST) 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: [RESEND][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-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Similarly to MP-tables PIRQ routing tables may not list devices behind=20 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=20 standardised way of routing interrupts by the means of swizzling do it=20 for configurations that use a PIRQ router as well, like with APIC-based=20 setups, and use the determined corresponding topmost bridge's interrupt=20 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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 =3D pirq_table; int entries =3D (rt->size - sizeof(struct irq_routing_table)) / @@ -1157,11 +1157,42 @@ static struct irq_info *pirq_get_info(st return slotinfo; } =20 +/* + * 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 =3D dev; + struct irq_info *info; + u8 temp_pin =3D *pin; + u8 dpin =3D temp_pin; + + info =3D pirq_get_dev_info(dev); + while (!info && temp_dev->bus->parent) { + struct pci_dev *bridge =3D temp_dev->bus->self; + + temp_pin =3D pci_swizzle_interrupt_pin(temp_dev, temp_pin); + info =3D 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 =3D bridge; + } + *pin =3D 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 =3D 0; u32 mask; struct irq_router *r =3D &pirq_router; @@ -1169,8 +1200,8 @@ static int pcibios_lookup_irq(struct pci char *msg =3D NULL; =20 /* 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; =20 - info =3D pirq_get_info(dev); + pin =3D dpin; + info =3D 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 =3D info->irq[pin - 1].link; mask =3D 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 &=3D pcibios_irq_mask; =20 /* Work around broken HP Pavilion Notebooks which assign USB to @@ -1238,7 +1270,7 @@ static int pcibios_lookup_irq(struct pci newirq =3D 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); =20 /* Check if it is hardcoded */ if ((pirq & 0xf0) =3D=3D 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); =20 /* 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; =20 - info =3D pirq_get_info(dev2); + pin =3D dpin; + info =3D pirq_get_info(dev2, &pin); if (!info) continue; if (info->irq[pin - 1].link =3D=3D pirq) {