Received: by 2002:a05:6a10:f3d0:0:0:0:0 with SMTP id a16csp3703428pxv; Mon, 5 Jul 2021 03:47:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzmfoSvVeJoegPm1DzLC34OO7y53YB0wbVpa2tM49fSqg40Fs24GPMSjClTnuy5/0ZJaQmC X-Received: by 2002:a92:c846:: with SMTP id b6mr10246276ilq.170.1625482064735; Mon, 05 Jul 2021 03:47:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1625482064; cv=none; d=google.com; s=arc-20160816; b=eUXhCI5WDQeuFROnXuE8+uuVSpnKqzPG+q4aRiFY9Fxgsk8uxKdQkfjvC2U6D4mIhp 9ZQyxoEMuMF3NUjM2Ce+UnpYF8Yigv+XU+riqYMFpdIMd8cjkpzkkrNabBausEZ7NE9Z U9ADVc7nhOM0pekEgsAUnMzPrYkvvCuWGTiVUkfb3aBCEJFE3Z9gKDfPni5OswIxtec2 X5pulqWcpxfhVkfd5ArvXx/74cJ77YX7Xt0ak2C3npEzQ4cZZyQzBr+wxO1nvRpGqEId cYPbSjhwojdhzhKHqF/FHUdj1yJnVn8a1Gst1/DTayJ+qeoNdzfvpY/hhQG6j5hO6JV9 5pLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:user-agent:message-id:subject:cc:to :from:date; bh=tTghH1R/Hiy+/fZXqwgug359bhz4Z6X5ipklzFYhLh0=; b=PSp2mS6b77Fu4roL+DegbIdFQFMBki9DJMOrSL+p/PIxSvyqk+UDcznZu/HpUgaEtK SdUm5lBkqyMoZv6HY+RMH6Az5PMXz+YaKwUl9tpkMetVy5Dl26WrBEerBbSC9851QmXo tSpf0wDSE5BlCYO3Ed3ifCzO9M6M3X04vtIwkRKA6w8xMk3Iy4FGMPBIW355LSJD7uWW 0gTDraSurGxB1wEMmhtWff1TDrAPNZc1EPufH3n328bJ+pxVP9wIfHyjVmIFC664OTi8 JWk2NRpSmw/yQoNHEDqDZhADnCMivKtbj+WBUfQmTApTza4JIRwX+wGJZhp2GDZq1crv I52A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t4si14632766ilq.47.2021.07.05.03.47.33; Mon, 05 Jul 2021 03:47:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231139AbhGEKsv (ORCPT + 99 others); Mon, 5 Jul 2021 06:48:51 -0400 Received: from angie.orcam.me.uk ([78.133.224.34]:60282 "EHLO angie.orcam.me.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230168AbhGEKsv (ORCPT ); Mon, 5 Jul 2021 06:48:51 -0400 Received: by angie.orcam.me.uk (Postfix, from userid 500) id 82FE092009C; Mon, 5 Jul 2021 12:46:13 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 7BD6092009B; Mon, 5 Jul 2021 12:46:13 +0200 (CEST) Date: Mon, 5 Jul 2021 12:46:13 +0200 (CEST) From: "Maciej W. Rozycki" To: Nikolai Zhubr , Bjorn Helgaas , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" cc: Arnd Bergmann , x86@kernel.org, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] x86/PCI: Handle PIRQ routing tables with no router device given Message-ID: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org PIRQ routing tables provided by the PCI BIOS usually specify the PCI vendor:device ID as well as the bus address of the device implementing the PIRQ router, e.g.: PCI: Interrupt Routing Table found at 0xc00fde10 [...] PCI: Attempting to find IRQ router for [8086:7000] pci 0000:00:07.0: PIIX/ICH IRQ router [8086:7000] however in some cases they do not, in which case we fail to match the router handler, e.g.: PCI: Interrupt Routing Table found at 0xc00fdae0 [...] PCI: Attempting to find IRQ router for [0000:0000] PCI: Interrupt router not found at 00:00 This is because we always match the vendor:device ID and the bus address literally, even if they are all zeros. Handle this case then and iterate over all PCI devices until we find a matching router handler if the vendor ID given by the routing table is the invalid value of zero. Signed-off-by: Maciej W. Rozycki --- arch/x86/pci/irq.c | 63 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 20 deletions(-) linux-x86-pirq-router-nodev.diff Index: linux-macro-ide-tty/arch/x86/pci/irq.c =================================================================== --- linux-macro-ide-tty.orig/arch/x86/pci/irq.c +++ linux-macro-ide-tty/arch/x86/pci/irq.c @@ -908,10 +908,32 @@ static struct pci_dev *pirq_router_dev; * chipset" ? */ +static bool __init pirq_try_router(struct irq_router *r, + struct irq_routing_table *rt, + struct pci_dev *dev) +{ + struct irq_router_handler *h; + + DBG(KERN_DEBUG "PCI: Trying IRQ router for [%04x:%04x]\n", + dev->vendor, dev->device); + + for (h = pirq_routers; h->vendor; h++) { + /* First look for a router match */ + if (rt->rtr_vendor == h->vendor && + h->probe(r, dev, rt->rtr_device)) + return true; + /* Fall back to a device match */ + if (dev->vendor == h->vendor && + h->probe(r, dev, dev->device)) + return true; + } + return false; +} + static void __init pirq_find_router(struct irq_router *r) { struct irq_routing_table *rt = pirq_table; - struct irq_router_handler *h; + struct pci_dev *dev; #ifdef CONFIG_PCI_BIOS if (!rt->signature) { @@ -930,27 +952,28 @@ static void __init pirq_find_router(stru DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for [%04x:%04x]\n", rt->rtr_vendor, rt->rtr_device); - pirq_router_dev = pci_get_domain_bus_and_slot(0, rt->rtr_bus, - rt->rtr_devfn); - if (!pirq_router_dev) { - DBG(KERN_DEBUG "PCI: Interrupt router not found at " - "%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); - return; + /* Use any vendor:device provided by the routing table or try all. */ + if (rt->rtr_vendor) { + dev = pci_get_domain_bus_and_slot(0, rt->rtr_bus, + rt->rtr_devfn); + if (pirq_try_router(r, rt, dev)) + pirq_router_dev = dev; + } else { + for_each_pci_dev(dev) { + if (pirq_try_router(r, rt, dev)) { + pirq_router_dev = dev; + break; + } + } } - for (h = pirq_routers; h->vendor; h++) { - /* First look for a router match */ - if (rt->rtr_vendor == h->vendor && - h->probe(r, pirq_router_dev, rt->rtr_device)) - break; - /* Fall back to a device match */ - if (pirq_router_dev->vendor == h->vendor && - h->probe(r, pirq_router_dev, pirq_router_dev->device)) - break; - } - dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x:%04x]\n", - pirq_router.name, - pirq_router_dev->vendor, pirq_router_dev->device); + if (pirq_router_dev) + dev_info(&pirq_router_dev->dev, "%s IRQ router [%04x:%04x]\n", + pirq_router.name, + pirq_router_dev->vendor, pirq_router_dev->device); + else + DBG(KERN_DEBUG "PCI: Interrupt router not found at " + "%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); /* The device remains referenced for the kernel lifetime */ }