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