aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2019-06-24 12:29:25 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2019-06-29 10:41:50 +1000
commitcf266e043b31977fb3724bb446c8cc9d5800e796 (patch)
treeeb1dd5b332701862c53dc3a0274203564807ada6
parenta153e07305211a3c21fdc620d47f7b58bffd6eed (diff)
downloadpci-cf266e043b31977fb3724bb446c8cc9d5800e796.tar.gz
PCI: Use multi-pass resource claiming in pci_bus_allocate_dev_resources()
This brings the generic resource claiming code a few steps closer to x86 (and to some extent powerpc) by using a multi-pass mechanism that will prefer enabled resources in the first pass and will claim non-IOV resources before IOV resources. The remaining differences with x86 are: - The code to disable ROM BARs will come later - We claim ROM resources (in pass 1 only). This will have to eventually be moved elsewhere so x86 can control it the way it does today. - We check for r->flags being 0 (x86 doesn't for some reason) - We honor IORESOURCE_UNSET Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--drivers/pci/setup-bus.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 0415818488f47d..941bdb1010fef4 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1383,20 +1383,52 @@ bool __weak pcibios_claim_zero_resource(struct pci_dev *dev, int rsrc_idx)
return host->rsrc_policy == pci_rsrc_claim_only;
}
-static void pci_claim_device_resources(struct pci_dev *dev)
+static void pci_claim_device_resources(struct pci_dev *dev, int pass)
{
- int i;
-
- for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
- struct resource *r = &dev->resource[i];
+ int idx, disabled, i;
+ u16 command;
+ struct resource *r;
- if (!r->flags || r->parent)
- continue;
- if (!r->start && !pcibios_claim_zero_resource(dev, i))
- continue;
+ struct {
+ int start;
+ int end;
+ } idx_range[] = {
+ { PCI_STD_RESOURCES, PCI_ROM_RESOURCE },
+#ifdef CONFIG_PCI_IOV
+ { PCI_IOV_RESOURCES, PCI_IOV_RESOURCE_END },
+#endif
+ };
- pci_claim_resource(dev, i);
- }
+ pci_read_config_word(dev, PCI_COMMAND, &command);
+ for (i = 0; i < ARRAY_SIZE(idx_range); i++)
+ for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
+ r = &dev->resource[idx];
+ if (!r->flags || r->parent || (r->flags & IORESOURCE_UNSET))
+ continue;
+ if (!r->start && !pcibios_claim_zero_resource(dev, i))
+ continue;
+ if (idx == PCI_ROM_RESOURCE)
+ disabled = 1;
+ else if (r->flags & IORESOURCE_IO)
+ disabled = !(command & PCI_COMMAND_IO);
+ else
+ disabled = !(command & PCI_COMMAND_MEMORY);
+ if (pass == disabled) {
+ dev_dbg(&dev->dev,
+ "BAR %d: reserving %pr (d=%d, p=%d)\n",
+ idx, r, disabled, pass);
+ if (pci_claim_resource(dev, idx) < 0) {
+ if (r->flags & IORESOURCE_PCI_FIXED) {
+ dev_info(&dev->dev, "BAR %d %pR is immovable\n",
+ idx, r);
+ } else {
+ /* We'll assign a new address later */
+ r->end -= r->start;
+ r->start = 0;
+ }
+ }
+ }
+ }
}
static void pci_claim_bridge_resources(struct pci_dev *dev)
@@ -1415,17 +1447,17 @@ static void pci_claim_bridge_resources(struct pci_dev *dev)
}
}
-static void pci_bus_allocate_dev_resources(struct pci_bus *b)
+static void pci_bus_allocate_dev_resources(struct pci_bus *b, int pass)
{
struct pci_dev *dev;
struct pci_bus *child;
list_for_each_entry(dev, &b->devices, bus_list) {
- pci_claim_device_resources(dev);
+ pci_claim_device_resources(dev, pass);
child = dev->subordinate;
if (child)
- pci_bus_allocate_dev_resources(child);
+ pci_bus_allocate_dev_resources(child, pass);
}
}
@@ -2178,7 +2210,8 @@ void pci_host_resource_survey(struct pci_bus *bus)
/* Claim existing resources if required */
if (host->rsrc_policy <= pci_rsrc_claim_assign) {
pci_bus_allocate_resources(bus);
- pci_bus_allocate_dev_resources(bus);
+ pci_bus_allocate_dev_resources(bus, 0);
+ pci_bus_allocate_dev_resources(bus, 1);
}
/* If we do any kind of assignment, do it now */