aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/bus.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:08 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-17 08:11:08 -0500
commitff0c41942fd9766a158502d8ed6965c8a7726f53 (patch)
treef369c636a02581a2a02857744466fd70837d1531 /drivers/acpi/bus.c
parent0596a52b8357b25185e06af32973225baeb7196a (diff)
ACPI / PM: Change the way power transitions to D3cold are carried out
During power transitions into D3cold from any shallower power states we are supposed to transition the device into D3hot and remove power from it afterward, but the current code in acpi_device_set_power() doesn't work this way. At the same time, though, we need to be careful enough to preserve backwards compatibility for systems that don't distinguish between D3hot and D3cold (e.g. designed before ACPI 4). Modify acpi_device_set_power() so that it works in accordance with the expectations in both cases. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/bus.c')
-rw-r--r--drivers/acpi/bus.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 1f0d457ecbcf..8e57fc49726e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -270,6 +270,7 @@ int acpi_device_set_power(struct acpi_device *device, int state)
270 int result = 0; 270 int result = 0;
271 acpi_status status = AE_OK; 271 acpi_status status = AE_OK;
272 char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' }; 272 char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' };
273 bool cut_power = false;
273 274
274 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) 275 if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
275 return -EINVAL; 276 return -EINVAL;
@@ -294,9 +295,13 @@ int acpi_device_set_power(struct acpi_device *device, int state)
294 return -ENODEV; 295 return -ENODEV;
295 } 296 }
296 297
297 /* For D3cold we should execute _PS3, not _PS4. */ 298 /* For D3cold we should first transition into D3hot. */
298 if (state == ACPI_STATE_D3_COLD) 299 if (state == ACPI_STATE_D3_COLD
300 && device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible) {
301 state = ACPI_STATE_D3_HOT;
299 object_name[3] = '3'; 302 object_name[3] = '3';
303 cut_power = true;
304 }
300 305
301 /* 306 /*
302 * Transition Power 307 * Transition Power
@@ -341,6 +346,9 @@ int acpi_device_set_power(struct acpi_device *device, int state)
341 } 346 }
342 } 347 }
343 348
349 if (cut_power)
350 result = acpi_power_transition(device, ACPI_STATE_D3_COLD);
351
344 end: 352 end:
345 if (result) 353 if (result)
346 printk(KERN_WARNING PREFIX 354 printk(KERN_WARNING PREFIX