diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2008-07-06 21:33:34 -0400 |
|---|---|---|
| committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-07-07 19:25:57 -0400 |
| commit | 77e766099efc29d8b01db4b8244ff64fa3d3d0ca (patch) | |
| tree | 6868acb2376388e5c02ed45a685ac31cc31a0bb1 | |
| parent | 44e4e66eeae5338b3ca0b28f8352e60bf18d5ba8 (diff) | |
ACPI: Introduce acpi_device_sleep_wake function
The currect ACPI code attempts to execute _PSW at three different
places and in one of them only it tries to execute _DSW before _PSW,
which is inconsistent with the other two cases.
Move the execution of _DSW and _PSW into a separate function called
acpi_device_sleep_wake() and call it wherever appropriate instead of
executing _DSW and/or _PSW directly.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
| -rw-r--r-- | drivers/acpi/power.c | 118 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 42 | ||||
| -rw-r--r-- | drivers/acpi/sleep/wakeup.c | 2 | ||||
| -rw-r--r-- | include/acpi/acpi_drivers.h | 4 |
4 files changed, 92 insertions, 74 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 81e4f081a4ae..2e959aa1ef0e 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
| @@ -292,69 +292,115 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev) | |||
| 292 | return 0; | 292 | return 0; |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | /** | ||
| 296 | * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in | ||
| 297 | * ACPI 3.0) _PSW (Power State Wake) | ||
| 298 | * @dev: Device to handle. | ||
| 299 | * @enable: 0 - disable, 1 - enable the wake capabilities of the device. | ||
| 300 | * @sleep_state: Target sleep state of the system. | ||
| 301 | * @dev_state: Target power state of the device. | ||
| 302 | * | ||
| 303 | * Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power | ||
| 304 | * State Wake) for the device, if present. On failure reset the device's | ||
| 305 | * wakeup.flags.valid flag. | ||
| 306 | * | ||
| 307 | * RETURN VALUE: | ||
| 308 | * 0 if either _DSW or _PSW has been successfully executed | ||
| 309 | * 0 if neither _DSW nor _PSW has been found | ||
| 310 | * -ENODEV if the execution of either _DSW or _PSW has failed | ||
| 311 | */ | ||
| 312 | int acpi_device_sleep_wake(struct acpi_device *dev, | ||
| 313 | int enable, int sleep_state, int dev_state) | ||
| 314 | { | ||
| 315 | union acpi_object in_arg[3]; | ||
| 316 | struct acpi_object_list arg_list = { 3, in_arg }; | ||
| 317 | acpi_status status = AE_OK; | ||
| 318 | |||
| 319 | /* | ||
| 320 | * Try to execute _DSW first. | ||
| 321 | * | ||
| 322 | * Three agruments are needed for the _DSW object: | ||
| 323 | * Argument 0: enable/disable the wake capabilities | ||
| 324 | * Argument 1: target system state | ||
| 325 | * Argument 2: target device state | ||
| 326 | * When _DSW object is called to disable the wake capabilities, maybe | ||
| 327 | * the first argument is filled. The values of the other two agruments | ||
| 328 | * are meaningless. | ||
| 329 | */ | ||
| 330 | in_arg[0].type = ACPI_TYPE_INTEGER; | ||
| 331 | in_arg[0].integer.value = enable; | ||
| 332 | in_arg[1].type = ACPI_TYPE_INTEGER; | ||
| 333 | in_arg[1].integer.value = sleep_state; | ||
| 334 | in_arg[2].type = ACPI_TYPE_INTEGER; | ||
| 335 | in_arg[2].integer.value = dev_state; | ||
| 336 | status = acpi_evaluate_object(dev->handle, "_DSW", &arg_list, NULL); | ||
| 337 | if (ACPI_SUCCESS(status)) { | ||
| 338 | return 0; | ||
| 339 | } else if (status != AE_NOT_FOUND) { | ||
| 340 | printk(KERN_ERR PREFIX "_DSW execution failed\n"); | ||
| 341 | dev->wakeup.flags.valid = 0; | ||
| 342 | return -ENODEV; | ||
| 343 | } | ||
| 344 | |||
| 345 | /* Execute _PSW */ | ||
| 346 | arg_list.count = 1; | ||
| 347 | in_arg[0].integer.value = enable; | ||
| 348 | status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); | ||
| 349 | if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { | ||
| 350 | printk(KERN_ERR PREFIX "_PSW execution failed\n"); | ||
| 351 | dev->wakeup.flags.valid = 0; | ||
| 352 | return -ENODEV; | ||
| 353 | } | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 295 | /* | 358 | /* |
| 296 | * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229): | 359 | * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229): |
| 297 | * 1. Power on the power resources required for the wakeup device | 360 | * 1. Power on the power resources required for the wakeup device |
| 298 | * 2. Enable _PSW (power state wake) for the device if present | 361 | * 2. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power |
| 362 | * State Wake) for the device, if present | ||
| 299 | */ | 363 | */ |
| 300 | int acpi_enable_wakeup_device_power(struct acpi_device *dev) | 364 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) |
| 301 | { | 365 | { |
| 302 | union acpi_object arg = { ACPI_TYPE_INTEGER }; | ||
| 303 | struct acpi_object_list arg_list = { 1, &arg }; | ||
| 304 | acpi_status status = AE_OK; | ||
| 305 | int i; | 366 | int i; |
| 306 | int ret = 0; | ||
| 307 | 367 | ||
| 308 | if (!dev || !dev->wakeup.flags.valid) | 368 | if (!dev || !dev->wakeup.flags.valid) |
| 309 | return -1; | 369 | return -EINVAL; |
| 310 | 370 | ||
| 311 | arg.integer.value = 1; | ||
| 312 | /* Open power resource */ | 371 | /* Open power resource */ |
| 313 | for (i = 0; i < dev->wakeup.resources.count; i++) { | 372 | for (i = 0; i < dev->wakeup.resources.count; i++) { |
| 314 | ret = acpi_power_on(dev->wakeup.resources.handles[i], dev); | 373 | int ret = acpi_power_on(dev->wakeup.resources.handles[i], dev); |
| 315 | if (ret) { | 374 | if (ret) { |
| 316 | printk(KERN_ERR PREFIX "Transition power state\n"); | 375 | printk(KERN_ERR PREFIX "Transition power state\n"); |
| 317 | dev->wakeup.flags.valid = 0; | 376 | dev->wakeup.flags.valid = 0; |
| 318 | return -1; | 377 | return -ENODEV; |
| 319 | } | 378 | } |
| 320 | } | 379 | } |
| 321 | 380 | ||
| 322 | /* Execute PSW */ | 381 | /* |
| 323 | status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); | 382 | * Passing 3 as the third argument below means the device may be placed |
| 324 | if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { | 383 | * in arbitrary power state afterwards. |
| 325 | printk(KERN_ERR PREFIX "Evaluate _PSW\n"); | 384 | */ |
| 326 | dev->wakeup.flags.valid = 0; | 385 | return acpi_device_sleep_wake(dev, 1, sleep_state, 3); |
| 327 | ret = -1; | ||
| 328 | } | ||
| 329 | |||
| 330 | return ret; | ||
| 331 | } | 386 | } |
| 332 | 387 | ||
| 333 | /* | 388 | /* |
| 334 | * Shutdown a wakeup device, counterpart of above method | 389 | * Shutdown a wakeup device, counterpart of above method |
| 335 | * 1. Disable _PSW (power state wake) | 390 | * 1. Execute _DSW (Device Sleep Wake) or (deprecated in ACPI 3.0) _PSW (Power |
| 391 | * State Wake) for the device, if present | ||
| 336 | * 2. Shutdown down the power resources | 392 | * 2. Shutdown down the power resources |
| 337 | */ | 393 | */ |
| 338 | int acpi_disable_wakeup_device_power(struct acpi_device *dev) | 394 | int acpi_disable_wakeup_device_power(struct acpi_device *dev) |
| 339 | { | 395 | { |
| 340 | union acpi_object arg = { ACPI_TYPE_INTEGER }; | 396 | int i, ret; |
| 341 | struct acpi_object_list arg_list = { 1, &arg }; | ||
| 342 | acpi_status status = AE_OK; | ||
| 343 | int i; | ||
| 344 | int ret = 0; | ||
| 345 | |||
| 346 | 397 | ||
| 347 | if (!dev || !dev->wakeup.flags.valid) | 398 | if (!dev || !dev->wakeup.flags.valid) |
| 348 | return -1; | 399 | return -EINVAL; |
| 349 | 400 | ||
| 350 | arg.integer.value = 0; | 401 | ret = acpi_device_sleep_wake(dev, 0, 0, 0); |
| 351 | /* Execute PSW */ | 402 | if (ret) |
| 352 | status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); | 403 | return ret; |
| 353 | if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { | ||
| 354 | printk(KERN_ERR PREFIX "Evaluate _PSW\n"); | ||
| 355 | dev->wakeup.flags.valid = 0; | ||
| 356 | return -1; | ||
| 357 | } | ||
| 358 | 404 | ||
| 359 | /* Close power resource */ | 405 | /* Close power resource */ |
| 360 | for (i = 0; i < dev->wakeup.resources.count; i++) { | 406 | for (i = 0; i < dev->wakeup.resources.count; i++) { |
| @@ -362,7 +408,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) | |||
| 362 | if (ret) { | 408 | if (ret) { |
| 363 | printk(KERN_ERR PREFIX "Transition power state\n"); | 409 | printk(KERN_ERR PREFIX "Transition power state\n"); |
| 364 | dev->wakeup.flags.valid = 0; | 410 | dev->wakeup.flags.valid = 0; |
| 365 | return -1; | 411 | return -ENODEV; |
| 366 | } | 412 | } |
| 367 | } | 413 | } |
| 368 | 414 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 6d85289f1c12..f276890cfde7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -691,9 +691,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
| 691 | acpi_status status = 0; | 691 | acpi_status status = 0; |
| 692 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 692 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 693 | union acpi_object *package = NULL; | 693 | union acpi_object *package = NULL; |
| 694 | union acpi_object in_arg[3]; | 694 | int psw_error; |
| 695 | struct acpi_object_list arg_list = { 3, in_arg }; | ||
| 696 | acpi_status psw_status = AE_OK; | ||
| 697 | 695 | ||
| 698 | struct acpi_device_id button_device_ids[] = { | 696 | struct acpi_device_id button_device_ids[] = { |
| 699 | {"PNP0C0D", 0}, | 697 | {"PNP0C0D", 0}, |
| @@ -725,39 +723,11 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
| 725 | * So it is necessary to call _DSW object first. Only when it is not | 723 | * So it is necessary to call _DSW object first. Only when it is not |
| 726 | * present will the _PSW object used. | 724 | * present will the _PSW object used. |
| 727 | */ | 725 | */ |
| 728 | /* | 726 | psw_error = acpi_device_sleep_wake(device, 0, 0, 0); |
| 729 | * Three agruments are needed for the _DSW object. | 727 | if (psw_error) |
| 730 | * Argument 0: enable/disable the wake capabilities | 728 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 731 | * When _DSW object is called to disable the wake capabilities, maybe | 729 | "error in _DSW or _PSW evaluation\n")); |
| 732 | * the first argument is filled. The value of the other two agruments | 730 | |
| 733 | * is meaningless. | ||
| 734 | */ | ||
| 735 | in_arg[0].type = ACPI_TYPE_INTEGER; | ||
| 736 | in_arg[0].integer.value = 0; | ||
| 737 | in_arg[1].type = ACPI_TYPE_INTEGER; | ||
| 738 | in_arg[1].integer.value = 0; | ||
| 739 | in_arg[2].type = ACPI_TYPE_INTEGER; | ||
| 740 | in_arg[2].integer.value = 0; | ||
| 741 | psw_status = acpi_evaluate_object(device->handle, "_DSW", | ||
| 742 | &arg_list, NULL); | ||
| 743 | if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) | ||
| 744 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n")); | ||
| 745 | /* | ||
| 746 | * When the _DSW object is not present, OSPM will call _PSW object. | ||
| 747 | */ | ||
| 748 | if (psw_status == AE_NOT_FOUND) { | ||
| 749 | /* | ||
| 750 | * Only one agruments is required for the _PSW object. | ||
| 751 | * agrument 0: enable/disable the wake capabilities | ||
| 752 | */ | ||
| 753 | arg_list.count = 1; | ||
| 754 | in_arg[0].integer.value = 0; | ||
| 755 | psw_status = acpi_evaluate_object(device->handle, "_PSW", | ||
| 756 | &arg_list, NULL); | ||
| 757 | if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) | ||
| 758 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in " | ||
| 759 | "evaluate _PSW\n")); | ||
| 760 | } | ||
| 761 | /* Power button, Lid switch always enable wakeup */ | 731 | /* Power button, Lid switch always enable wakeup */ |
| 762 | if (!acpi_match_device_ids(device, button_device_ids)) | 732 | if (!acpi_match_device_ids(device, button_device_ids)) |
| 763 | device->wakeup.flags.run_wake = 1; | 733 | device->wakeup.flags.run_wake = 1; |
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index ed8e41becf0c..7422a2213944 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c | |||
| @@ -42,7 +42,7 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state) | |||
| 42 | continue; | 42 | continue; |
| 43 | 43 | ||
| 44 | spin_unlock(&acpi_device_lock); | 44 | spin_unlock(&acpi_device_lock); |
| 45 | acpi_enable_wakeup_device_power(dev); | 45 | acpi_enable_wakeup_device_power(dev, sleep_state); |
| 46 | spin_lock(&acpi_device_lock); | 46 | spin_lock(&acpi_device_lock); |
| 47 | } | 47 | } |
| 48 | spin_unlock(&acpi_device_lock); | 48 | spin_unlock(&acpi_device_lock); |
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 9757a040a505..e5f38e5ce86f 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h | |||
| @@ -87,7 +87,9 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, | |||
| 87 | -------------------------------------------------------------------------- */ | 87 | -------------------------------------------------------------------------- */ |
| 88 | 88 | ||
| 89 | #ifdef CONFIG_ACPI_POWER | 89 | #ifdef CONFIG_ACPI_POWER |
| 90 | int acpi_enable_wakeup_device_power(struct acpi_device *dev); | 90 | int acpi_device_sleep_wake(struct acpi_device *dev, |
| 91 | int enable, int sleep_state, int dev_state); | ||
| 92 | int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); | ||
| 91 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); | 93 | int acpi_disable_wakeup_device_power(struct acpi_device *dev); |
| 92 | int acpi_power_get_inferred_state(struct acpi_device *device); | 94 | int acpi_power_get_inferred_state(struct acpi_device *device); |
| 93 | int acpi_power_transition(struct acpi_device *device, int state); | 95 | int acpi_power_transition(struct acpi_device *device, int state); |
