diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-17 08:11:05 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-17 08:11:05 -0500 |
commit | d43e167db44b37bb284dc72fff2c3b61bb155752 (patch) | |
tree | 7ae48a798412e10a9531932080489e2a57836989 | |
parent | bc9b6407bd6df3ab7189e5622816bbc11ae9d2d8 (diff) |
ACPI / scan: More straightforward preparation of ACPI device objects
Simplify the code preparing struct acpi_device objects for
registration by removing useless code, moving different pieces of
code into the functions they belong to and making a couple of int
functions always returning 0 void.
This also fixes a possible memory leak in ACPI device registration
error code path by making acpi_device_register() detach data from
device->handle if device_register() fails and prepares the scanning
code for special-casing ACPI power resources (next patch).
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/scan.c | 178 |
1 files changed, 61 insertions, 117 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c6d60910e8a8..02629a810c04 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -472,6 +472,7 @@ static void acpi_free_ids(struct acpi_device *device) | |||
472 | kfree(id->id); | 472 | kfree(id->id); |
473 | kfree(id); | 473 | kfree(id); |
474 | } | 474 | } |
475 | kfree(device->pnp.unique_id); | ||
475 | } | 476 | } |
476 | 477 | ||
477 | static void acpi_device_release(struct device *dev) | 478 | static void acpi_device_release(struct device *dev) |
@@ -479,7 +480,6 @@ static void acpi_device_release(struct device *dev) | |||
479 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 480 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
480 | 481 | ||
481 | acpi_free_ids(acpi_dev); | 482 | acpi_free_ids(acpi_dev); |
482 | kfree(acpi_dev->pnp.unique_id); | ||
483 | kfree(acpi_dev); | 483 | kfree(acpi_dev); |
484 | } | 484 | } |
485 | 485 | ||
@@ -623,6 +623,18 @@ static int acpi_device_register(struct acpi_device *device) | |||
623 | struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; | 623 | struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; |
624 | int found = 0; | 624 | int found = 0; |
625 | 625 | ||
626 | if (device->handle) { | ||
627 | acpi_status status; | ||
628 | |||
629 | status = acpi_attach_data(device->handle, acpi_bus_data_handler, | ||
630 | device); | ||
631 | if (ACPI_FAILURE(status)) { | ||
632 | acpi_handle_err(device->handle, | ||
633 | "Unable to attach device data\n"); | ||
634 | return -ENODEV; | ||
635 | } | ||
636 | } | ||
637 | |||
626 | /* | 638 | /* |
627 | * Linkage | 639 | * Linkage |
628 | * ------- | 640 | * ------- |
@@ -637,8 +649,9 @@ static int acpi_device_register(struct acpi_device *device) | |||
637 | 649 | ||
638 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); | 650 | new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); |
639 | if (!new_bus_id) { | 651 | if (!new_bus_id) { |
640 | printk(KERN_ERR PREFIX "Memory allocation error\n"); | 652 | pr_err(PREFIX "Memory allocation error\n"); |
641 | return -ENOMEM; | 653 | result = -ENOMEM; |
654 | goto err_detach; | ||
642 | } | 655 | } |
643 | 656 | ||
644 | mutex_lock(&acpi_device_lock); | 657 | mutex_lock(&acpi_device_lock); |
@@ -677,7 +690,7 @@ static int acpi_device_register(struct acpi_device *device) | |||
677 | result = device_register(&device->dev); | 690 | result = device_register(&device->dev); |
678 | if (result) { | 691 | if (result) { |
679 | dev_err(&device->dev, "Error registering device\n"); | 692 | dev_err(&device->dev, "Error registering device\n"); |
680 | goto end; | 693 | goto err; |
681 | } | 694 | } |
682 | 695 | ||
683 | result = acpi_device_setup_files(device); | 696 | result = acpi_device_setup_files(device); |
@@ -687,12 +700,16 @@ static int acpi_device_register(struct acpi_device *device) | |||
687 | 700 | ||
688 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; | 701 | device->removal_type = ACPI_BUS_REMOVAL_NORMAL; |
689 | return 0; | 702 | return 0; |
690 | end: | 703 | |
704 | err: | ||
691 | mutex_lock(&acpi_device_lock); | 705 | mutex_lock(&acpi_device_lock); |
692 | if (device->parent) | 706 | if (device->parent) |
693 | list_del(&device->node); | 707 | list_del(&device->node); |
694 | list_del(&device->wakeup_list); | 708 | list_del(&device->wakeup_list); |
695 | mutex_unlock(&acpi_device_lock); | 709 | mutex_unlock(&acpi_device_lock); |
710 | |||
711 | err_detach: | ||
712 | acpi_detach_data(device->handle, acpi_bus_data_handler); | ||
696 | return result; | 713 | return result; |
697 | } | 714 | } |
698 | 715 | ||
@@ -857,12 +874,6 @@ void acpi_bus_data_handler(acpi_handle handle, void *context) | |||
857 | return; | 874 | return; |
858 | } | 875 | } |
859 | 876 | ||
860 | static int acpi_bus_get_perf_flags(struct acpi_device *device) | ||
861 | { | ||
862 | device->performance.state = ACPI_STATE_UNKNOWN; | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static acpi_status | 877 | static acpi_status |
867 | acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, | 878 | acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, |
868 | struct acpi_device_wakeup *wakeup) | 879 | struct acpi_device_wakeup *wakeup) |
@@ -1013,12 +1024,25 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
1013 | 1024 | ||
1014 | static void acpi_bus_add_power_resource(acpi_handle handle); | 1025 | static void acpi_bus_add_power_resource(acpi_handle handle); |
1015 | 1026 | ||
1016 | static int acpi_bus_get_power_flags(struct acpi_device *device) | 1027 | static void acpi_bus_get_power_flags(struct acpi_device *device) |
1017 | { | 1028 | { |
1018 | acpi_status status = 0; | 1029 | acpi_status status = 0; |
1019 | acpi_handle handle = NULL; | 1030 | acpi_handle handle = NULL; |
1020 | u32 i = 0; | 1031 | u32 i = 0; |
1021 | 1032 | ||
1033 | /* Power resources cannot be power manageable. */ | ||
1034 | if (device->device_type == ACPI_BUS_TYPE_POWER) | ||
1035 | return; | ||
1036 | |||
1037 | /* Presence of _PS0|_PR0 indicates 'power manageable' */ | ||
1038 | status = acpi_get_handle(device->handle, "_PS0", &handle); | ||
1039 | if (ACPI_FAILURE(status)) { | ||
1040 | status = acpi_get_handle(device->handle, "_PR0", &handle); | ||
1041 | if (ACPI_FAILURE(status)) | ||
1042 | return; | ||
1043 | } | ||
1044 | |||
1045 | device->flags.power_manageable = 1; | ||
1022 | 1046 | ||
1023 | /* | 1047 | /* |
1024 | * Power Management Flags | 1048 | * Power Management Flags |
@@ -1084,16 +1108,13 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
1084 | device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1; | 1108 | device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1; |
1085 | 1109 | ||
1086 | acpi_bus_init_power(device); | 1110 | acpi_bus_init_power(device); |
1087 | |||
1088 | return 0; | ||
1089 | } | 1111 | } |
1090 | 1112 | ||
1091 | static int acpi_bus_get_flags(struct acpi_device *device) | 1113 | static void acpi_bus_get_flags(struct acpi_device *device) |
1092 | { | 1114 | { |
1093 | acpi_status status = AE_OK; | 1115 | acpi_status status = AE_OK; |
1094 | acpi_handle temp = NULL; | 1116 | acpi_handle temp = NULL; |
1095 | 1117 | ||
1096 | |||
1097 | /* Presence of _STA indicates 'dynamic_status' */ | 1118 | /* Presence of _STA indicates 'dynamic_status' */ |
1098 | status = acpi_get_handle(device->handle, "_STA", &temp); | 1119 | status = acpi_get_handle(device->handle, "_STA", &temp); |
1099 | if (ACPI_SUCCESS(status)) | 1120 | if (ACPI_SUCCESS(status)) |
@@ -1113,21 +1134,6 @@ static int acpi_bus_get_flags(struct acpi_device *device) | |||
1113 | if (ACPI_SUCCESS(status)) | 1134 | if (ACPI_SUCCESS(status)) |
1114 | device->flags.ejectable = 1; | 1135 | device->flags.ejectable = 1; |
1115 | } | 1136 | } |
1116 | |||
1117 | /* Power resources cannot be power manageable. */ | ||
1118 | if (device->device_type == ACPI_BUS_TYPE_POWER) | ||
1119 | return 0; | ||
1120 | |||
1121 | /* Presence of _PS0|_PR0 indicates 'power manageable' */ | ||
1122 | status = acpi_get_handle(device->handle, "_PS0", &temp); | ||
1123 | if (ACPI_FAILURE(status)) | ||
1124 | status = acpi_get_handle(device->handle, "_PR0", &temp); | ||
1125 | if (ACPI_SUCCESS(status)) | ||
1126 | device->flags.power_manageable = 1; | ||
1127 | |||
1128 | /* TBD: Performance management */ | ||
1129 | |||
1130 | return 0; | ||
1131 | } | 1137 | } |
1132 | 1138 | ||
1133 | static void acpi_device_get_busid(struct acpi_device *device) | 1139 | static void acpi_device_get_busid(struct acpi_device *device) |
@@ -1352,27 +1358,18 @@ static void acpi_device_set_id(struct acpi_device *device) | |||
1352 | } | 1358 | } |
1353 | } | 1359 | } |
1354 | 1360 | ||
1355 | static int acpi_device_set_context(struct acpi_device *device) | 1361 | static void acpi_init_device_object(struct acpi_device *device, |
1362 | acpi_handle handle, | ||
1363 | int type, unsigned long long sta) | ||
1356 | { | 1364 | { |
1357 | acpi_status status; | 1365 | INIT_LIST_HEAD(&device->pnp.ids); |
1358 | 1366 | device->device_type = type; | |
1359 | /* | 1367 | device->handle = handle; |
1360 | * Context | 1368 | device->parent = acpi_bus_get_parent(handle); |
1361 | * ------- | 1369 | STRUCT_TO_INT(device->status) = sta; |
1362 | * Attach this 'struct acpi_device' to the ACPI object. This makes | 1370 | acpi_device_get_busid(device); |
1363 | * resolutions from handle->device very efficient. Fixed hardware | 1371 | acpi_device_set_id(device); |
1364 | * devices have no handles, so we skip them. | 1372 | acpi_bus_get_flags(device); |
1365 | */ | ||
1366 | if (!device->handle) | ||
1367 | return 0; | ||
1368 | |||
1369 | status = acpi_attach_data(device->handle, | ||
1370 | acpi_bus_data_handler, device); | ||
1371 | if (ACPI_SUCCESS(status)) | ||
1372 | return 0; | ||
1373 | |||
1374 | printk(KERN_ERR PREFIX "Error attaching device data\n"); | ||
1375 | return -ENODEV; | ||
1376 | } | 1373 | } |
1377 | 1374 | ||
1378 | static int acpi_add_single_object(struct acpi_device **child, | 1375 | static int acpi_add_single_object(struct acpi_device **child, |
@@ -1389,78 +1386,25 @@ static int acpi_add_single_object(struct acpi_device **child, | |||
1389 | return -ENOMEM; | 1386 | return -ENOMEM; |
1390 | } | 1387 | } |
1391 | 1388 | ||
1392 | INIT_LIST_HEAD(&device->pnp.ids); | 1389 | acpi_init_device_object(device, handle, type, sta); |
1393 | device->device_type = type; | 1390 | acpi_bus_get_power_flags(device); |
1394 | device->handle = handle; | ||
1395 | device->parent = acpi_bus_get_parent(handle); | ||
1396 | STRUCT_TO_INT(device->status) = sta; | ||
1397 | |||
1398 | acpi_device_get_busid(device); | ||
1399 | |||
1400 | /* | ||
1401 | * Flags | ||
1402 | * ----- | ||
1403 | * Note that we only look for object handles -- cannot evaluate objects | ||
1404 | * until we know the device is present and properly initialized. | ||
1405 | */ | ||
1406 | result = acpi_bus_get_flags(device); | ||
1407 | if (result) | ||
1408 | goto end; | ||
1409 | |||
1410 | /* | ||
1411 | * Initialize Device | ||
1412 | * ----------------- | ||
1413 | * TBD: Synch with Core's enumeration/initialization process. | ||
1414 | */ | ||
1415 | acpi_device_set_id(device); | ||
1416 | |||
1417 | /* | ||
1418 | * Power Management | ||
1419 | * ---------------- | ||
1420 | */ | ||
1421 | if (device->flags.power_manageable) { | ||
1422 | result = acpi_bus_get_power_flags(device); | ||
1423 | if (result) | ||
1424 | goto end; | ||
1425 | } | ||
1426 | |||
1427 | /* | ||
1428 | * Wakeup device management | ||
1429 | *----------------------- | ||
1430 | */ | ||
1431 | acpi_bus_get_wakeup_device_flags(device); | 1391 | acpi_bus_get_wakeup_device_flags(device); |
1432 | 1392 | ||
1433 | /* | ||
1434 | * Performance Management | ||
1435 | * ---------------------- | ||
1436 | */ | ||
1437 | if (device->flags.performance_manageable) { | ||
1438 | result = acpi_bus_get_perf_flags(device); | ||
1439 | if (result) | ||
1440 | goto end; | ||
1441 | } | ||
1442 | |||
1443 | if ((result = acpi_device_set_context(device))) | ||
1444 | goto end; | ||
1445 | |||
1446 | device->flags.match_driver = match_driver; | 1393 | device->flags.match_driver = match_driver; |
1447 | result = acpi_device_register(device); | 1394 | result = acpi_device_register(device); |
1448 | 1395 | if (result) { | |
1449 | end: | ||
1450 | if (!result) { | ||
1451 | acpi_power_add_remove_device(device, true); | ||
1452 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
1453 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
1454 | "Adding %s [%s] parent %s\n", dev_name(&device->dev), | ||
1455 | (char *) buffer.pointer, | ||
1456 | device->parent ? dev_name(&device->parent->dev) : | ||
1457 | "(null)")); | ||
1458 | kfree(buffer.pointer); | ||
1459 | *child = device; | ||
1460 | } else | ||
1461 | acpi_device_release(&device->dev); | 1396 | acpi_device_release(&device->dev); |
1397 | return result; | ||
1398 | } | ||
1462 | 1399 | ||
1463 | return result; | 1400 | acpi_power_add_remove_device(device, true); |
1401 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
1402 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Added %s [%s] parent %s\n", | ||
1403 | dev_name(&device->dev), (char *) buffer.pointer, | ||
1404 | device->parent ? dev_name(&device->parent->dev) : "(null)")); | ||
1405 | kfree(buffer.pointer); | ||
1406 | *child = device; | ||
1407 | return 0; | ||
1464 | } | 1408 | } |
1465 | 1409 | ||
1466 | #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ | 1410 | #define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ |