diff options
author | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2016-06-08 12:04:47 +0100 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-06-23 11:48:59 -0500 |
commit | 765bf9b739731b925ca26a8f05765b87f2bd9724 (patch) | |
tree | 4d927ae75b8bfc8a75e74cf7d355b6b13412d870 /drivers/pci/setup-bus.c | |
parent | caa8e9323e5a4d012c8bd16bc9ef2a444af8243a (diff) | |
download | linux-stable-765bf9b739731b925ca26a8f05765b87f2bd9724.tar.gz linux-stable-765bf9b739731b925ca26a8f05765b87f2bd9724.tar.bz2 linux-stable-765bf9b739731b925ca26a8f05765b87f2bd9724.zip |
PCI: Add generic pci_bus_claim_resources()
All PCI resources (bridge windows and BARs) should be inserted in the
iomem_resource and ioport_resource trees so we know what space is occupied
and what is available for other devices. There's nothing arch-specific
about this, but it is currently done by arch-specific code.
Add a generic pci_bus_claim_resources() interface so we can migrate away
from the arch-specific code.
[bhelgaas: changelog]
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
CC: Arnd Bergmann <arnd@arndb.de>
CC: Yinghai Lu <yinghai@kernel.org>
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r-- | drivers/pci/setup-bus.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 55641a39a3e9..1d1a2c952c35 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1423,6 +1423,74 @@ void pci_bus_assign_resources(const struct pci_bus *bus) } EXPORT_SYMBOL(pci_bus_assign_resources); +static void pci_claim_device_resources(struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + + if (!r->flags || r->parent) + continue; + + pci_claim_resource(dev, i); + } +} + +static void pci_claim_bridge_resources(struct pci_dev *dev) +{ + int i; + + for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + + if (!r->flags || r->parent) + continue; + + pci_claim_bridge_resource(dev, i); + } +} + +static void pci_bus_allocate_dev_resources(struct pci_bus *b) +{ + struct pci_dev *dev; + struct pci_bus *child; + + list_for_each_entry(dev, &b->devices, bus_list) { + pci_claim_device_resources(dev); + + child = dev->subordinate; + if (child) + pci_bus_allocate_dev_resources(child); + } +} + +static void pci_bus_allocate_resources(struct pci_bus *b) +{ + struct pci_bus *child; + + /* + * Carry out a depth-first search on the PCI bus + * tree to allocate bridge apertures. Read the + * programmed bridge bases and recursively claim + * the respective bridge resources. + */ + if (b->self) { + pci_read_bridge_bases(b); + pci_claim_bridge_resources(b->self); + } + + list_for_each_entry(child, &b->children, node) + pci_bus_allocate_resources(child); +} + +void pci_bus_claim_resources(struct pci_bus *b) +{ + pci_bus_allocate_resources(b); + pci_bus_allocate_dev_resources(b); +} +EXPORT_SYMBOL(pci_bus_claim_resources); + static void __pci_bridge_assign_resources(const struct pci_dev *bridge, struct list_head *add_head, struct list_head *fail_head) |