diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2019-06-24 12:29:25 +1000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2019-06-29 10:41:50 +1000 |
commit | cf266e043b31977fb3724bb446c8cc9d5800e796 (patch) | |
tree | eb1dd5b332701862c53dc3a0274203564807ada6 | |
parent | a153e07305211a3c21fdc620d47f7b58bffd6eed (diff) | |
download | pci-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.c | 63 |
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 */ |