[PATCH] ACPI: s2idle: Add _Ixx GPE wake indicator support

Saranya Gopal <[email protected]>
Newsgroups org.kernel.vger.linux-acpi,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pm
Message-ID <[email protected]>
ACPI 6.6 defines _Ixx indicator objects under \_GPE to mark GPEs that
should remain wake-enabled in s2idle without a _PRW association.
To support them, add new function acpi_setup_ixx_gpes() that looks for
_Ixx objects for all GPEs in the FADT 0/1 blocks and if it finds any, it
marks the corresponding GPE as wake-capable, in which case the GPE is
also enabled so long as it has a handler method because marking it as
wake-capable causes acpi_update_all_gpes() to skip it. Since that only
needs to be done if suspend-to-idle is enabled, make acpi_s2idle_setup()
call that new function.

For now, this is limited to x86 systems and it assumes that the GPEs
with _Ixx will not cause spurious wakeups to occur while suspended.

Signed-off-by: Saranya Gopal <[email protected]>
---
 drivers/acpi/x86/s2idle.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
index b6b1dd76a06b..ac49f9e75fae 100644
--- a/drivers/acpi/x86/s2idle.c
+++ b/drivers/acpi/x86/s2idle.c
@@ -24,6 +24,31 @@
 
 #ifdef CONFIG_SUSPEND
 
+static void acpi_setup_ixx_gpes(void)
+{
+	acpi_handle gpe_root;
+	unsigned int i;
+	char gpe_nr_str[5];
+
+	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_GPE", &gpe_root)))
+		return;
+
+	for (i = 0; i <= 0xff; i++) {
+		scnprintf(gpe_nr_str, sizeof(gpe_nr_str), "_I%02X", i);
+		if (!acpi_has_method(gpe_root, gpe_nr_str))
+			continue;
+		/*
+		 * Enable the GPE if it has a handler method because marking it
+		 * as wake-capable causes acpi_update_all_gpes() to skip it.
+		 */
+		if (ACPI_FAILURE(acpi_enable_gpe_cond(NULL, i, ACPI_GPE_DISPATCH_METHOD)))
+			continue;
+		acpi_mark_gpe_for_wake(NULL, i);
+		acpi_set_gpe_wake_mask(NULL, i, ACPI_GPE_ENABLE);
+		pm_pr_dbg("ACPI: GPE 0x%02x armed for wake via %s\n", i, gpe_nr_str);
+	}
+}
+
 static bool sleep_no_lps0 __read_mostly;
 module_param(sleep_no_lps0, bool, 0644);
 MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface");
@@ -649,6 +674,7 @@ void __init acpi_s2idle_setup(void)
 {
 	acpi_scan_add_handler(&lps0_handler);
 	s2idle_set_ops(&acpi_s2idle_ops_lps0);
+	acpi_setup_ixx_gpes();
 }
 
 int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.