diff options
author | Lv Zheng <lv.zheng@intel.com> | 2016-09-07 02:07:24 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-09-09 20:43:03 -0400 |
commit | ac0f06ebb815dabe42f2b2886ee9f879a2170ce4 (patch) | |
tree | 59cd81530337d1b16b388dadf0586aeb36bd8e48 /drivers/acpi/acpica/exconfig.c | |
parent | 441ad11d078f35093ceaf510742df423c2d89a3b (diff) |
ACPICA: Tables: Tune table mutex to be a leaf lock
ACPICA commit f564d57c6501b97a2871f0b4c048e79910f71783
This patch tunes MTX_TABLES into a leaf lock by always ensuring it is
released before holding other locks.
This patch also collects all table loading related functions into
acpi_tb_load_table() (invoked by load_table opcode) and
acpi_tb_install_and_load_table() (invoked by Load opcode and acpi_load_table()) so
that we can have lock tuning code collected at the boundary of these 2
functions. Lv Zheng.
Link: https://github.com/acpica/acpica/commit/f564d57c
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Dutch Guy <lucht_piloot@gmx.net>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/exconfig.c')
-rw-r--r-- | drivers/acpi/acpica/exconfig.c | 105 |
1 files changed, 21 insertions, 84 deletions
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 578d5c832325..421836a7a5b9 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c | |||
@@ -55,9 +55,7 @@ ACPI_MODULE_NAME("exconfig") | |||
55 | 55 | ||
56 | /* Local prototypes */ | 56 | /* Local prototypes */ |
57 | static acpi_status | 57 | static acpi_status |
58 | acpi_ex_add_table(u32 table_index, | 58 | acpi_ex_add_table(u32 table_index, union acpi_operand_object **ddb_handle); |
59 | struct acpi_namespace_node *parent_node, | ||
60 | union acpi_operand_object **ddb_handle); | ||
61 | 59 | ||
62 | static acpi_status | 60 | static acpi_status |
63 | acpi_ex_region_read(union acpi_operand_object *obj_desc, | 61 | acpi_ex_region_read(union acpi_operand_object *obj_desc, |
@@ -79,13 +77,9 @@ acpi_ex_region_read(union acpi_operand_object *obj_desc, | |||
79 | ******************************************************************************/ | 77 | ******************************************************************************/ |
80 | 78 | ||
81 | static acpi_status | 79 | static acpi_status |
82 | acpi_ex_add_table(u32 table_index, | 80 | acpi_ex_add_table(u32 table_index, union acpi_operand_object **ddb_handle) |
83 | struct acpi_namespace_node *parent_node, | ||
84 | union acpi_operand_object **ddb_handle) | ||
85 | { | 81 | { |
86 | union acpi_operand_object *obj_desc; | 82 | union acpi_operand_object *obj_desc; |
87 | acpi_status status; | ||
88 | acpi_owner_id owner_id; | ||
89 | 83 | ||
90 | ACPI_FUNCTION_TRACE(ex_add_table); | 84 | ACPI_FUNCTION_TRACE(ex_add_table); |
91 | 85 | ||
@@ -100,40 +94,8 @@ acpi_ex_add_table(u32 table_index, | |||
100 | 94 | ||
101 | obj_desc->common.flags |= AOPOBJ_DATA_VALID; | 95 | obj_desc->common.flags |= AOPOBJ_DATA_VALID; |
102 | obj_desc->reference.class = ACPI_REFCLASS_TABLE; | 96 | obj_desc->reference.class = ACPI_REFCLASS_TABLE; |
103 | *ddb_handle = obj_desc; | ||
104 | |||
105 | /* Install the new table into the local data structures */ | ||
106 | |||
107 | obj_desc->reference.value = table_index; | 97 | obj_desc->reference.value = table_index; |
108 | 98 | *ddb_handle = obj_desc; | |
109 | /* Add the table to the namespace */ | ||
110 | |||
111 | status = acpi_ns_load_table(table_index, parent_node); | ||
112 | if (ACPI_FAILURE(status)) { | ||
113 | acpi_ut_remove_reference(obj_desc); | ||
114 | *ddb_handle = NULL; | ||
115 | return_ACPI_STATUS(status); | ||
116 | } | ||
117 | |||
118 | /* Execute any module-level code that was found in the table */ | ||
119 | |||
120 | acpi_ex_exit_interpreter(); | ||
121 | if (!acpi_gbl_parse_table_as_term_list | ||
122 | && acpi_gbl_group_module_level_code) { | ||
123 | acpi_ns_exec_module_code_list(); | ||
124 | } | ||
125 | acpi_ex_enter_interpreter(); | ||
126 | |||
127 | /* | ||
128 | * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is | ||
129 | * responsible for discovering any new wake GPEs by running _PRW methods | ||
130 | * that may have been loaded by this table. | ||
131 | */ | ||
132 | status = acpi_tb_get_owner_id(table_index, &owner_id); | ||
133 | if (ACPI_SUCCESS(status)) { | ||
134 | acpi_ev_update_gpes(owner_id); | ||
135 | } | ||
136 | |||
137 | return_ACPI_STATUS(AE_OK); | 99 | return_ACPI_STATUS(AE_OK); |
138 | } | 100 | } |
139 | 101 | ||
@@ -160,16 +122,17 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
160 | struct acpi_namespace_node *start_node; | 122 | struct acpi_namespace_node *start_node; |
161 | struct acpi_namespace_node *parameter_node = NULL; | 123 | struct acpi_namespace_node *parameter_node = NULL; |
162 | union acpi_operand_object *ddb_handle; | 124 | union acpi_operand_object *ddb_handle; |
163 | struct acpi_table_header *table; | ||
164 | u32 table_index; | 125 | u32 table_index; |
165 | 126 | ||
166 | ACPI_FUNCTION_TRACE(ex_load_table_op); | 127 | ACPI_FUNCTION_TRACE(ex_load_table_op); |
167 | 128 | ||
168 | /* Find the ACPI table in the RSDT/XSDT */ | 129 | /* Find the ACPI table in the RSDT/XSDT */ |
169 | 130 | ||
131 | acpi_ex_exit_interpreter(); | ||
170 | status = acpi_tb_find_table(operand[0]->string.pointer, | 132 | status = acpi_tb_find_table(operand[0]->string.pointer, |
171 | operand[1]->string.pointer, | 133 | operand[1]->string.pointer, |
172 | operand[2]->string.pointer, &table_index); | 134 | operand[2]->string.pointer, &table_index); |
135 | acpi_ex_enter_interpreter(); | ||
173 | if (ACPI_FAILURE(status)) { | 136 | if (ACPI_FAILURE(status)) { |
174 | if (status != AE_NOT_FOUND) { | 137 | if (status != AE_NOT_FOUND) { |
175 | return_ACPI_STATUS(status); | 138 | return_ACPI_STATUS(status); |
@@ -232,7 +195,15 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
232 | 195 | ||
233 | /* Load the table into the namespace */ | 196 | /* Load the table into the namespace */ |
234 | 197 | ||
235 | status = acpi_ex_add_table(table_index, parent_node, &ddb_handle); | 198 | ACPI_INFO(("Dynamic OEM Table Load:")); |
199 | acpi_ex_exit_interpreter(); | ||
200 | status = acpi_tb_load_table(table_index, parent_node); | ||
201 | acpi_ex_enter_interpreter(); | ||
202 | if (ACPI_FAILURE(status)) { | ||
203 | return_ACPI_STATUS(status); | ||
204 | } | ||
205 | |||
206 | status = acpi_ex_add_table(table_index, &ddb_handle); | ||
236 | if (ACPI_FAILURE(status)) { | 207 | if (ACPI_FAILURE(status)) { |
237 | return_ACPI_STATUS(status); | 208 | return_ACPI_STATUS(status); |
238 | } | 209 | } |
@@ -255,19 +226,6 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
255 | } | 226 | } |
256 | } | 227 | } |
257 | 228 | ||
258 | status = acpi_get_table_by_index(table_index, &table); | ||
259 | if (ACPI_SUCCESS(status)) { | ||
260 | ACPI_INFO(("Dynamic OEM Table Load:")); | ||
261 | acpi_tb_print_table_header(0, table); | ||
262 | } | ||
263 | |||
264 | /* Invoke table handler if present */ | ||
265 | |||
266 | if (acpi_gbl_table_handler) { | ||
267 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, | ||
268 | acpi_gbl_table_handler_context); | ||
269 | } | ||
270 | |||
271 | *return_desc = ddb_handle; | 229 | *return_desc = ddb_handle; |
272 | return_ACPI_STATUS(status); | 230 | return_ACPI_STATUS(status); |
273 | } | 231 | } |
@@ -478,13 +436,12 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
478 | /* Install the new table into the local data structures */ | 436 | /* Install the new table into the local data structures */ |
479 | 437 | ||
480 | ACPI_INFO(("Dynamic OEM Table Load:")); | 438 | ACPI_INFO(("Dynamic OEM Table Load:")); |
481 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 439 | acpi_ex_exit_interpreter(); |
482 | 440 | status = | |
483 | status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table), | 441 | acpi_tb_install_and_load_table(table, ACPI_PTR_TO_PHYSADDR(table), |
484 | ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, | 442 | ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, |
485 | TRUE, TRUE, &table_index); | 443 | TRUE, &table_index); |
486 | 444 | acpi_ex_enter_interpreter(); | |
487 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
488 | if (ACPI_FAILURE(status)) { | 445 | if (ACPI_FAILURE(status)) { |
489 | 446 | ||
490 | /* Delete allocated table buffer */ | 447 | /* Delete allocated table buffer */ |
@@ -494,25 +451,13 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
494 | } | 451 | } |
495 | 452 | ||
496 | /* | 453 | /* |
497 | * Note: Now table is "INSTALLED", it must be validated before | ||
498 | * loading. | ||
499 | */ | ||
500 | status = | ||
501 | acpi_tb_validate_table(&acpi_gbl_root_table_list. | ||
502 | tables[table_index]); | ||
503 | if (ACPI_FAILURE(status)) { | ||
504 | return_ACPI_STATUS(status); | ||
505 | } | ||
506 | |||
507 | /* | ||
508 | * Add the table to the namespace. | 454 | * Add the table to the namespace. |
509 | * | 455 | * |
510 | * Note: Load the table objects relative to the root of the namespace. | 456 | * Note: Load the table objects relative to the root of the namespace. |
511 | * This appears to go against the ACPI specification, but we do it for | 457 | * This appears to go against the ACPI specification, but we do it for |
512 | * compatibility with other ACPI implementations. | 458 | * compatibility with other ACPI implementations. |
513 | */ | 459 | */ |
514 | status = | 460 | status = acpi_ex_add_table(table_index, &ddb_handle); |
515 | acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); | ||
516 | if (ACPI_FAILURE(status)) { | 461 | if (ACPI_FAILURE(status)) { |
517 | 462 | ||
518 | /* On error, table_ptr was deallocated above */ | 463 | /* On error, table_ptr was deallocated above */ |
@@ -535,14 +480,6 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
535 | /* Remove the reference by added by acpi_ex_store above */ | 480 | /* Remove the reference by added by acpi_ex_store above */ |
536 | 481 | ||
537 | acpi_ut_remove_reference(ddb_handle); | 482 | acpi_ut_remove_reference(ddb_handle); |
538 | |||
539 | /* Invoke table handler if present */ | ||
540 | |||
541 | if (acpi_gbl_table_handler) { | ||
542 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, | ||
543 | acpi_gbl_table_handler_context); | ||
544 | } | ||
545 | |||
546 | return_ACPI_STATUS(status); | 483 | return_ACPI_STATUS(status); |
547 | } | 484 | } |
548 | 485 | ||