Skip to content

Commit

Permalink
PCI: improve resource allocation under transparent bridges
Browse files Browse the repository at this point in the history
We could run out of space under under 4g, but devices under transparent
bridges can use 64bit resources, so keep trying on the parent bus until
we hit a non-transparent bridge.

Impact: better support for assigning unassigned resources

Reviewed-by: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
  • Loading branch information
Yinghai Lu authored and Jesse Barnes committed Jun 11, 2009
1 parent 1f82de1 commit d09ee96
Showing 2 changed files with 36 additions and 14 deletions.
1 change: 0 additions & 1 deletion drivers/pci/setup-bus.c
Original file line number Diff line number Diff line change
@@ -58,7 +58,6 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
res = list->res;
idx = res - &list->dev->resource[0];
if (pci_assign_resource(list->dev, idx)) {
/* FIXME: get rid of this */
res->start = 0;
res->end = 0;
res->flags = 0;
49 changes: 36 additions & 13 deletions drivers/pci/setup-res.c
Original file line number Diff line number Diff line change
@@ -135,23 +135,16 @@ void pci_disable_bridge_window(struct pci_dev *dev)
}
#endif /* CONFIG_PCI_QUIRKS */

int pci_assign_resource(struct pci_dev *dev, int resno)
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
int resno)
{
struct pci_bus *bus = dev->bus;
struct resource *res = dev->resource + resno;
resource_size_t size, min, align;
int ret;

size = resource_size(res);
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;

align = resource_alignment(res);
if (!align) {
dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
"alignment) %pR flags %#lx\n",
resno, res, res->flags);
return -EINVAL;
}

/* First, try exact prefetching match.. */
ret = pci_bus_alloc_resource(bus, res, size, align, min,
@@ -169,10 +162,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
pcibios_align_resource, dev);
}

if (ret) {
dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
} else {
if (!ret) {
res->flags &= ~IORESOURCE_STARTALIGN;
if (resno < PCI_BRIDGE_RESOURCES)
pci_update_resource(dev, resno);
@@ -181,6 +171,39 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
return ret;
}

int pci_assign_resource(struct pci_dev *dev, int resno)
{
struct resource *res = dev->resource + resno;
resource_size_t align;
struct pci_bus *bus;
int ret;

align = resource_alignment(res);
if (!align) {
dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
"alignment) %pR flags %#lx\n",
resno, res, res->flags);
return -EINVAL;
}

bus = dev->bus;
while ((ret = __pci_assign_resource(bus, dev, resno))) {
if (bus->parent && bus->self->transparent)
bus = bus->parent;
else
bus = NULL;
if (bus)
continue;
break;
}

if (ret)
dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);

return ret;
}

#if 0
int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
{

0 comments on commit d09ee96

Please sign in to comment.