--- /dev/null
+From 0e32818397426a688f598f35d3bc762eca6d7592 Mon Sep 17 00:00:00 2001
+From: "Maciej W. Rozycki" <macro@orcam.me.uk>
+Date: Wed, 21 Sep 2022 20:49:16 +0100
+Subject: PCI: Sanitise firmware BAR assignments behind a PCI-PCI bridge
+
+From: Maciej W. Rozycki <macro@orcam.me.uk>
+
+commit 0e32818397426a688f598f35d3bc762eca6d7592 upstream.
+
+When pci_assign_resource() is unable to assign resources to a BAR, it uses
+pci_revert_fw_address() to fall back to a firmware assignment (if any).
+Previously pci_revert_fw_address() assumed all addresses could reach the
+device, but this is not true if the device is below a bridge that only
+forwards addresses within its windows.
+
+This problem was observed on a Tyan Tomcat IV S1564D system where the BIOS
+did not assign valid addresses to several bridges and USB devices:
+
+ pci 0000:00:11.0: PCI-to-PCIe bridge to [bus 01-ff]
+ pci 0000:00:11.0: bridge window [io 0xe000-0xefff]
+ pci 0000:01:00.0: PCIe Upstream Port to [bus 02-ff]
+ pci 0000:01:00.0: bridge window [io 0x0000-0x0fff] # unreachable
+ pci 0000:02:02.0: PCIe Downstream Port to [bus 05-ff]
+ pci 0000:02:02.0: bridge window [io 0x0000-0x0fff] # unreachable
+ pci 0000:05:00.0: PCIe-to-PCI bridge to [bus 06-ff]
+ pci 0000:05:00.0: bridge window [io 0x0000-0x0fff] # unreachable
+ pci 0000:06:08.0: USB UHCI 1.1
+ pci 0000:06:08.0: BAR 4: [io 0xfce0-0xfcff] # unreachable
+ pci 0000:06:08.1: USB UHCI 1.1
+ pci 0000:06:08.1: BAR 4: [io 0xfce0-0xfcff] # unreachable
+ pci 0000:06:08.0: can't claim BAR 4 [io 0xfce0-0xfcff]: no compatible bridge window
+ pci 0000:06:08.1: can't claim BAR 4 [io 0xfce0-0xfcff]: no compatible bridge window
+
+During the first pass of assigning unassigned resources, there was not
+enough I/O space available, so we couldn't assign the 06:08.0 BAR and
+reverted to the firmware assignment (still unreachable). Reverting the
+06:08.1 assignment failed because it conflicted with 06:08.0:
+
+ pci 0000:00:11.0: bridge window [io 0xe000-0xefff]
+ pci 0000:01:00.0: no space for bridge window [io size 0x2000]
+ pci 0000:02:02.0: no space for bridge window [io size 0x1000]
+ pci 0000:05:00.0: no space for bridge window [io size 0x1000]
+ 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.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]
+
+A subsequent pass assigned valid bridge windows and a valid 06:08.1 BAR,
+but left the 06:08.0 BAR alone, so the UHCI device was still unusable:
+
+ pci 0000:00:11.0: bridge window [io 0xe000-0xefff] released
+ pci 0000:00:11.0: bridge window [io 0x1000-0x2fff] # reassigned
+ pci 0000:01:00.0: bridge window [io 0x1000-0x2fff] # reassigned
+ pci 0000:02:02.0: bridge window [io 0x2000-0x2fff] # reassigned
+ pci 0000:05:00.0: bridge window [io 0x2000-0x2fff] # reassigned
+ pci 0000:06:08.0: BAR 4: assigned [io 0xfce0-0xfcff] # left alone
+ pci 0000:06:08.1: BAR 4: assigned [io 0x2000-0x201f]
+ ...
+ 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 the address assigned by firmware is not reachable because it's not
+within upstream bridge windows, fail instead of assigning the unusable
+address from firmware.
+
+[bhelgaas: commit log, use pci_upstream_bridge()]
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=16263
+Link: https://lore.kernel.org/r/alpine.DEB.2.21.2203012338460.46819@angie.orcam.me.uk
+Link: https://lore.kernel.org/r/alpine.DEB.2.21.2209211921250.29493@angie.orcam.me.uk
+Fixes: 58c84eda0756 ("PCI: fall back to original BIOS BAR addresses")
+Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org # v2.6.35+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/setup-res.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/pci/setup-res.c
++++ b/drivers/pci/setup-res.c
+@@ -214,6 +214,17 @@ static int pci_revert_fw_address(struct
+
+ root = pci_find_parent_resource(dev, res);
+ if (!root) {
++ /*
++ * If dev is behind a bridge, accesses will only reach it
++ * if res is inside the relevant bridge window.
++ */
++ if (pci_upstream_bridge(dev))
++ return -ENXIO;
++
++ /*
++ * On the root bus, assume the host bridge will forward
++ * everything.
++ */
+ if (res->flags & IORESOURCE_IO)
+ root = &ioport_resource;
+ else