PCI: add pci_bridge_release_resources and pci_bus_release_bridge_resources
We use this in later patches to free resrouce ranges for reassignment in an effort to support a wider variety of PCI topologies. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Reviewed-by: Alex Chiang <achiang@hp.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
ba02b242bb
commit
5009b46025
|
@ -604,6 +604,88 @@ void __ref pci_bus_assign_resources(const struct pci_bus *bus)
|
|||
}
|
||||
EXPORT_SYMBOL(pci_bus_assign_resources);
|
||||
|
||||
static void pci_bridge_release_resources(struct pci_bus *bus,
|
||||
unsigned long type)
|
||||
{
|
||||
int idx;
|
||||
bool changed = false;
|
||||
struct pci_dev *dev;
|
||||
struct resource *r;
|
||||
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
|
||||
IORESOURCE_PREFETCH;
|
||||
|
||||
dev = bus->self;
|
||||
for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END;
|
||||
idx++) {
|
||||
r = &dev->resource[idx];
|
||||
if ((r->flags & type_mask) != type)
|
||||
continue;
|
||||
if (!r->parent)
|
||||
continue;
|
||||
/*
|
||||
* if there are children under that, we should release them
|
||||
* all
|
||||
*/
|
||||
release_child_resources(r);
|
||||
if (!release_resource(r)) {
|
||||
dev_printk(KERN_DEBUG, &dev->dev,
|
||||
"resource %d %pR released\n", idx, r);
|
||||
/* keep the old size */
|
||||
r->end = resource_size(r) - 1;
|
||||
r->start = 0;
|
||||
r->flags = 0;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
/* avoiding touch the one without PREF */
|
||||
if (type & IORESOURCE_PREFETCH)
|
||||
type = IORESOURCE_PREFETCH;
|
||||
__pci_setup_bridge(bus, type);
|
||||
}
|
||||
}
|
||||
|
||||
enum release_type {
|
||||
leaf_only,
|
||||
whole_subtree,
|
||||
};
|
||||
/*
|
||||
* try to release pci bridge resources that is from leaf bridge,
|
||||
* so we can allocate big new one later
|
||||
*/
|
||||
static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus,
|
||||
unsigned long type,
|
||||
enum release_type rel_type)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
bool is_leaf_bridge = true;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
struct pci_bus *b = dev->subordinate;
|
||||
if (!b)
|
||||
continue;
|
||||
|
||||
is_leaf_bridge = false;
|
||||
|
||||
if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
|
||||
continue;
|
||||
|
||||
if (rel_type == whole_subtree)
|
||||
pci_bus_release_bridge_resources(b, type,
|
||||
whole_subtree);
|
||||
}
|
||||
|
||||
if (pci_is_root_bus(bus))
|
||||
return;
|
||||
|
||||
if ((bus->self->class >> 8) != PCI_CLASS_BRIDGE_PCI)
|
||||
return;
|
||||
|
||||
if ((rel_type == whole_subtree) || is_leaf_bridge)
|
||||
pci_bridge_release_resources(bus, type);
|
||||
}
|
||||
|
||||
static void pci_bus_dump_res(struct pci_bus *bus)
|
||||
{
|
||||
int i;
|
||||
|
|
Loading…
Reference in New Issue