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

Commit f9cde5ff authored by Gary Hade's avatar Gary Hade Committed by Jesse Barnes
Browse files

x86/ACPI: Correct maximum allowed _CRS returned resources and warn if exceeded



Issue a warning if _CRS returns too many resource descriptors to be
accommodated by the fixed size resource array instances.  If there is no
transparent bridge on the root bus "too many" is the
PCI_BUS_NUM_RESOURCES size of the resource array.  Otherwise, the last 3
slots of the resource array must be excluded making the maximum
(PCI_BUS_NUM_RESOURCES - 3).

The current code:
 - is silent when _CRS returns too many resource descriptors and
 - incorrectly allows use of the last 3 slots of the resource array
   for a root bus with a transparent bridge

Signed-off-by: default avatarGary Hade <garyhade@us.ibm.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent ab7de999
Loading
Loading
Loading
Loading
+27 −6
Original line number Diff line number Diff line
@@ -38,15 +38,26 @@ count_resource(struct acpi_resource *acpi_res, void *data)
	struct acpi_resource_address64 addr;
	acpi_status status;

	if (info->res_num >= PCI_BUS_NUM_RESOURCES)
		return AE_OK;

	status = resource_to_addr(acpi_res, &addr);
	if (ACPI_SUCCESS(status))
		info->res_num++;
	return AE_OK;
}

static int
bus_has_transparent_bridge(struct pci_bus *bus)
{
	struct pci_dev *dev;

	list_for_each_entry(dev, &bus->devices, bus_list) {
		u16 class = dev->class >> 8;

		if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
			return true;
	}
	return false;
}

static acpi_status
setup_resource(struct acpi_resource *acpi_res, void *data)
{
@@ -56,9 +67,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
	acpi_status status;
	unsigned long flags;
	struct resource *root;

	if (info->res_num >= PCI_BUS_NUM_RESOURCES)
		return AE_OK;
	int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;

	status = resource_to_addr(acpi_res, &addr);
	if (!ACPI_SUCCESS(status))
@@ -82,6 +91,18 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
	res->end = res->start + addr.address_length - 1;
	res->child = NULL;

	if (bus_has_transparent_bridge(info->bus))
		max_root_bus_resources -= 3;
	if (info->res_num >= max_root_bus_resources) {
		printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
			"from %s for %s due to _CRS returning more than "
			"%d resource descriptors\n", (unsigned long) res->start,
			(unsigned long) res->end, root->name, info->name,
			max_root_bus_resources);
		info->res_num++;
		return AE_OK;
	}

	if (insert_resource(root, res)) {
		printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
			"from %s for %s\n", (unsigned long) res->start,