aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-11-24 18:10:44 -0500
committerLen Brown <len.brown@intel.com>2011-01-12 04:48:45 -0500
commitbf325f9538d8c89312be305b9779edbcb436af00 (patch)
treefee681d8bf0c0058450b34a325bb60c5f02994aa
parent97d9a9e9f5ee68f20005ca5aa77c6b684e7cace8 (diff)
ACPI / PM: Register power resource devices as soon as they are needed
Depending on the organization of the ACPI namespace, power resource device objects may generally be scanned after the "regular" device objects that they are referred from through _PRn. This, in turn, may cause acpi_bus_get_power_flags() to attempt to access them through acpi_bus_init_power() before they are registered (and initialized by acpi_power_driver). [This is not a theoretical issue, it actually happens for one PnP device on my testbed HP nx6325.] To fix this problem, make acpi_bus_get_power_flags() attempt to register power resource devices as soon as they have been found in the _PRn output for any other devices. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/scan.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 2951a27303cb..cb7956c23ca4 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -847,6 +847,8 @@ end:
847 return 0; 847 return 0;
848} 848}
849 849
850static void acpi_bus_add_power_resource(acpi_handle handle);
851
850static int acpi_bus_get_power_flags(struct acpi_device *device) 852static int acpi_bus_get_power_flags(struct acpi_device *device)
851{ 853{
852 acpi_status status = 0; 854 acpi_status status = 0;
@@ -875,8 +877,12 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
875 acpi_evaluate_reference(device->handle, object_name, NULL, 877 acpi_evaluate_reference(device->handle, object_name, NULL,
876 &ps->resources); 878 &ps->resources);
877 if (ps->resources.count) { 879 if (ps->resources.count) {
880 int j;
881
878 device->power.flags.power_resources = 1; 882 device->power.flags.power_resources = 1;
879 ps->flags.valid = 1; 883 ps->flags.valid = 1;
884 for (j = 0; j < ps->resources.count; j++)
885 acpi_bus_add_power_resource(ps->resources.handles[j]);
880 } 886 }
881 887
882 /* Evaluate "_PSx" to see if we can do explicit sets */ 888 /* Evaluate "_PSx" to see if we can do explicit sets */
@@ -1323,6 +1329,20 @@ end:
1323#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \ 1329#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
1324 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING) 1330 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
1325 1331
1332static void acpi_bus_add_power_resource(acpi_handle handle)
1333{
1334 struct acpi_bus_ops ops = {
1335 .acpi_op_add = 1,
1336 .acpi_op_start = 1,
1337 };
1338 struct acpi_device *device = NULL;
1339
1340 acpi_bus_get_device(handle, &device);
1341 if (!device)
1342 acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
1343 ACPI_STA_DEFAULT, &ops);
1344}
1345
1326static int acpi_bus_type_and_status(acpi_handle handle, int *type, 1346static int acpi_bus_type_and_status(acpi_handle handle, int *type,
1327 unsigned long long *sta) 1347 unsigned long long *sta)
1328{ 1348{