Commit 7c3855c4 authored by Kai-Heng Feng's avatar Kai-Heng Feng Committed by Bjorn Helgaas

PCI: Coalesce host bridge contiguous apertures

Built-in graphics at 07:00.0 on HP EliteDesk 805 G6 doesn't work because
graphics can't get the BAR it needs.  The BIOS configuration is
correct: BARs 0 and 2 both fit in the 00:08.1 bridge window.

But that 00:08.1 window covers two host bridge apertures from _CRS.
Previously we assumed this was illegal, so we clipped the window to fit
into one aperture (see 0f7e7aee ("PCI: Add pci_bus_clip_resource() to
clip to fit upstream window")).

  pci_bus 0000:00: root bus resource [mem 0x10020200000-0x100303fffff window]
  pci_bus 0000:00: root bus resource [mem 0x10030400000-0x100401fffff window]

  pci 0000:00:08.1:   bridge window [mem 0x10030000000-0x100401fffff 64bit pref]
  pci 0000:07:00.0: reg 0x10: [mem 0x10030000000-0x1003fffffff 64bit pref]
  pci 0000:07:00.0: reg 0x18: [mem 0x10040000000-0x100401fffff 64bit pref]

  pci 0000:00:08.1: can't claim BAR 15 [mem 0x10030000000-0x100401fffff 64bit pref]: no compatible bridge window
  pci 0000:00:08.1: [mem 0x10030000000-0x100401fffff 64bit pref] clipped to [mem 0x10030000000-0x100303fffff 64bit pref]
  pci 0000:00:08.1:   bridge window [mem 0x10030000000-0x100303fffff 64bit pref]

  pci 0000:07:00.0: can't claim BAR 0 [mem 0x10030000000-0x1003fffffff 64bit pref]: no compatible bridge window
  pci 0000:07:00.0: can't claim BAR 2 [mem 0x10040000000-0x100401fffff 64bit pref]: no compatible bridge window

However, the host bridge apertures are contiguous, so there's no need to
clip in this case.  Coalesce contiguous apertures so we can allocate from
the entire contiguous region.

Previous commit 65db0405 ("PCI: Coalesce host bridge contiguous
apertures") was similar but sorted the apertures, and Guenter Roeck
reported a regression in ppc:sam460ex qemu emulation from nvme; see
https://lore.kernel.org/all/20210709231529.GA3270116@roeck-us.net/

[bhelgaas: commit log]
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=212013Suggested-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Link: https://lore.kernel.org/r/20210713125007.1260304-1-kai.heng.feng@canonical.comSigned-off-by: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Cc: Guenter Roeck <linux@roeck-us.net>
parent e4e737bb
...@@ -883,11 +883,11 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus) ...@@ -883,11 +883,11 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus)
static int pci_register_host_bridge(struct pci_host_bridge *bridge) static int pci_register_host_bridge(struct pci_host_bridge *bridge)
{ {
struct device *parent = bridge->dev.parent; struct device *parent = bridge->dev.parent;
struct resource_entry *window, *n; struct resource_entry *window, *next, *n;
struct pci_bus *bus, *b; struct pci_bus *bus, *b;
resource_size_t offset; resource_size_t offset, next_offset;
LIST_HEAD(resources); LIST_HEAD(resources);
struct resource *res; struct resource *res, *next_res;
char addr[64], *fmt; char addr[64], *fmt;
const char *name; const char *name;
int err; int err;
...@@ -970,11 +970,34 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge) ...@@ -970,11 +970,34 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE) if (nr_node_ids > 1 && pcibus_to_node(bus) == NUMA_NO_NODE)
dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n"); dev_warn(&bus->dev, "Unknown NUMA node; performance will be reduced\n");
/* Coalesce contiguous windows */
resource_list_for_each_entry_safe(window, n, &resources) {
if (list_is_last(&window->node, &resources))
break;
next = list_next_entry(window, node);
offset = window->offset;
res = window->res;
next_offset = next->offset;
next_res = next->res;
if (res->flags != next_res->flags || offset != next_offset)
continue;
if (res->end + 1 == next_res->start) {
next_res->start = res->start;
res->flags = res->start = res->end = 0;
}
}
/* Add initial resources to the bus */ /* Add initial resources to the bus */
resource_list_for_each_entry_safe(window, n, &resources) { resource_list_for_each_entry_safe(window, n, &resources) {
list_move_tail(&window->node, &bridge->windows);
offset = window->offset; offset = window->offset;
res = window->res; res = window->res;
if (!res->end)
continue;
list_move_tail(&window->node, &bridge->windows);
if (res->flags & IORESOURCE_BUS) if (res->flags & IORESOURCE_BUS)
pci_bus_insert_busn_res(bus, bus->number, res->end); pci_bus_insert_busn_res(bus, bus->number, res->end);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment