X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Facpi%2Fpci_root.c;h=2adaba68b85b7fc8bd1b00d88c1bcdbf1bce679a;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=3d19331bc088bd0ff68c275651ef9d0bf39e2c91;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 3d19331bc..2adaba68b 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -90,6 +90,7 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver) return n; } +EXPORT_SYMBOL(acpi_pci_register_driver); void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) { @@ -112,6 +113,41 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) driver->remove(root->handle); } } +EXPORT_SYMBOL(acpi_pci_unregister_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 ( @@ -190,9 +226,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