Commit 06648ed5 authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] PCI bus numbering workaround for ServerWorks

from David Shaohua Li
http://bugzilla.kernel.org/show_bug.cgi?id=1662
parent 98b20278
......@@ -113,6 +113,40 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
}
}
static acpi_status
get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data)
{
int *busnr = (int *)data;
struct acpi_resource_address64 address;
if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
resource->id != ACPI_RSTYPE_ADDRESS32 &&
resource->id != ACPI_RSTYPE_ADDRESS64)
return AE_OK;
acpi_resource_to_address64(resource, &address);
if ((address.address_length > 0) &&
(address.resource_type == ACPI_BUS_NUMBER_RANGE))
*busnr = address.min_address_range;
return AE_OK;
}
static acpi_status
try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
{
acpi_status status;
*busnum = -1;
status = acpi_walk_resources(handle, METHOD_NAME__CRS, get_root_bridge_busnr_callback, busnum);
if (ACPI_FAILURE(status))
return status;
/* Check if we really get a bus number from _CRS */
if (*busnum == -1)
return AE_ERROR;
return AE_OK;
}
static int
acpi_pci_root_add (
struct acpi_device *device)
......@@ -190,9 +224,22 @@ acpi_pci_root_add (
/* Some systems have wrong _BBN */
list_for_each_entry(tmp, &acpi_pci_roots, node) {
if ((tmp->id.segment == root->id.segment)
&& (tmp->id.bus == root->id.bus))
&& (tmp->id.bus == root->id.bus)) {
int bus = 0;
acpi_status status;
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
status = try_get_root_bridge_busnr(root->handle, &bus);
if (ACPI_FAILURE(status))
break;
if (bus != root->id.bus) {
printk(KERN_INFO PREFIX "PCI _CRS %d overrides _BBN 0\n", bus);
root->id.bus = bus;
}
break;
}
}
/*
* Device & Function
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment