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 */ |