Received: by 2002:a05:6a10:f3d0:0:0:0:0 with SMTP id a16csp64353pxv; Thu, 8 Jul 2021 15:13:50 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwAffM6LrTY0A5F92ijZZEluXqLHj9wPETHpBPI+6cdKiNbhB/R+kjfC0DDu51PZ9SAUX2r X-Received: by 2002:aa7:c3d8:: with SMTP id l24mr40869252edr.172.1625782429877; Thu, 08 Jul 2021 15:13:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1625782429; cv=none; d=google.com; s=arc-20160816; b=VW6sWT/YXNQBjEJdLurR30rncsyj6+Wjtx8rdcr6IHwi3KLl78tlnVklrthNAcAqlr xxiYexdXj0nzT8rxx5SZycUOu3jW6qsk7l8lceYoDsQie1nsdQAHDtHT3UvNRhoxQjKl w265tJHpTMSVitZw7MCKdtXYt12Zzldg3lWoNt+4HOeAmrcbM+3EV848ng5WnrvWOgFH cQnGlKl/Vfnj/lHxCGY+Ef1orMscTl8eYBZWObbJtt/4P9woyBVI0Gh2OaJgwGhOfGjp DZGTvM3Jc4u2tDCU3ff/6KfL7ABBaOi96rjZ3WEbm3ECchHKd5PR6RxZYoOsn+VFJj6H cl5w== 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=cLbIphCA24APJAKItb+pacVaRhSu9zwmFmCbkEDghTA=; b=kJrj3d1T6NQIkQ5DykNaFSnivT1XX8fJp+2WUVbVV+pY+VxVaWfPKGcFHFjYX/5msa daeCDECl6bE5wdEE0s1nKlHepIUbNfMyba1NCrRMBS2JjKtejp6p0U6mPOdPVJpy7/J/ Z7CMqr1zt2IIxjiN/mb3yB7W1T99Fyt5Rj9j36dPv9KuRFdgxH/zXmO0THo2Mhu65vX/ V+GJ6mdDVslAONvrpzyXUOs6yjcgbzzqLTuvus7sglNsajFtDU1RSdHvNahf7vTHpMUs zuYoiSREYNjsTi2ht2fNpdJZqSCEDEdTuTPHiLzOz0QNe8GteRNjTR85MmKOhbfh9Hsv 0zFA== 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 ho20si4149532ejc.581.2021.07.08.15.13.25; Thu, 08 Jul 2021 15:13:49 -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 S230336AbhGHWNK (ORCPT + 99 others); Thu, 8 Jul 2021 18:13:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39254 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230238AbhGHWNJ (ORCPT ); Thu, 8 Jul 2021 18:13:09 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [IPv6:2001:4190:8020::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 443A1C061574; Thu, 8 Jul 2021 15:10:27 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id 2ACB192009C; Fri, 9 Jul 2021 00:10:26 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 2583192009B; Fri, 9 Jul 2021 00:10:26 +0200 (CEST) Date: Fri, 9 Jul 2021 00:10:26 +0200 (CEST) From: "Maciej W. Rozycki" To: Bjorn Helgaas cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH v2] PCI: Sanitise firmware BAR assignments behind a PCI-PCI bridge 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 Fix an issue with the Tyan Tomcat IV S1564D system, the BIOS of which does not assign PCI buses beyond #2, where our resource reallocation code preserves the reset default of an I/O BAR assignment outside its upstream PCI-to-PCI bridge's I/O forwarding range for device 06:08.0 in this log: pci_bus 0000:00: max bus depth: 4 pci_try_num: 5 [...] pci 0000:06:08.0: BAR 4: no space for [io size 0x0020] pci 0000:06:08.0: BAR 4: trying firmware assignment [io 0xfce0-0xfcff] pci 0000:06:08.0: BAR 4: assigned [io 0xfce0-0xfcff] pci 0000:06:08.1: BAR 4: no space for [io size 0x0020] pci 0000:06:08.1: BAR 4: trying firmware assignment [io 0xfce0-0xfcff] pci 0000:06:08.1: BAR 4: [io 0xfce0-0xfcff] conflicts with 0000:06:08.0 [io 0xfce0-0xfcff] pci 0000:06:08.1: BAR 4: failed to assign [io size 0x0020] pci 0000:05:00.0: PCI bridge to [bus 06] pci 0000:05:00.0: bridge window [mem 0xd8000000-0xd85fffff] [...] pci 0000:00:11.0: PCI bridge to [bus 01-06] pci 0000:00:11.0: bridge window [io 0xe000-0xefff] pci 0000:00:11.0: bridge window [mem 0xd8000000-0xdfffffff] pci 0000:00:11.0: bridge window [mem 0xa8000000-0xafffffff 64bit pref] pci_bus 0000:00: No. 2 try to assign unassigned res [...] pci 0000:06:08.1: BAR 4: no space for [io size 0x0020] pci 0000:06:08.1: BAR 4: trying firmware assignment [io 0xfce0-0xfcff] pci 0000:06:08.1: BAR 4: [io 0xfce0-0xfcff] conflicts with 0000:06:08.0 [io 0xfce0-0xfcff] pci 0000:06:08.1: BAR 4: failed to assign [io size 0x0020] pci 0000:05:00.0: PCI bridge to [bus 06] pci 0000:05:00.0: bridge window [mem 0xd8000000-0xd85fffff] [...] pci 0000:00:11.0: PCI bridge to [bus 01-06] pci 0000:00:11.0: bridge window [io 0xe000-0xefff] pci 0000:00:11.0: bridge window [mem 0xd8000000-0xdfffffff] pci 0000:00:11.0: bridge window [mem 0xa8000000-0xafffffff 64bit pref] pci_bus 0000:00: No. 3 try to assign unassigned res pci 0000:00:11.0: resource 7 [io 0xe000-0xefff] released [...] pci 0000:06:08.1: BAR 4: assigned [io 0x2000-0x201f] pci 0000:05:00.0: PCI bridge to [bus 06] pci 0000:05:00.0: bridge window [io 0x2000-0x2fff] pci 0000:05:00.0: bridge window [mem 0xd8000000-0xd85fffff] [...] pci 0000:00:11.0: PCI bridge to [bus 01-06] pci 0000:00:11.0: bridge window [io 0x1000-0x2fff] pci 0000:00:11.0: bridge window [mem 0xd8000000-0xdfffffff] pci 0000:00:11.0: bridge window [mem 0xa8000000-0xafffffff 64bit pref] pci_bus 0000:00: resource 4 [io 0x0000-0xffff] pci_bus 0000:00: resource 5 [mem 0x00000000-0xffffffff] pci_bus 0000:01: resource 0 [io 0x1000-0x2fff] pci_bus 0000:01: resource 1 [mem 0xd8000000-0xdfffffff] pci_bus 0000:01: resource 2 [mem 0xa8000000-0xafffffff 64bit pref] pci_bus 0000:02: resource 0 [io 0x1000-0x2fff] pci_bus 0000:02: resource 1 [mem 0xd8000000-0xd8bfffff] pci_bus 0000:04: resource 0 [io 0x1000-0x1fff] pci_bus 0000:04: resource 1 [mem 0xd8600000-0xd8afffff] pci_bus 0000:05: resource 0 [io 0x2000-0x2fff] pci_bus 0000:05: resource 1 [mem 0xd8000000-0xd85fffff] pci_bus 0000:06: resource 0 [io 0x2000-0x2fff] pci_bus 0000:06: resource 1 [mem 0xd8000000-0xd85fffff] -- note that the assignment of 0xfce0-0xfcff is outside the range of 0x2000-0x2fff assigned to bus #6: 05:00.0 PCI bridge: Texas Instruments XIO2000(A)/XIO2200A PCI Express-to-PCI Bridge (rev 03) (prog-if 00 [Normal decode]) Flags: bus master, fast devsel, latency 0 Bus: primary=05, secondary=06, subordinate=06, sec-latency=0 I/O behind bridge: 00002000-00002fff Memory behind bridge: d8000000-d85fffff Capabilities: [50] Power Management version 2 Capabilities: [60] Message Signalled Interrupts: 64bit+ Queue=0/4 Enable- Capabilities: [80] #0d [0000] Capabilities: [90] Express PCI/PCI-X Bridge IRQ 0 06:08.0 USB controller: VIA Technologies, Inc. VT82xx/62xx/VX700/8x0/900 UHCI USB 1.1 Controller (rev 61) (prog-if 00 [UHCI]) Subsystem: VIA Technologies, Inc. VT82xx/62xx/VX700/8x0/900 UHCI USB 1.1 Controller Flags: bus master, medium devsel, latency 22, IRQ 5 I/O ports at fce0 [size=32] Capabilities: [80] Power Management version 2 06:08.1 USB controller: VIA Technologies, Inc. VT82xx/62xx/VX700/8x0/900 UHCI USB 1.1 Controller (rev 61) (prog-if 00 [UHCI]) Subsystem: VIA Technologies, Inc. VT82xx/62xx/VX700/8x0/900 UHCI USB 1.1 Controller Flags: bus master, medium devsel, latency 22, IRQ 5 I/O ports at 2000 [size=32] Capabilities: [80] Power Management version 2 Since both 06:08.0 and 06:08.1 have the same reset defaults the latter device escapes its fate and gets a good assignment owing to an address conflict with the former device. Consequently when the device driver tries to access 06:08.0 according to its designated address range it pokes at an unassigned I/O location, likely subtractively decoded by the southbridge and forwarded to ISA, causing the driver to become confused and bail out: uhci_hcd 0000:06:08.0: host system error, PCI problems? uhci_hcd 0000:06:08.0: host controller process error, something bad happened! uhci_hcd 0000:06:08.0: host controller halted, very bad! uhci_hcd 0000:06:08.0: HCRESET not completed yet! uhci_hcd 0000:06:08.0: HC died; cleaning up if good luck happens or if bad luck does, an infinite flood of messages: uhci_hcd 0000:06:08.0: host system error, PCI problems? uhci_hcd 0000:06:08.0: host controller process error, something bad happened! uhci_hcd 0000:06:08.0: host system error, PCI problems? uhci_hcd 0000:06:08.0: host controller process error, something bad happened! uhci_hcd 0000:06:08.0: host system error, PCI problems? uhci_hcd 0000:06:08.0: host controller process error, something bad happened! [...] making the system virtually unusuable. This is because we have code to deal with a situation from PR #16263, where broken ACPI firmware reports the wrong address range for the host bridge's decoding window and trying to adjust to the window causes more breakage than leaving the BIOS assignments intact. This may work for a device directly on the root bus decoded by the host bridge only, but for a device behind one or more PCI-to-PCI (or CardBus) bridges those bridges' forwarding windows have been standardised and need to be respected, or leaving whatever has been there in a downstream device's BAR will have no effect as cycles for the addresses recorded there will have no chance to appear on the bus the device has been immediately attached to. Make sure then for a device behind a PCI-to-PCI bridge that any firmware assignment is within the bridge's relevant forwarding window or do not restore the assignment, fixing the system concerned as follows: pci_bus 0000:00: max bus depth: 4 pci_try_num: 5 [...] pci 0000:06:08.0: BAR 4: no space for [io size 0x0020] pci 0000:06:08.0: BAR 4: failed to assign [io 0xfce0-0xfcff] pci 0000:06:08.1: BAR 4: no space for [io size 0x0020] pci 0000:06:08.1: BAR 4: failed to assign [io 0xfce0-0xfcff] [...] pci_bus 0000:00: No. 2 try to assign unassigned res [...] pci 0000:06:08.0: BAR 4: no space for [io size 0x0020] pci 0000:06:08.0: BAR 4: failed to assign [io 0xfce0-0xfcff] pci 0000:06:08.1: BAR 4: no space for [io size 0x0020] pci 0000:06:08.1: BAR 4: failed to assign [io 0xfce0-0xfcff] [...] pci_bus 0000:00: No. 3 try to assign unassigned res [...] pci 0000:06:08.0: BAR 4: assigned [io 0x2000-0x201f] pci 0000:06:08.1: BAR 4: assigned [io 0x2020-0x203f] and making device 06:08.0 work correctly. Cf. Signed-off-by: Maciej W. Rozycki Fixes: 58c84eda0756 ("PCI: fall back to original BIOS BAR addresses") Cc: stable@vger.kernel.org # v2.6.35+ --- For the record the system's bus topology is as follows: -[0000:00]-+-00.0 +-07.0 +-07.1 +-07.2 +-11.0-[0000:01-06]----00.0-[0000:02-06]--+-00.0-[0000:03]-- | +-01.0-[0000:04]--+-00.0 | | \-00.3 | \-02.0-[0000:05-06]----00.0-[0000:06]--+-05.0 | +-08.0 | +-08.1 | \-08.2 +-12.0 +-13.0 \-14.0 Changes from v1: - Do restore firmware BAR assignments behind a PCI-PCI bridge, but only if within the bridge's forwarding window. - Update the change description and heading accordingly (was: PCI: Do not restore firmware BAR assignments behind a PCI-PCI bridge). --- drivers/pci/setup-res.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) linux-pci-setup-res-fw-address-nobridge.diff Index: linux-macro-ide-tty/drivers/pci/setup-res.c =================================================================== --- linux-macro-ide-tty.orig/drivers/pci/setup-res.c +++ linux-macro-ide-tty/drivers/pci/setup-res.c @@ -208,9 +208,19 @@ static int pci_revert_fw_address(struct res->end = res->start + size - 1; res->flags &= ~IORESOURCE_UNSET; + /* + * If we're behind a P2P or CardBus bridge, make sure we're + * inside the relevant forwarding window, or otherwise the + * assignment must have been bogus and accesses intended for + * the range assigned would not reach the device anyway. + * On the root bus accept anything under the assumption the + * host bridge will let it through. + */ root = pci_find_parent_resource(dev, res); if (!root) { - if (res->flags & IORESOURCE_IO) + if (dev->bus->parent) + return -ENXIO; + else if (res->flags & IORESOURCE_IO) root = &ioport_resource; else root = &iomem_resource;