diff options
Diffstat (limited to 'drivers/acpi/acpica/tbinstal.c')
-rw-r--r-- | drivers/acpi/acpica/tbinstal.c | 82 |
1 files changed, 69 insertions, 13 deletions
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 37374b21969d..f865d5a096de 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c | |||
@@ -103,7 +103,9 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) | |||
103 | * | 103 | * |
104 | * RETURN: Status | 104 | * RETURN: Status |
105 | * | 105 | * |
106 | * DESCRIPTION: This function is called to add the ACPI table | 106 | * DESCRIPTION: This function is called to add an ACPI table. It is used to |
107 | * dynamically load tables via the Load and load_table AML | ||
108 | * operators. | ||
107 | * | 109 | * |
108 | ******************************************************************************/ | 110 | ******************************************************************************/ |
109 | 111 | ||
@@ -112,6 +114,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | |||
112 | { | 114 | { |
113 | u32 i; | 115 | u32 i; |
114 | acpi_status status = AE_OK; | 116 | acpi_status status = AE_OK; |
117 | struct acpi_table_header *override_table = NULL; | ||
115 | 118 | ||
116 | ACPI_FUNCTION_TRACE(tb_add_table); | 119 | ACPI_FUNCTION_TRACE(tb_add_table); |
117 | 120 | ||
@@ -201,6 +204,29 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) | |||
201 | } | 204 | } |
202 | } | 205 | } |
203 | 206 | ||
207 | /* | ||
208 | * ACPI Table Override: | ||
209 | * Allow the host to override dynamically loaded tables. | ||
210 | */ | ||
211 | status = acpi_os_table_override(table_desc->pointer, &override_table); | ||
212 | if (ACPI_SUCCESS(status) && override_table) { | ||
213 | ACPI_INFO((AE_INFO, | ||
214 | "%4.4s @ 0x%p Table override, replaced with:", | ||
215 | table_desc->pointer->signature, | ||
216 | ACPI_CAST_PTR(void, table_desc->address))); | ||
217 | |||
218 | /* We can delete the table that was passed as a parameter */ | ||
219 | |||
220 | acpi_tb_delete_table(table_desc); | ||
221 | |||
222 | /* Setup descriptor for the new table */ | ||
223 | |||
224 | table_desc->address = ACPI_PTR_TO_PHYSADDR(override_table); | ||
225 | table_desc->pointer = override_table; | ||
226 | table_desc->length = override_table->length; | ||
227 | table_desc->flags = ACPI_TABLE_ORIGIN_OVERRIDE; | ||
228 | } | ||
229 | |||
204 | /* Add the table to the global root table list */ | 230 | /* Add the table to the global root table list */ |
205 | 231 | ||
206 | status = acpi_tb_store_table(table_desc->address, table_desc->pointer, | 232 | status = acpi_tb_store_table(table_desc->address, table_desc->pointer, |
@@ -247,8 +273,9 @@ acpi_status acpi_tb_resize_root_table_list(void) | |||
247 | /* Increase the Table Array size */ | 273 | /* Increase the Table Array size */ |
248 | 274 | ||
249 | tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. | 275 | tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. |
250 | size + ACPI_ROOT_TABLE_SIZE_INCREMENT) | 276 | size + |
251 | * sizeof(struct acpi_table_desc)); | 277 | ACPI_ROOT_TABLE_SIZE_INCREMENT) * |
278 | sizeof(struct acpi_table_desc)); | ||
252 | if (!tables) { | 279 | if (!tables) { |
253 | ACPI_ERROR((AE_INFO, | 280 | ACPI_ERROR((AE_INFO, |
254 | "Could not allocate new root table array")); | 281 | "Could not allocate new root table array")); |
@@ -407,27 +434,56 @@ void acpi_tb_terminate(void) | |||
407 | * | 434 | * |
408 | * PARAMETERS: table_index - Table index | 435 | * PARAMETERS: table_index - Table index |
409 | * | 436 | * |
410 | * RETURN: None | 437 | * RETURN: Status |
411 | * | 438 | * |
412 | * DESCRIPTION: Delete all namespace objects created when this table was loaded. | 439 | * DESCRIPTION: Delete all namespace objects created when this table was loaded. |
413 | * | 440 | * |
414 | ******************************************************************************/ | 441 | ******************************************************************************/ |
415 | 442 | ||
416 | void acpi_tb_delete_namespace_by_owner(u32 table_index) | 443 | acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) |
417 | { | 444 | { |
418 | acpi_owner_id owner_id; | 445 | acpi_owner_id owner_id; |
446 | acpi_status status; | ||
447 | |||
448 | ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); | ||
449 | |||
450 | status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
451 | if (ACPI_FAILURE(status)) { | ||
452 | return_ACPI_STATUS(status); | ||
453 | } | ||
454 | |||
455 | if (table_index >= acpi_gbl_root_table_list.count) { | ||
456 | |||
457 | /* The table index does not exist */ | ||
419 | 458 | ||
420 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
421 | if (table_index < acpi_gbl_root_table_list.count) { | ||
422 | owner_id = | ||
423 | acpi_gbl_root_table_list.tables[table_index].owner_id; | ||
424 | } else { | ||
425 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 459 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
426 | return; | 460 | return_ACPI_STATUS(AE_NOT_EXIST); |
427 | } | 461 | } |
428 | 462 | ||
463 | /* Get the owner ID for this table, used to delete namespace nodes */ | ||
464 | |||
465 | owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; | ||
429 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 466 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
467 | |||
468 | /* | ||
469 | * Need to acquire the namespace writer lock to prevent interference | ||
470 | * with any concurrent namespace walks. The interpreter must be | ||
471 | * released during the deletion since the acquisition of the deletion | ||
472 | * lock may block, and also since the execution of a namespace walk | ||
473 | * must be allowed to use the interpreter. | ||
474 | */ | ||
475 | acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); | ||
476 | status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); | ||
477 | |||
430 | acpi_ns_delete_namespace_by_owner(owner_id); | 478 | acpi_ns_delete_namespace_by_owner(owner_id); |
479 | if (ACPI_FAILURE(status)) { | ||
480 | return_ACPI_STATUS(status); | ||
481 | } | ||
482 | |||
483 | acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); | ||
484 | |||
485 | status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); | ||
486 | return_ACPI_STATUS(status); | ||
431 | } | 487 | } |
432 | 488 | ||
433 | /******************************************************************************* | 489 | /******************************************************************************* |
@@ -535,8 +591,8 @@ u8 acpi_tb_is_table_loaded(u32 table_index) | |||
535 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | 591 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
536 | if (table_index < acpi_gbl_root_table_list.count) { | 592 | if (table_index < acpi_gbl_root_table_list.count) { |
537 | is_loaded = (u8) | 593 | is_loaded = (u8) |
538 | (acpi_gbl_root_table_list.tables[table_index]. | 594 | (acpi_gbl_root_table_list.tables[table_index].flags & |
539 | flags & ACPI_TABLE_IS_LOADED); | 595 | ACPI_TABLE_IS_LOADED); |
540 | } | 596 | } |
541 | 597 | ||
542 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | 598 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |