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: Gary Hade <garyhade@us.ibm.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
Родитель
ab7de999a2
Коммит
f9cde5ffed
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче