diff options
| author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-06-18 16:46:52 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2009-06-20 00:01:52 -0400 |
| commit | f5eebbe119a861b5e4f5c67c886eab0937c686ed (patch) | |
| tree | 9aa3e915a50d5d8155a21c76c447afa9911ed072 | |
| parent | fbe2b31b4b6dfa790cbc88e00631f3112c4fc54e (diff) | |
ACPI: pci_root: simplify acpi_pci_root_add() control flow
By looking up the segment & bus number earlier, we don't have to
worry about cleaning up if it fails.
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | drivers/acpi/pci_root.c | 100 |
1 files changed, 38 insertions, 62 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index a8b250783937..0d69c0348c58 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -161,19 +161,22 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | |||
| 161 | return AE_OK; | 161 | return AE_OK; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, int *busnum) | 164 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, |
| 165 | unsigned long long *bus) | ||
| 165 | { | 166 | { |
| 166 | acpi_status status; | 167 | acpi_status status; |
| 168 | int busnum; | ||
| 167 | 169 | ||
| 168 | *busnum = -1; | 170 | busnum = -1; |
| 169 | status = | 171 | status = |
| 170 | acpi_walk_resources(handle, METHOD_NAME__CRS, | 172 | acpi_walk_resources(handle, METHOD_NAME__CRS, |
| 171 | get_root_bridge_busnr_callback, busnum); | 173 | get_root_bridge_busnr_callback, &busnum); |
| 172 | if (ACPI_FAILURE(status)) | 174 | if (ACPI_FAILURE(status)) |
| 173 | return status; | 175 | return status; |
| 174 | /* Check if we really get a bus number from _CRS */ | 176 | /* Check if we really get a bus number from _CRS */ |
| 175 | if (*busnum == -1) | 177 | if (busnum == -1) |
| 176 | return AE_ERROR; | 178 | return AE_ERROR; |
| 179 | *bus = busnum; | ||
| 177 | return AE_OK; | 180 | return AE_OK; |
| 178 | } | 181 | } |
| 179 | 182 | ||
| @@ -363,24 +366,39 @@ EXPORT_SYMBOL(acpi_pci_osc_control_set); | |||
| 363 | 366 | ||
| 364 | static int __devinit acpi_pci_root_add(struct acpi_device *device) | 367 | static int __devinit acpi_pci_root_add(struct acpi_device *device) |
| 365 | { | 368 | { |
| 366 | int result = 0; | 369 | unsigned long long segment, bus; |
| 367 | struct acpi_pci_root *root = NULL; | 370 | acpi_status status; |
| 368 | acpi_status status = AE_OK; | 371 | int result; |
| 369 | unsigned long long value = 0; | 372 | struct acpi_pci_root *root; |
| 370 | acpi_handle handle = NULL; | 373 | acpi_handle handle; |
| 371 | struct acpi_device *child; | 374 | struct acpi_device *child; |
| 372 | u32 flags, base_flags; | 375 | u32 flags, base_flags; |
| 373 | int bus; | ||
| 374 | 376 | ||
| 377 | segment = 0; | ||
| 378 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, | ||
| 379 | &segment); | ||
| 380 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
| 381 | printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); | ||
| 382 | return -ENODEV; | ||
| 383 | } | ||
| 375 | 384 | ||
| 376 | if (!device) | 385 | /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ |
| 377 | return -EINVAL; | 386 | bus = 0; |
| 387 | status = try_get_root_bridge_busnr(device->handle, &bus); | ||
| 388 | if (ACPI_FAILURE(status)) { | ||
| 389 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); | ||
| 390 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
| 391 | printk(KERN_ERR PREFIX | ||
| 392 | "no bus number in _CRS and can't evaluate _BBN\n"); | ||
| 393 | return -ENODEV; | ||
| 394 | } | ||
| 395 | } | ||
| 378 | 396 | ||
| 379 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | 397 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); |
| 380 | if (!root) | 398 | if (!root) |
| 381 | return -ENOMEM; | 399 | return -ENOMEM; |
| 382 | INIT_LIST_HEAD(&root->node); | ||
| 383 | 400 | ||
| 401 | INIT_LIST_HEAD(&root->node); | ||
| 384 | root->device = device; | 402 | root->device = device; |
| 385 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); | 403 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); |
| 386 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); | 404 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); |
| @@ -395,54 +413,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 395 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; | 413 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; |
| 396 | acpi_pci_osc_support(root, flags); | 414 | acpi_pci_osc_support(root, flags); |
| 397 | 415 | ||
| 398 | /* | ||
| 399 | * Segment | ||
| 400 | * ------- | ||
| 401 | * Obtained via _SEG, if exists, otherwise assumed to be zero (0). | ||
| 402 | */ | ||
| 403 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, | ||
| 404 | &value); | ||
| 405 | switch (status) { | ||
| 406 | case AE_OK: | ||
| 407 | root->id.segment = (u16) value; | ||
| 408 | break; | ||
| 409 | case AE_NOT_FOUND: | ||
| 410 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 411 | "Assuming segment 0 (no _SEG)\n")); | ||
| 412 | root->id.segment = 0; | ||
| 413 | break; | ||
| 414 | default: | ||
| 415 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SEG")); | ||
| 416 | result = -ENODEV; | ||
| 417 | goto end; | ||
| 418 | } | ||
| 419 | |||
| 420 | /* | ||
| 421 | * Bus | ||
| 422 | * --- | ||
| 423 | * Check _CRS first, then _BBN. If no _BBN, default to zero. | ||
| 424 | */ | ||
| 425 | status = try_get_root_bridge_busnr(device->handle, &bus); | ||
| 426 | if (ACPI_SUCCESS(status)) | ||
| 427 | root->id.bus = bus; | ||
| 428 | else { | ||
| 429 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &value); | ||
| 430 | if (ACPI_SUCCESS(status)) | ||
| 431 | root->id.bus = (u16) value; | ||
| 432 | else if (status == AE_NOT_FOUND) | ||
| 433 | root->id.bus = 0; | ||
| 434 | else { | ||
| 435 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BBN")); | ||
| 436 | result = -ENODEV; | ||
| 437 | goto end; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 441 | /* | 416 | /* |
| 442 | * Device & Function | 417 | * Device & Function |
| 443 | * ----------------- | 418 | * ----------------- |
| 444 | * Obtained from _ADR (which has already been evaluated for us). | 419 | * Obtained from _ADR (which has already been evaluated for us). |
| 445 | */ | 420 | */ |
| 421 | root->id.segment = segment & 0xFFFF; | ||
| 422 | root->id.bus = bus & 0xFF; | ||
| 446 | root->id.device = device->pnp.bus_address >> 16; | 423 | root->id.device = device->pnp.bus_address >> 16; |
| 447 | root->id.function = device->pnp.bus_address & 0xFFFF; | 424 | root->id.function = device->pnp.bus_address & 0xFFFF; |
| 448 | 425 | ||
| @@ -509,13 +486,12 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 509 | if (flags != base_flags) | 486 | if (flags != base_flags) |
| 510 | acpi_pci_osc_support(root, flags); | 487 | acpi_pci_osc_support(root, flags); |
| 511 | 488 | ||
| 512 | end: | 489 | return 0; |
| 513 | if (result) { | ||
| 514 | if (!list_empty(&root->node)) | ||
| 515 | list_del(&root->node); | ||
| 516 | kfree(root); | ||
| 517 | } | ||
| 518 | 490 | ||
| 491 | end: | ||
| 492 | if (!list_empty(&root->node)) | ||
| 493 | list_del(&root->node); | ||
| 494 | kfree(root); | ||
| 519 | return result; | 495 | return result; |
| 520 | } | 496 | } |
| 521 | 497 | ||
