Skip to content

Commit 54c516a

Browse files
jwrdegoederafaeljw
authored andcommitted
ACPICA: Allow address_space_handler Install and _REG execution as 2 separate steps
ACPI-2.0 says that the EC op_region handler must be available immediately (like the standard default op_region handlers): Quoting from the ACPI spec version 6.3: "6.5.4 _REG (Region) ... 2. OSPM must make Embedded Controller operation regions, accessed via the Embedded Controllers described in ECDT, available before executing any control method. These operation regions may become inaccessible after OSPM runs _REG(EmbeddedControl, 0)." So the OS must probe the ECDT described EC and install the OpRegion handler before calling acpi_enable_subsystem() and acpi_initialize_objects(). This is a problem because calling acpi_install_address_space_handler() does not just install the op_region handler, it also runs the EC's _REG method. This _REG method may rely on initialization done by the _INI methods of one of the PCI / _SB root devices. For the other early/default op_region handlers the op_region handler install and the _REG execution is split into 2 separate steps: 1. acpi_ev_install_region_handlers(), called early from acpi_load_tables() 2. acpi_ev_initialize_op_regions(), called from acpi_initialize_objects() To fix the EC op_region issue, add 2 bew functions: 1. acpi_install_address_space_handler_no_reg() 2. acpi_execute_reg_methods() to allow doing things in 2 steps for other op_region handlers, like the EC handler, too. Note that the comment describing acpi_ev_install_region_handlers() even has an alinea describing this problem. Using the new methods allows users to avoid this problem. Link: acpica/acpica#786 Link: https://bugzilla.kernel.org/show_bug.cgi?id=214899 Reported-and-tested-by: Johannes Penßel <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 7a9d74e commit 54c516a

File tree

2 files changed

+95
-7
lines changed

2 files changed

+95
-7
lines changed

drivers/acpi/acpica/evxfregn.c

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ ACPI_MODULE_NAME("evxfregn")
2020

2121
/*******************************************************************************
2222
*
23-
* FUNCTION: acpi_install_address_space_handler
23+
* FUNCTION: acpi_install_address_space_handler_internal
2424
*
2525
* PARAMETERS: device - Handle for the device
2626
* space_id - The address space ID
2727
* handler - Address of the handler
2828
* setup - Address of the setup function
2929
* context - Value passed to the handler on each access
30+
* Run_reg - Run _REG methods for this address space?
3031
*
3132
* RETURN: Status
3233
*
@@ -37,13 +38,16 @@ ACPI_MODULE_NAME("evxfregn")
3738
* are executed here, and these methods can only be safely executed after
3839
* the default handlers have been installed and the hardware has been
3940
* initialized (via acpi_enable_subsystem.)
41+
* To avoid this problem pass FALSE for Run_Reg and later on call
42+
* acpi_execute_reg_methods() to execute _REG.
4043
*
4144
******************************************************************************/
42-
acpi_status
43-
acpi_install_address_space_handler(acpi_handle device,
44-
acpi_adr_space_type space_id,
45-
acpi_adr_space_handler handler,
46-
acpi_adr_space_setup setup, void *context)
45+
static acpi_status
46+
acpi_install_address_space_handler_internal(acpi_handle device,
47+
acpi_adr_space_type space_id,
48+
acpi_adr_space_handler handler,
49+
acpi_adr_space_setup setup,
50+
void *context, u8 run_reg)
4751
{
4852
struct acpi_namespace_node *node;
4953
acpi_status status;
@@ -80,14 +84,40 @@ acpi_install_address_space_handler(acpi_handle device,
8084

8185
/* Run all _REG methods for this address space */
8286

83-
acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
87+
if (run_reg) {
88+
acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
89+
}
8490

8591
unlock_and_exit:
8692
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
8793
return_ACPI_STATUS(status);
8894
}
8995

96+
acpi_status
97+
acpi_install_address_space_handler(acpi_handle device,
98+
acpi_adr_space_type space_id,
99+
acpi_adr_space_handler handler,
100+
acpi_adr_space_setup setup, void *context)
101+
{
102+
return acpi_install_address_space_handler_internal(device, space_id,
103+
handler, setup,
104+
context, TRUE);
105+
}
106+
90107
ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
108+
acpi_status
109+
acpi_install_address_space_handler_no_reg(acpi_handle device,
110+
acpi_adr_space_type space_id,
111+
acpi_adr_space_handler handler,
112+
acpi_adr_space_setup setup,
113+
void *context)
114+
{
115+
return acpi_install_address_space_handler_internal(device, space_id,
116+
handler, setup,
117+
context, FALSE);
118+
}
119+
120+
ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_no_reg)
91121

92122
/*******************************************************************************
93123
*
@@ -228,3 +258,51 @@ acpi_remove_address_space_handler(acpi_handle device,
228258
}
229259

230260
ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
261+
/*******************************************************************************
262+
*
263+
* FUNCTION: acpi_execute_reg_methods
264+
*
265+
* PARAMETERS: device - Handle for the device
266+
* space_id - The address space ID
267+
*
268+
* RETURN: Status
269+
*
270+
* DESCRIPTION: Execute _REG for all op_regions of a given space_id.
271+
*
272+
******************************************************************************/
273+
acpi_status
274+
acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id)
275+
{
276+
struct acpi_namespace_node *node;
277+
acpi_status status;
278+
279+
ACPI_FUNCTION_TRACE(acpi_execute_reg_methods);
280+
281+
/* Parameter validation */
282+
283+
if (!device) {
284+
return_ACPI_STATUS(AE_BAD_PARAMETER);
285+
}
286+
287+
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
288+
if (ACPI_FAILURE(status)) {
289+
return_ACPI_STATUS(status);
290+
}
291+
292+
/* Convert and validate the device handle */
293+
294+
node = acpi_ns_validate_handle(device);
295+
if (node) {
296+
297+
/* Run all _REG methods for this address space */
298+
299+
acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
300+
} else {
301+
status = AE_BAD_PARAMETER;
302+
}
303+
304+
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
305+
return_ACPI_STATUS(status);
306+
}
307+
308+
ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods)

include/acpi/acpixf.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,16 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
652652
acpi_adr_space_setup
653653
setup,
654654
void *context))
655+
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
656+
acpi_install_address_space_handler_no_reg
657+
(acpi_handle device, acpi_adr_space_type space_id,
658+
acpi_adr_space_handler handler,
659+
acpi_adr_space_setup setup,
660+
void *context))
661+
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
662+
acpi_execute_reg_methods(acpi_handle device,
663+
acpi_adr_space_type
664+
space_id))
655665
ACPI_EXTERNAL_RETURN_STATUS(acpi_status
656666
acpi_remove_address_space_handler(acpi_handle
657667
device,

0 commit comments

Comments
 (0)