aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:05 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:05 -0500
commit82c7d5efaadf99fb4a26500cd5b59b6fd7659772 (patch)
treebdd905dde94786f58852dcd1aba86d28054257dd /drivers/acpi/scan.c
parentd43e167db44b37bb284dc72fff2c3b61bb155752 (diff)
ACPI / scan: Treat power resources in a special way
ACPI power resources need to be treated in a special way by the namespace scanning code, because they need to be ready to use as soon as they have been discovered (even before registering ACPI device nodes using them for power management). For this reason, it doesn't make sense to separate the preparation of struct acpi_device objects representing them in the device hierarchy from the creation of struct acpi_power_resource objects actually used for power resource manipulation. Accordingly, it doesn't make sense to define non-empty .add() and .remove() callbacks in the power resources "driver" (in fact, it is questionable whether or not it is useful to register such a "driver" at all). Rearrange the code in scan.c and power.c so that power resources are initialized entirely by one routine, acpi_add_power_resource(), that also prepares their struct acpi_device objects and registers them with the driver core, telling it to use a special release routine, acpi_release_power_resource(), for removing objects that represent power resources from memory. Make the ACPI namespace scanning code in scan.c always use acpi_add_power_resource() for preparing and registering objects that represent power resources. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c47
1 files changed, 17 insertions, 30 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 02629a810c04..952b08af91de 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -464,7 +464,7 @@ int acpi_match_device_ids(struct acpi_device *device,
464} 464}
465EXPORT_SYMBOL(acpi_match_device_ids); 465EXPORT_SYMBOL(acpi_match_device_ids);
466 466
467static void acpi_free_ids(struct acpi_device *device) 467void acpi_free_ids(struct acpi_device *device)
468{ 468{
469 struct acpi_hardware_id *id, *tmp; 469 struct acpi_hardware_id *id, *tmp;
470 470
@@ -617,7 +617,8 @@ struct bus_type acpi_bus_type = {
617 .uevent = acpi_device_uevent, 617 .uevent = acpi_device_uevent,
618}; 618};
619 619
620static int acpi_device_register(struct acpi_device *device) 620int acpi_device_register(struct acpi_device *device,
621 void (*release)(struct device *))
621{ 622{
622 int result; 623 int result;
623 struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; 624 struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
@@ -686,7 +687,7 @@ static int acpi_device_register(struct acpi_device *device)
686 if (device->parent) 687 if (device->parent)
687 device->dev.parent = &device->parent->dev; 688 device->dev.parent = &device->parent->dev;
688 device->dev.bus = &acpi_bus_type; 689 device->dev.bus = &acpi_bus_type;
689 device->dev.release = &acpi_device_release; 690 device->dev.release = release;
690 result = device_register(&device->dev); 691 result = device_register(&device->dev);
691 if (result) { 692 if (result) {
692 dev_err(&device->dev, "Error registering device\n"); 693 dev_err(&device->dev, "Error registering device\n");
@@ -1022,18 +1023,12 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
1022 "error in _DSW or _PSW evaluation\n")); 1023 "error in _DSW or _PSW evaluation\n"));
1023} 1024}
1024 1025
1025static void acpi_bus_add_power_resource(acpi_handle handle);
1026
1027static void acpi_bus_get_power_flags(struct acpi_device *device) 1026static void acpi_bus_get_power_flags(struct acpi_device *device)
1028{ 1027{
1029 acpi_status status = 0; 1028 acpi_status status = 0;
1030 acpi_handle handle = NULL; 1029 acpi_handle handle = NULL;
1031 u32 i = 0; 1030 u32 i = 0;
1032 1031
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' */ 1032 /* Presence of _PS0|_PR0 indicates 'power manageable' */
1038 status = acpi_get_handle(device->handle, "_PS0", &handle); 1033 status = acpi_get_handle(device->handle, "_PS0", &handle);
1039 if (ACPI_FAILURE(status)) { 1034 if (ACPI_FAILURE(status)) {
@@ -1068,8 +1063,10 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
1068 int j; 1063 int j;
1069 1064
1070 device->power.flags.power_resources = 1; 1065 device->power.flags.power_resources = 1;
1071 for (j = 0; j < ps->resources.count; j++) 1066 for (j = 0; j < ps->resources.count; j++) {
1072 acpi_bus_add_power_resource(ps->resources.handles[j]); 1067 acpi_handle rhandle = ps->resources.handles[j];
1068 acpi_add_power_resource(rhandle);
1069 }
1073 } 1070 }
1074 1071
1075 /* Evaluate "_PSx" to see if we can do explicit sets */ 1072 /* Evaluate "_PSx" to see if we can do explicit sets */
@@ -1358,9 +1355,8 @@ static void acpi_device_set_id(struct acpi_device *device)
1358 } 1355 }
1359} 1356}
1360 1357
1361static void acpi_init_device_object(struct acpi_device *device, 1358void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
1362 acpi_handle handle, 1359 int type, unsigned long long sta)
1363 int type, unsigned long long sta)
1364{ 1360{
1365 INIT_LIST_HEAD(&device->pnp.ids); 1361 INIT_LIST_HEAD(&device->pnp.ids);
1366 device->device_type = type; 1362 device->device_type = type;
@@ -1391,7 +1387,7 @@ static int acpi_add_single_object(struct acpi_device **child,
1391 acpi_bus_get_wakeup_device_flags(device); 1387 acpi_bus_get_wakeup_device_flags(device);
1392 1388
1393 device->flags.match_driver = match_driver; 1389 device->flags.match_driver = match_driver;
1394 result = acpi_device_register(device); 1390 result = acpi_device_register(device, acpi_device_release);
1395 if (result) { 1391 if (result) {
1396 acpi_device_release(&device->dev); 1392 acpi_device_release(&device->dev);
1397 return result; 1393 return result;
@@ -1407,19 +1403,6 @@ static int acpi_add_single_object(struct acpi_device **child,
1407 return 0; 1403 return 0;
1408} 1404}
1409 1405
1410#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
1411 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
1412
1413static void acpi_bus_add_power_resource(acpi_handle handle)
1414{
1415 struct acpi_device *device = NULL;
1416
1417 acpi_bus_get_device(handle, &device);
1418 if (!device)
1419 acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
1420 ACPI_STA_DEFAULT, true);
1421}
1422
1423static int acpi_bus_type_and_status(acpi_handle handle, int *type, 1406static int acpi_bus_type_and_status(acpi_handle handle, int *type,
1424 unsigned long long *sta) 1407 unsigned long long *sta)
1425{ 1408{
@@ -1476,6 +1459,11 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
1476 if (result) 1459 if (result)
1477 return AE_OK; 1460 return AE_OK;
1478 1461
1462 if (type == ACPI_BUS_TYPE_POWER) {
1463 acpi_add_power_resource(handle);
1464 return AE_OK;
1465 }
1466
1479 if (!(sta & ACPI_STA_DEVICE_PRESENT) && 1467 if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
1480 !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { 1468 !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
1481 struct acpi_device_wakeup wakeup; 1469 struct acpi_device_wakeup wakeup;
@@ -1488,8 +1476,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
1488 return AE_CTRL_DEPTH; 1476 return AE_CTRL_DEPTH;
1489 } 1477 }
1490 1478
1491 acpi_add_single_object(&device, handle, type, sta, 1479 acpi_add_single_object(&device, handle, type, sta, false);
1492 type == ACPI_BUS_TYPE_POWER);
1493 if (!device) 1480 if (!device)
1494 return AE_CTRL_DEPTH; 1481 return AE_CTRL_DEPTH;
1495 1482