VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / acpi / pci_root.c
index 3d19331..dd08b63 100644 (file)
@@ -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