diff options
| author | Zhao Yakui <yakui.zhao@intel.com> | 2008-03-19 01:26:54 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2008-04-09 21:57:22 -0400 |
| commit | 729b2bdbfa19dd9be98dbd49caf2773b3271cc24 (patch) | |
| tree | 525cca2b27a6252e54fea99db36d748ba299e32c | |
| parent | 7180c4c9e09888db0a188f729c96c6d7bd61fa83 (diff) | |
ACPI : Disable the device's ability to wake the sleeping system in the boot phase
In some machines some GPE is shared by several ACPI devices, for example:
sleep button, keyboard, mouse. At the same time one of them is
non-wake(runtime) device and the other are wake devices. In such case OSPM
should call the _PSW object to disable the device's ability to
wake the sleeping system in the boot phase.
Otherwise there will be ACPI interrupt flood triggered by the GPE input.
The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW.
So it is necessary to call _DSW object first. Only when it is not
present will the _PSW object used.
http://bugzilla.kernel.org/show_bug.cgi?id=10224
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | drivers/acpi/scan.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e6ce262b5d44..bd32351854ac 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -692,6 +692,9 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
| 692 | acpi_status status = 0; | 692 | acpi_status status = 0; |
| 693 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 693 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 694 | union acpi_object *package = NULL; | 694 | union acpi_object *package = NULL; |
| 695 | union acpi_object in_arg[3]; | ||
| 696 | struct acpi_object_list arg_list = { 3, in_arg }; | ||
| 697 | acpi_status psw_status = AE_OK; | ||
| 695 | 698 | ||
| 696 | struct acpi_device_id button_device_ids[] = { | 699 | struct acpi_device_id button_device_ids[] = { |
| 697 | {"PNP0C0D", 0}, | 700 | {"PNP0C0D", 0}, |
| @@ -700,7 +703,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
| 700 | {"", 0}, | 703 | {"", 0}, |
| 701 | }; | 704 | }; |
| 702 | 705 | ||
| 703 | |||
| 704 | /* _PRW */ | 706 | /* _PRW */ |
| 705 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); | 707 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); |
| 706 | if (ACPI_FAILURE(status)) { | 708 | if (ACPI_FAILURE(status)) { |
| @@ -718,6 +720,45 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
| 718 | kfree(buffer.pointer); | 720 | kfree(buffer.pointer); |
| 719 | 721 | ||
| 720 | device->wakeup.flags.valid = 1; | 722 | device->wakeup.flags.valid = 1; |
| 723 | /* Call _PSW/_DSW object to disable its ability to wake the sleeping | ||
| 724 | * system for the ACPI device with the _PRW object. | ||
| 725 | * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. | ||
| 726 | * So it is necessary to call _DSW object first. Only when it is not | ||
| 727 | * present will the _PSW object used. | ||
| 728 | */ | ||
| 729 | /* | ||
| 730 | * Three agruments are needed for the _DSW object. | ||
| 731 | * Argument 0: enable/disable the wake capabilities | ||
| 732 | * When _DSW object is called to disable the wake capabilities, maybe | ||
| 733 | * the first argument is filled. The value of the other two agruments | ||
| 734 | * is meaningless. | ||
| 735 | */ | ||
| 736 | in_arg[0].type = ACPI_TYPE_INTEGER; | ||
| 737 | in_arg[0].integer.value = 0; | ||
| 738 | in_arg[1].type = ACPI_TYPE_INTEGER; | ||
| 739 | in_arg[1].integer.value = 0; | ||
| 740 | in_arg[2].type = ACPI_TYPE_INTEGER; | ||
| 741 | in_arg[2].integer.value = 0; | ||
| 742 | psw_status = acpi_evaluate_object(device->handle, "_DSW", | ||
| 743 | &arg_list, NULL); | ||
| 744 | if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) | ||
| 745 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n")); | ||
| 746 | /* | ||
| 747 | * When the _DSW object is not present, OSPM will call _PSW object. | ||
| 748 | */ | ||
| 749 | if (psw_status == AE_NOT_FOUND) { | ||
| 750 | /* | ||
| 751 | * Only one agruments is required for the _PSW object. | ||
| 752 | * agrument 0: enable/disable the wake capabilities | ||
| 753 | */ | ||
| 754 | arg_list.count = 1; | ||
| 755 | in_arg[0].integer.value = 0; | ||
| 756 | psw_status = acpi_evaluate_object(device->handle, "_PSW", | ||
| 757 | &arg_list, NULL); | ||
| 758 | if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) | ||
| 759 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in " | ||
| 760 | "evaluate _PSW\n")); | ||
| 761 | } | ||
| 721 | /* Power button, Lid switch always enable wakeup */ | 762 | /* Power button, Lid switch always enable wakeup */ |
| 722 | if (!acpi_match_device_ids(device, button_device_ids)) | 763 | if (!acpi_match_device_ids(device, button_device_ids)) |
| 723 | device->wakeup.flags.run_wake = 1; | 764 | device->wakeup.flags.run_wake = 1; |
