[PATCH] ACPI/ACPICA: Run EC _REG explicitly for ECDT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From 6f2fac0ffcd7fd61036baa0798ab171496cff50f Mon Sep 17 00:00:00 2001
From: Zhang Rui <rui.zhang@xxxxxxxxx>
Date: Fri, 4 Jan 2019 14:35:52 +0800
Subject: [PATCH] ACPI/ACPICA: Run EC _REG explicitly for ECDT

commit d737f333b211 ("ACPI: probe ECDT before loading AML tables
regardless of module-level code flag") probes ECDT before loading
the AML tables.

This is the right thing to do according to the ACPI Spec, but
unfortunately, it breaks the current kernel EC/ECDT support, and makes
many devices, including battery, lid, etc, fails to work on a variety
of platforms.

This is because:
1. Probing ECDT requires installing EC address space handler
2. EC _REG can not be evaluated at the time when probing ECDT because AML
   tables have not been loaded yet.
3. Many devices fail to work because EC _REG is not evaluated.

To fix this, a solution is proposed in this patch to evaluate EC _REG
explicitly in ACPICA, if ECDT has been probed.

Fixes: d737f333b211 ("ACPI: probe ECDT before loading AML tables regardless of module-level code flag")
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199981
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=201351
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=200011
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=200141
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=201679
Signed-off-by: Zhang Rui <rui.zhang@xxxxxxxxx>
---
 drivers/acpi/acpica/acevents.h  |  4 ++--
 drivers/acpi/acpica/evhandler.c | 21 ++++++++++++++-------
 drivers/acpi/acpica/evregion.c  | 10 ++++++++--
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index b412aa9..2f43ab0 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -155,8 +155,8 @@ union acpi_operand_object *acpi_ev_find_region_handler(acpi_adr_space_type
 						       *handler_obj);
 
 u8
-acpi_ev_has_default_handler(struct acpi_namespace_node *node,
-			    acpi_adr_space_type space_id);
+acpi_ev_has_handler(struct acpi_namespace_node *node,
+			    acpi_adr_space_type space_id, bool default_handler);
 
 acpi_status acpi_ev_install_region_handlers(void);
 
diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c
index 4ed1e67..c6d61fd 100644
--- a/drivers/acpi/acpica/evhandler.c
+++ b/drivers/acpi/acpica/evhandler.c
@@ -102,21 +102,22 @@ acpi_status acpi_ev_install_region_handlers(void)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_has_default_handler
+ * FUNCTION:    acpi_ev_has_handler
  *
  * PARAMETERS:  node                - Namespace node for the device
  *              space_id            - The address space ID
+ *              default_handler     - check for default handler
  *
- * RETURN:      TRUE if default handler is installed, FALSE otherwise
+ * RETURN:      TRUE if handler is installed, FALSE otherwise
  *
- * DESCRIPTION: Check if the default handler is installed for the requested
+ * DESCRIPTION: Check if the handler is installed for the requested
  *              space ID.
  *
  ******************************************************************************/
 
 u8
-acpi_ev_has_default_handler(struct acpi_namespace_node *node,
-			    acpi_adr_space_type space_id)
+acpi_ev_has_handler(struct acpi_namespace_node *node,
+			    acpi_adr_space_type space_id, bool default_handler)
 {
 	union acpi_operand_object *obj_desc;
 	union acpi_operand_object *handler_obj;
@@ -131,8 +132,14 @@ acpi_ev_has_default_handler(struct acpi_namespace_node *node,
 
 		while (handler_obj) {
 			if (handler_obj->address_space.space_id == space_id) {
-				if (handler_obj->address_space.handler_flags &
-				    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
+				if (default_handler &&
+				    (handler_obj->address_space.handler_flags &
+				    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+					return (TRUE);
+				}
+				if (!default_handler &&
+				    !(handler_obj->address_space.handler_flags &
+				    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 					return (TRUE);
 				}
 			}
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 49decca..2b04cf5 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -60,15 +60,21 @@ acpi_status acpi_ev_initialize_op_regions(void)
 		 * default, the _REG methods will have already been run (when the
 		 * handler was installed)
 		 */
-		if (acpi_ev_has_default_handler(acpi_gbl_root_node,
+		if (acpi_ev_has_handler(acpi_gbl_root_node,
 						acpi_gbl_default_address_spaces
-						[i])) {
+						[i], true)) {
 			acpi_ev_execute_reg_methods(acpi_gbl_root_node,
 						    acpi_gbl_default_address_spaces
 						    [i], ACPI_REG_CONNECT);
 		}
 	}
 
+	/* Run _REG methods for EC Operation Region if ECDT has been probed */
+	if (acpi_ev_has_handler(acpi_gbl_root_node, ACPI_ADR_SPACE_EC, false))
+		acpi_ev_execute_reg_methods(acpi_gbl_root_node,
+					    ACPI_ADR_SPACE_EC,
+					    ACPI_REG_CONNECT);
+
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return_ACPI_STATUS(status);
 }
-- 
2.7.4




[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux