Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d09ee968 authored by Yinghai Lu's avatar Yinghai Lu Committed by Jesse Barnes
Browse files

PCI: improve resource allocation under transparent bridges



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: default avatarIvan Kokshaysky <ink@jurassic.park.msu.ru>
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 1f82de10
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -58,7 +58,6 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
		res = list->res;
		res = list->res;
		idx = res - &list->dev->resource[0];
		idx = res - &list->dev->resource[0];
		if (pci_assign_resource(list->dev, idx)) {
		if (pci_assign_resource(list->dev, idx)) {
			/* FIXME: get rid of this */
			res->start = 0;
			res->start = 0;
			res->end = 0;
			res->end = 0;
			res->flags = 0;
			res->flags = 0;
+36 −13
Original line number Original line Diff line number Diff line
@@ -135,23 +135,16 @@ void pci_disable_bridge_window(struct pci_dev *dev)
}
}
#endif	/* CONFIG_PCI_QUIRKS */
#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;
	struct resource *res = dev->resource + resno;
	resource_size_t size, min, align;
	resource_size_t size, min, align;
	int ret;
	int ret;


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

	align = resource_alignment(res);
	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.. */
	/* First, try exact prefetching match.. */
	ret = pci_bus_alloc_resource(bus, res, size, align, min,
	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);
					     pcibios_align_resource, dev);
	}
	}


	if (ret) {
	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 {
		res->flags &= ~IORESOURCE_STARTALIGN;
		res->flags &= ~IORESOURCE_STARTALIGN;
		if (resno < PCI_BRIDGE_RESOURCES)
		if (resno < PCI_BRIDGE_RESOURCES)
			pci_update_resource(dev, resno);
			pci_update_resource(dev, resno);
@@ -181,6 +171,39 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
	return ret;
	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
#if 0
int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
{
{