aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-25 15:51:57 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-25 15:51:57 -0500
commit660b1113e0f33a476952cb2cbcb5c9831e7ff4cd (patch)
treede08984b801858b0be37a34cdc8493a896f39742 /drivers/acpi/power.c
parent18a387099b3e3fd901cc706f708b163aa45347b6 (diff)
ACPI / PM: Fix consistency check for power resources during resume
During system resume we check if there are power resources that have been turned off by the BIOS, but our reference counters for them are nonzero (they need to be turned on then). It turns out, however, that we also need to check the opposite, i.e. if there are power resources that have been turned on by the BIOS, but our reference counters for them are zero (which means that no devices are going to need them any time soon) and we should turn them off. Make the power resources resume code do the additional check and turn off the unused power resources as appropriate. This change has been tested on HP nx6325. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 9466f56b938f..b820528a5fa3 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -299,9 +299,22 @@ static int acpi_power_on(struct acpi_power_resource *resource)
299 return result; 299 return result;
300} 300}
301 301
302static int __acpi_power_off(struct acpi_power_resource *resource)
303{
304 acpi_status status;
305
306 status = acpi_evaluate_object(resource->device.handle, "_OFF",
307 NULL, NULL);
308 if (ACPI_FAILURE(status))
309 return -ENODEV;
310
311 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned off\n",
312 resource->name));
313 return 0;
314}
315
302static int acpi_power_off(struct acpi_power_resource *resource) 316static int acpi_power_off(struct acpi_power_resource *resource)
303{ 317{
304 acpi_status status = AE_OK;
305 int result = 0; 318 int result = 0;
306 319
307 mutex_lock(&resource->resource_lock); 320 mutex_lock(&resource->resource_lock);
@@ -317,17 +330,12 @@ static int acpi_power_off(struct acpi_power_resource *resource)
317 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 330 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
318 "Power resource [%s] still in use\n", 331 "Power resource [%s] still in use\n",
319 resource->name)); 332 resource->name));
320 goto unlock; 333 } else {
334 result = __acpi_power_off(resource);
335 if (result)
336 resource->ref_count++;
321 } 337 }
322 338
323 status = acpi_evaluate_object(resource->device.handle, "_OFF", NULL, NULL);
324 if (ACPI_FAILURE(status))
325 result = -ENODEV;
326 else
327 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
328 "Power resource [%s] turned off\n",
329 resource->name));
330
331 unlock: 339 unlock:
332 mutex_unlock(&resource->resource_lock); 340 mutex_unlock(&resource->resource_lock);
333 341
@@ -851,10 +859,17 @@ void acpi_resume_power_resources(void)
851 mutex_lock(&resource->resource_lock); 859 mutex_lock(&resource->resource_lock);
852 860
853 result = acpi_power_get_state(resource->device.handle, &state); 861 result = acpi_power_get_state(resource->device.handle, &state);
854 if (!result && state == ACPI_POWER_RESOURCE_STATE_OFF 862 if (result)
863 continue;
864
865 if (state == ACPI_POWER_RESOURCE_STATE_OFF
855 && resource->ref_count) { 866 && resource->ref_count) {
856 dev_info(&resource->device.dev, "Turning ON\n"); 867 dev_info(&resource->device.dev, "Turning ON\n");
857 __acpi_power_on(resource); 868 __acpi_power_on(resource);
869 } else if (state == ACPI_POWER_RESOURCE_STATE_ON
870 && !resource->ref_count) {
871 dev_info(&resource->device.dev, "Turning OFF\n");
872 __acpi_power_off(resource);
858 } 873 }
859 874
860 mutex_unlock(&resource->resource_lock); 875 mutex_unlock(&resource->resource_lock);