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 /drivers/acpi | |
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>
Diffstat (limited to 'drivers/acpi')
-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 | ||