aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/pci_root.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-28 17:42:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-28 17:42:18 -0400
commit9a90e09854a3c7cc603ab8fc9163f77bb1f66cfa (patch)
treec8c5f767dd2351c9db440f003cc14401583bafd3 /drivers/acpi/pci_root.c
parentd372e7fe4698bde3a00b718f7901a0025dda47ef (diff)
parentd3b383338f105f50724c10a7d81b04a3930e886b (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (27 commits) ACPI: Don't let acpi_pad needlessly mark TSC unstable drivers/acpi/sleep.h: Checkpatch cleanup ACPI: Minor cleanup eliminating redundant PMTIMER_TICKS to NS conversion ACPI: delete unused c-state promotion/demotion data strucutures ACPI: video: fix acpi_backlight=video ACPI: EC: Use kmemdup drivers/acpi: use kasprintf ACPI, APEI, EINJ injection parameters support Add x64 support to debugfs ACPI, APEI, Use ERST for persistent storage of MCE ACPI, APEI, Error Record Serialization Table (ERST) support ACPI, APEI, Generic Hardware Error Source memory error support ACPI, APEI, UEFI Common Platform Error Record (CPER) header Unified UUID/GUID definition ACPI Hardware Error Device (PNP0C33) support ACPI, APEI, PCIE AER, use general HEST table parsing in AER firmware_first setup ACPI, APEI, Document for APEI ACPI, APEI, EINJ support ACPI, APEI, HEST table parsing ACPI, APEI, APEI supporting infrastructure ...
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 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);
154static acpi_status 155static acpi_status
155get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) 156get_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
173static acpi_status try_get_root_bridge_busnr(acpi_handle handle, 176static 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 }