diff options
| -rw-r--r-- | drivers/acpi/pci_root.c | 67 | ||||
| -rw-r--r-- | include/acpi/acpi_bus.h | 2 |
2 files changed, 41 insertions, 28 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d724736d56c8..bf476fea97ab 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -119,7 +119,8 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | |||
| 119 | struct acpi_pci_root *root; | 119 | struct acpi_pci_root *root; |
| 120 | 120 | ||
| 121 | list_for_each_entry(root, &acpi_pci_roots, node) | 121 | list_for_each_entry(root, &acpi_pci_roots, node) |
| 122 | if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) | 122 | if ((root->segment == (u16) seg) && |
| 123 | (root->secondary.start == (u16) bus)) | ||
| 123 | return root->device->handle; | 124 | return root->device->handle; |
| 124 | return NULL; | 125 | return NULL; |
| 125 | } | 126 | } |
| @@ -153,7 +154,7 @@ EXPORT_SYMBOL_GPL(acpi_is_root_bridge); | |||
| 153 | static acpi_status | 154 | static acpi_status |
| 154 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | 155 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) |
| 155 | { | 156 | { |
| 156 | int *busnr = data; | 157 | struct resource *res = data; |
| 157 | struct acpi_resource_address64 address; | 158 | struct acpi_resource_address64 address; |
| 158 | 159 | ||
| 159 | if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && | 160 | if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && |
| @@ -163,28 +164,27 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | |||
| 163 | 164 | ||
| 164 | acpi_resource_to_address64(resource, &address); | 165 | acpi_resource_to_address64(resource, &address); |
| 165 | if ((address.address_length > 0) && | 166 | if ((address.address_length > 0) && |
| 166 | (address.resource_type == ACPI_BUS_NUMBER_RANGE)) | 167 | (address.resource_type == ACPI_BUS_NUMBER_RANGE)) { |
| 167 | *busnr = address.minimum; | 168 | res->start = address.minimum; |
| 169 | res->end = address.minimum + address.address_length - 1; | ||
| 170 | } | ||
| 168 | 171 | ||
| 169 | return AE_OK; | 172 | return AE_OK; |
| 170 | } | 173 | } |
| 171 | 174 | ||
| 172 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, | 175 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, |
| 173 | unsigned long long *bus) | 176 | struct resource *res) |
| 174 | { | 177 | { |
| 175 | acpi_status status; | 178 | acpi_status status; |
| 176 | int busnum; | ||
| 177 | 179 | ||
| 178 | busnum = -1; | 180 | res->start = -1; |
| 179 | status = | 181 | status = |
| 180 | acpi_walk_resources(handle, METHOD_NAME__CRS, | 182 | acpi_walk_resources(handle, METHOD_NAME__CRS, |
| 181 | get_root_bridge_busnr_callback, &busnum); | 183 | get_root_bridge_busnr_callback, res); |
| 182 | if (ACPI_FAILURE(status)) | 184 | if (ACPI_FAILURE(status)) |
| 183 | return status; | 185 | return status; |
| 184 | /* Check if we really get a bus number from _CRS */ | 186 | if (res->start == -1) |
| 185 | if (busnum == -1) | ||
| 186 | return AE_ERROR; | 187 | return AE_ERROR; |
| 187 | *bus = busnum; | ||
| 188 | return AE_OK; | 188 | return AE_OK; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| @@ -428,34 +428,47 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 428 | struct acpi_device *child; | 428 | struct acpi_device *child; |
| 429 | u32 flags, base_flags; | 429 | u32 flags, base_flags; |
| 430 | 430 | ||
| 431 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | ||
| 432 | if (!root) | ||
| 433 | return -ENOMEM; | ||
| 434 | |||
| 431 | segment = 0; | 435 | segment = 0; |
| 432 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, | 436 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, |
| 433 | &segment); | 437 | &segment); |
| 434 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 438 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { |
| 435 | printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); | 439 | printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); |
| 436 | return -ENODEV; | 440 | result = -ENODEV; |
| 441 | goto end; | ||
| 437 | } | 442 | } |
| 438 | 443 | ||
| 439 | /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ | 444 | /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ |
| 440 | bus = 0; | 445 | root->secondary.flags = IORESOURCE_BUS; |
| 441 | status = try_get_root_bridge_busnr(device->handle, &bus); | 446 | status = try_get_root_bridge_busnr(device->handle, &root->secondary); |
| 442 | if (ACPI_FAILURE(status)) { | 447 | if (ACPI_FAILURE(status)) { |
| 448 | /* | ||
| 449 | * We need both the start and end of the downstream bus range | ||
| 450 | * to interpret _CBA (MMCONFIG base address), so it really is | ||
| 451 | * supposed to be in _CRS. If we don't find it there, all we | ||
| 452 | * can do is assume [_BBN-0xFF] or [0-0xFF]. | ||
| 453 | */ | ||
| 454 | root->secondary.end = 0xFF; | ||
| 455 | printk(KERN_WARNING FW_BUG PREFIX | ||
| 456 | "no secondary bus range in _CRS\n"); | ||
| 443 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); | 457 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); |
| 444 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 458 | if (ACPI_SUCCESS(status)) |
| 445 | printk(KERN_ERR PREFIX | 459 | root->secondary.start = bus; |
| 446 | "no bus number in _CRS and can't evaluate _BBN\n"); | 460 | else if (status == AE_NOT_FOUND) |
| 447 | return -ENODEV; | 461 | root->secondary.start = 0; |
| 462 | else { | ||
| 463 | printk(KERN_ERR PREFIX "can't evaluate _BBN\n"); | ||
| 464 | result = -ENODEV; | ||
| 465 | goto end; | ||
| 448 | } | 466 | } |
| 449 | } | 467 | } |
| 450 | 468 | ||
| 451 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | ||
| 452 | if (!root) | ||
| 453 | return -ENOMEM; | ||
| 454 | |||
| 455 | INIT_LIST_HEAD(&root->node); | 469 | INIT_LIST_HEAD(&root->node); |
| 456 | root->device = device; | 470 | root->device = device; |
| 457 | root->segment = segment & 0xFFFF; | 471 | root->segment = segment & 0xFFFF; |
| 458 | root->bus_nr = bus & 0xFF; | ||
| 459 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); | 472 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); |
| 460 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); | 473 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); |
| 461 | device->driver_data = root; | 474 | device->driver_data = root; |
| @@ -474,9 +487,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 474 | /* TBD: Locking */ | 487 | /* TBD: Locking */ |
| 475 | list_add_tail(&root->node, &acpi_pci_roots); | 488 | list_add_tail(&root->node, &acpi_pci_roots); |
| 476 | 489 | ||
| 477 | printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", | 490 | printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", |
| 478 | acpi_device_name(device), acpi_device_bid(device), | 491 | acpi_device_name(device), acpi_device_bid(device), |
| 479 | root->segment, root->bus_nr); | 492 | root->segment, &root->secondary); |
| 480 | 493 | ||
| 481 | /* | 494 | /* |
| 482 | * Scan the Root Bridge | 495 | * Scan the Root Bridge |
| @@ -485,11 +498,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 485 | * PCI namespace does not get created until this call is made (and | 498 | * PCI namespace does not get created until this call is made (and |
| 486 | * thus the root bridge's pci_dev does not exist). | 499 | * thus the root bridge's pci_dev does not exist). |
| 487 | */ | 500 | */ |
| 488 | root->bus = pci_acpi_scan_root(device, segment, bus); | 501 | root->bus = pci_acpi_scan_root(device, segment, root->secondary.start); |
| 489 | if (!root->bus) { | 502 | if (!root->bus) { |
| 490 | printk(KERN_ERR PREFIX | 503 | printk(KERN_ERR PREFIX |
| 491 | "Bus %04x:%02x not present in PCI namespace\n", | 504 | "Bus %04x:%02x not present in PCI namespace\n", |
| 492 | root->segment, root->bus_nr); | 505 | root->segment, (unsigned int)root->secondary.start); |
| 493 | result = -ENODEV; | 506 | result = -ENODEV; |
| 494 | goto end; | 507 | goto end; |
| 495 | } | 508 | } |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7bf83ddf82e0..baacd98e7cc6 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -373,7 +373,7 @@ struct acpi_pci_root { | |||
| 373 | struct acpi_pci_id id; | 373 | struct acpi_pci_id id; |
| 374 | struct pci_bus *bus; | 374 | struct pci_bus *bus; |
| 375 | u16 segment; | 375 | u16 segment; |
| 376 | u8 bus_nr; | 376 | struct resource secondary; /* downstream bus range */ |
| 377 | 377 | ||
| 378 | u32 osc_support_set; /* _OSC state of support bits */ | 378 | u32 osc_support_set; /* _OSC state of support bits */ |
| 379 | u32 osc_control_set; /* _OSC state of control bits */ | 379 | u32 osc_control_set; /* _OSC state of control bits */ |
