diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2019-06-19 11:06:11 +1000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2019-06-24 12:29:48 +1000 |
commit | eb586fc14ed98d4c0e54f96120e5f936f1c5546a (patch) | |
tree | 375c9ae4dc44326705f09b071ca5fb61b55c5f61 | |
parent | 083f5b241de1190158b3650799efecc81778e355 (diff) | |
download | pci-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.c | 64 |
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); } /* |