Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: EC: Fix regression related to wrong ECDT initialization order

Commit 2a5708409e4e (ACPI / EC: Fix a gap that ECDT EC cannot handle
EC events) introduced acpi_ec_ecdt_start(), but that function is
invoked before acpi_ec_query_init(), which is too early. This causes
the kernel to crash if an EC event occurs after boot, when ec_query_wq
is not valid:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000102
...
Workqueue: events acpi_ec_event_handler
task: ffff9f539790dac0 task.stack: ffffb437c0e10000
RIP: 0010:__queue_work+0x32/0x430

Normally, the DSDT EC should always be valid, so acpi_ec_ecdt_start()
is actually a no-op in the majority of cases. However, commit
c712bb58d827 (ACPI / EC: Add support to skip boot stage DSDT probe)
caused the probing of the DSDT EC as the "boot EC" to be skipped when
the ECDT EC is valid and uncovered the bug.

Fix this issue by invoking acpi_ec_ecdt_start() after acpi_ec_query_init()
in acpi_ec_init().

Link: https://jira01.devtools.intel.com/browse/LCK-4348
Fixes: 2a5708409e4e (ACPI / EC: Fix a gap that ECDT EC cannot handle EC events)
Fixes: c712bb58d827 (ACPI / EC: Add support to skip boot stage DSDT probe)
Reported-by: Wang Wendy <wendy.wang@intel.com>
Tested-by: Feng Chenzhou <chenzhoux.feng@intel.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
[ rjw: Changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Lv Zheng and committed by
Rafael J. Wysocki
98529b92 ef954844

+7 -12
+7 -10
drivers/acpi/ec.c
··· 1741 1741 * functioning ECDT EC first in order to handle the events. 1742 1742 * https://bugzilla.kernel.org/show_bug.cgi?id=115021 1743 1743 */ 1744 - int __init acpi_ec_ecdt_start(void) 1744 + static int __init acpi_ec_ecdt_start(void) 1745 1745 { 1746 1746 acpi_handle handle; 1747 1747 ··· 2003 2003 int __init acpi_ec_init(void) 2004 2004 { 2005 2005 int result; 2006 + int ecdt_fail, dsdt_fail; 2006 2007 2007 2008 /* register workqueue for _Qxx evaluations */ 2008 2009 result = acpi_ec_query_init(); 2009 2010 if (result) 2010 - goto err_exit; 2011 - /* Now register the driver for the EC */ 2012 - result = acpi_bus_register_driver(&acpi_ec_driver); 2013 - if (result) 2014 - goto err_exit; 2011 + return result; 2015 2012 2016 - err_exit: 2017 - if (result) 2018 - acpi_ec_query_exit(); 2019 - return result; 2013 + /* Drivers must be started after acpi_ec_query_init() */ 2014 + ecdt_fail = acpi_ec_ecdt_start(); 2015 + dsdt_fail = acpi_bus_register_driver(&acpi_ec_driver); 2016 + return ecdt_fail && dsdt_fail ? -ENODEV : 0; 2020 2017 } 2021 2018 2022 2019 /* EC driver currently not unloadable */
-1
drivers/acpi/internal.h
··· 185 185 int acpi_ec_init(void); 186 186 int acpi_ec_ecdt_probe(void); 187 187 int acpi_ec_dsdt_probe(void); 188 - int acpi_ec_ecdt_start(void); 189 188 void acpi_ec_block_transactions(void); 190 189 void acpi_ec_unblock_transactions(void); 191 190 int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
-1
drivers/acpi/scan.c
··· 2084 2084 2085 2085 acpi_gpe_apply_masked_gpes(); 2086 2086 acpi_update_all_gpes(); 2087 - acpi_ec_ecdt_start(); 2088 2087 2089 2088 acpi_scan_initialized = true; 2090 2089