aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/pci_root.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2010-03-11 14:20:06 -0500
committerLen Brown <len.brown@intel.com>2010-04-04 00:29:41 -0400
commit6ad95513d60096b569e4e4bd721420f03b57e4d4 (patch)
tree1029d5804adc51eb3f5c0aed56ef0fd00ae2042f /drivers/acpi/pci_root.c
parent2eaa9cfdf33b8d7fb7aff27792192e0019ae8fc6 (diff)
ACPI: pci_root: save downstream bus range
Previously, we only saved the root bus number, i.e., the beginning of the downstream bus range. We now support IORESOURCE_BUS resources, so this patch uses that to keep track of both the beginning and the end of the downstream bus range. It's important to know both the beginning and the end for supporting _CBA (see PCI Firmware spec, rev 3.0, sec 4.1.3) and so we know the limits for any possible PCI bus renumbering (we can't renumber downstream buses to be outside the bus number range claimed by the host bridge). It's clear from the spec that the bus range is supposed to be in _CRS, but if we don't find it there, we'll assume [_BBN - 0xFF] or [0 - 0xFF]. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/pci_root.c')
-rw-r--r--drivers/acpi/pci_root.c67
1 files changed, 40 insertions, 27 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 }