aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2019-06-19 11:06:11 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2019-06-24 12:29:48 +1000
commiteb586fc14ed98d4c0e54f96120e5f936f1c5546a (patch)
tree375c9ae4dc44326705f09b071ca5fb61b55c5f61
parent083f5b241de1190158b3650799efecc81778e355 (diff)
downloadpci-previous.tar.gz
pci: Use multi-pass resource claiming in pci_bus_allocate_dev_resources()previous
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> # Conflicts: # drivers/pci/setup-bus.c
-rw-r--r--drivers/pci/setup-bus.c64
1 files changed, 49 insertions, 15 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 9fbce98941e95..438b92e2fad66 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1382,21 +1382,53 @@ bool __weak pcibios_claim_zero_resource(struct pci_dev *dev, int rsrc_idx,
return 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,
enum pci_rsrc_policy policy)
{
- 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, policy))
- 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, policy))
+ 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, enum pci_rsrc_policy policy)
@@ -1415,17 +1447,18 @@ static void pci_claim_bridge_resources(struct pci_dev *dev, enum pci_rsrc_policy
}
}
-static void pci_bus_allocate_dev_resources(struct pci_bus *b, enum pci_rsrc_policy policy)
+static void pci_bus_allocate_dev_resources(struct pci_bus *b, int pass,
+ enum pci_rsrc_policy policy)
{
struct pci_dev *dev;
struct pci_bus *child;
list_for_each_entry(dev, &b->devices, bus_list) {
- pci_claim_device_resources(dev, policy);
+ pci_claim_device_resources(dev, pass, policy);
child = dev->subordinate;
if (child)
- pci_bus_allocate_dev_resources(child, policy);
+ pci_bus_allocate_dev_resources(child, pass, policy);
}
}
@@ -2185,7 +2218,8 @@ void pci_host_resource_survey(struct pci_bus *bus, enum pci_rsrc_policy policy)
/* Claim existing resources if required */
if (policy < pci_rsrc_assign_only) {
pci_bus_allocate_resources(bus, policy);
- pci_bus_allocate_dev_resources(bus, policy);
+ pci_bus_allocate_dev_resources(bus, 0, policy);
+ pci_bus_allocate_dev_resources(bus, 1, policy);
}
/*