aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r--drivers/acpi/power.c87
1 files changed, 38 insertions, 49 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 56665a63bf19..22b297916519 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -43,6 +43,9 @@
43#include <linux/seq_file.h> 43#include <linux/seq_file.h>
44#include <acpi/acpi_bus.h> 44#include <acpi/acpi_bus.h>
45#include <acpi/acpi_drivers.h> 45#include <acpi/acpi_drivers.h>
46#include "sleep.h"
47
48#define PREFIX "ACPI: "
46 49
47#define _COMPONENT ACPI_POWER_COMPONENT 50#define _COMPONENT ACPI_POWER_COMPONENT
48ACPI_MODULE_NAME("power"); 51ACPI_MODULE_NAME("power");
@@ -194,7 +197,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
194 197
195static int acpi_power_on(acpi_handle handle, struct acpi_device *dev) 198static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
196{ 199{
197 int result = 0, state; 200 int result = 0;
198 int found = 0; 201 int found = 0;
199 acpi_status status = AE_OK; 202 acpi_status status = AE_OK;
200 struct acpi_power_resource *resource = NULL; 203 struct acpi_power_resource *resource = NULL;
@@ -236,18 +239,6 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
236 if (ACPI_FAILURE(status)) 239 if (ACPI_FAILURE(status))
237 return -ENODEV; 240 return -ENODEV;
238 241
239 if (!acpi_power_nocheck) {
240 /*
241 * If acpi_power_nocheck is set, it is unnecessary to check
242 * the power state after power transition.
243 */
244 result = acpi_power_get_state(resource->device->handle,
245 &state);
246 if (result)
247 return result;
248 if (state != ACPI_POWER_RESOURCE_STATE_ON)
249 return -ENOEXEC;
250 }
251 /* Update the power resource's _device_ power state */ 242 /* Update the power resource's _device_ power state */
252 resource->device->power.state = ACPI_STATE_D0; 243 resource->device->power.state = ACPI_STATE_D0;
253 244
@@ -258,7 +249,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
258 249
259static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) 250static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
260{ 251{
261 int result = 0, state; 252 int result = 0;
262 acpi_status status = AE_OK; 253 acpi_status status = AE_OK;
263 struct acpi_power_resource *resource = NULL; 254 struct acpi_power_resource *resource = NULL;
264 struct list_head *node, *next; 255 struct list_head *node, *next;
@@ -293,18 +284,6 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
293 if (ACPI_FAILURE(status)) 284 if (ACPI_FAILURE(status))
294 return -ENODEV; 285 return -ENODEV;
295 286
296 if (!acpi_power_nocheck) {
297 /*
298 * If acpi_power_nocheck is set, it is unnecessary to check
299 * the power state after power transition.
300 */
301 result = acpi_power_get_state(handle, &state);
302 if (result)
303 return result;
304 if (state != ACPI_POWER_RESOURCE_STATE_OFF)
305 return -ENOEXEC;
306 }
307
308 /* Update the power resource's _device_ power state */ 287 /* Update the power resource's _device_ power state */
309 resource->device->power.state = ACPI_STATE_D3; 288 resource->device->power.state = ACPI_STATE_D3;
310 289
@@ -385,17 +364,15 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
385 */ 364 */
386int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) 365int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
387{ 366{
388 int i, err; 367 int i, err = 0;
389 368
390 if (!dev || !dev->wakeup.flags.valid) 369 if (!dev || !dev->wakeup.flags.valid)
391 return -EINVAL; 370 return -EINVAL;
392 371
393 /* 372 mutex_lock(&acpi_device_lock);
394 * Do not execute the code below twice in a row without calling 373
395 * acpi_disable_wakeup_device_power() in between for the same device 374 if (dev->wakeup.prepare_count++)
396 */ 375 goto out;
397 if (dev->wakeup.flags.prepared)
398 return 0;
399 376
400 /* Open power resource */ 377 /* Open power resource */
401 for (i = 0; i < dev->wakeup.resources.count; i++) { 378 for (i = 0; i < dev->wakeup.resources.count; i++) {
@@ -403,7 +380,8 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
403 if (ret) { 380 if (ret) {
404 printk(KERN_ERR PREFIX "Transition power state\n"); 381 printk(KERN_ERR PREFIX "Transition power state\n");
405 dev->wakeup.flags.valid = 0; 382 dev->wakeup.flags.valid = 0;
406 return -ENODEV; 383 err = -ENODEV;
384 goto err_out;
407 } 385 }
408 } 386 }
409 387
@@ -412,9 +390,13 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
412 * in arbitrary power state afterwards. 390 * in arbitrary power state afterwards.
413 */ 391 */
414 err = acpi_device_sleep_wake(dev, 1, sleep_state, 3); 392 err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
415 if (!err)
416 dev->wakeup.flags.prepared = 1;
417 393
394 err_out:
395 if (err)
396 dev->wakeup.prepare_count = 0;
397
398 out:
399 mutex_unlock(&acpi_device_lock);
418 return err; 400 return err;
419} 401}
420 402
@@ -426,35 +408,42 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
426 */ 408 */
427int acpi_disable_wakeup_device_power(struct acpi_device *dev) 409int acpi_disable_wakeup_device_power(struct acpi_device *dev)
428{ 410{
429 int i, ret; 411 int i, err = 0;
430 412
431 if (!dev || !dev->wakeup.flags.valid) 413 if (!dev || !dev->wakeup.flags.valid)
432 return -EINVAL; 414 return -EINVAL;
433 415
416 mutex_lock(&acpi_device_lock);
417
418 if (--dev->wakeup.prepare_count > 0)
419 goto out;
420
434 /* 421 /*
435 * Do not execute the code below twice in a row without calling 422 * Executing the code below even if prepare_count is already zero when
436 * acpi_enable_wakeup_device_power() in between for the same device 423 * the function is called may be useful, for example for initialisation.
437 */ 424 */
438 if (!dev->wakeup.flags.prepared) 425 if (dev->wakeup.prepare_count < 0)
439 return 0; 426 dev->wakeup.prepare_count = 0;
440 427
441 dev->wakeup.flags.prepared = 0; 428 err = acpi_device_sleep_wake(dev, 0, 0, 0);
442 429 if (err)
443 ret = acpi_device_sleep_wake(dev, 0, 0, 0); 430 goto out;
444 if (ret)
445 return ret;
446 431
447 /* Close power resource */ 432 /* Close power resource */
448 for (i = 0; i < dev->wakeup.resources.count; i++) { 433 for (i = 0; i < dev->wakeup.resources.count; i++) {
449 ret = acpi_power_off_device(dev->wakeup.resources.handles[i], dev); 434 int ret = acpi_power_off_device(
435 dev->wakeup.resources.handles[i], dev);
450 if (ret) { 436 if (ret) {
451 printk(KERN_ERR PREFIX "Transition power state\n"); 437 printk(KERN_ERR PREFIX "Transition power state\n");
452 dev->wakeup.flags.valid = 0; 438 dev->wakeup.flags.valid = 0;
453 return -ENODEV; 439 err = -ENODEV;
440 goto out;
454 } 441 }
455 } 442 }
456 443
457 return ret; 444 out:
445 mutex_unlock(&acpi_device_lock);
446 return err;
458} 447}
459 448
460/* -------------------------------------------------------------------------- 449/* --------------------------------------------------------------------------