aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2008-07-06 21:33:34 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-07-07 19:25:57 -0400
commit77e766099efc29d8b01db4b8244ff64fa3d3d0ca (patch)
tree6868acb2376388e5c02ed45a685ac31cc31a0bb1
parent44e4e66eeae5338b3ca0b28f8352e60bf18d5ba8 (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.c118
-rw-r--r--drivers/acpi/scan.c42
-rw-r--r--drivers/acpi/sleep/wakeup.c2
-rw-r--r--include/acpi/acpi_drivers.h4
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 */
312int 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 */
300int acpi_enable_wakeup_device_power(struct acpi_device *dev) 364int 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 */
338int acpi_disable_wakeup_device_power(struct acpi_device *dev) 394int 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
90int acpi_enable_wakeup_device_power(struct acpi_device *dev); 90int acpi_device_sleep_wake(struct acpi_device *dev,
91 int enable, int sleep_state, int dev_state);
92int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state);
91int acpi_disable_wakeup_device_power(struct acpi_device *dev); 93int acpi_disable_wakeup_device_power(struct acpi_device *dev);
92int acpi_power_get_inferred_state(struct acpi_device *device); 94int acpi_power_get_inferred_state(struct acpi_device *device);
93int acpi_power_transition(struct acpi_device *device, int state); 95int acpi_power_transition(struct acpi_device *device, int state);