From: Guenter Roeck <linux@roeck-us.net>
Subject: [PATCH] PCI: Only try to assign io port only if root bus support that
The PCI subsystem always assumes that I/O is supported on root bus and
tries to assign an I/O window to each child bus even if that is not the
case.
This may result in messages such as:
pcieport 0000:02:00.0: res[7]=[io 0x1000-0x0fff] get_res_add_size add_size 1000
pcieport 0000:02:00.0: BAR 7: no space for [io size 0x1000]
pcieport 0000:02:00.0: BAR 7: failed to assign [io size 0x1000]
for each bridge port, even if root does not support I/O in the first place.
To avoid this message, check if root bus supports I/O, then child bus
will inherit the setting from parent bus, and later during sizing and
assigning, check that bus flags and skip those resources.
[bhelgaas: reverse sense of new pci_bus_flags_t value]
[yinghai: only check root bus io port, and use flag on sizing and assigning]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
CC: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
drivers/pci/probe.c | 5 +++++
drivers/pci/setup-bus.c | 9 +++++++++
include/linux/pci.h | 1 +
3 files changed, 15 insertions(+)
===================================================================
@@ -340,6 +340,9 @@ static void pci_read_bridge_io(struct pc
struct pci_bus_region region;
struct resource *res;
+ if (!(child->bus_flags & PCI_BUS_FLAGS_ROOT_SUPPORTS_IO))
+ return;
+
io_mask = PCI_IO_RANGE_MASK;
io_granularity = 0x1000;
if (dev->io_window_1k) {
@@ -2070,6 +2073,8 @@ struct pci_bus *pci_create_root_bus(stru
} else
bus_addr[0] = '\0';
dev_info(&b->dev, "root bus resource %pR%s\n", res, bus_addr);
+ if (resource_type(res) == IORESOURCE_IO)
+ b->bus_flags |= PCI_BUS_FLAGS_ROOT_SUPPORTS_IO;
}
down_write(&pci_bus_sem);
===================================================================
@@ -156,6 +156,10 @@ static void pdev_sort_resources(struct p
if (r->flags & IORESOURCE_PCI_FIXED)
continue;
+ if ((r->flags & IORESOURCE_IO) &&
+ !(dev->bus->bus_flags & PCI_BUS_FLAGS_ROOT_SUPPORTS_IO))
+ continue;
+
if (!(r->flags) || r->parent)
continue;
@@ -912,6 +916,11 @@ static void pbus_size_io(struct pci_bus
if (!b_res)
return;
+ if (!(bus->bus_flags & PCI_BUS_FLAGS_ROOT_SUPPORTS_IO)) {
+ b_res->flags = 0;
+ return;
+ }
+
min_align = window_alignment(bus, IORESOURCE_IO);
list_for_each_entry(dev, &bus->devices, bus_list) {
int i;
===================================================================
@@ -193,6 +193,7 @@ typedef unsigned short __bitwise pci_bus
enum pci_bus_flags {
PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
+ PCI_BUS_FLAGS_ROOT_SUPPORTS_IO = (__force pci_bus_flags_t) 4,
};
/* These values come from the PCI Express Spec */