aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/pci_root.c67
-rw-r--r--include/acpi/acpi_bus.h2
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);
153static acpi_status 154static acpi_status
154get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) 155get_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
172static acpi_status try_get_root_bridge_busnr(acpi_handle handle, 175static 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 */