diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 25802f302ffe18c00608ff5ae347f79931b57645..009aef5fcbfc6c4ed353518c1f18be3cf68d05fc 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -234,6 +234,13 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, table->oem_table_id)); } + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, + acpi_gbl_table_handler_context); + } + *return_desc = ddb_handle; return_ACPI_STATUS(status); } @@ -352,6 +359,14 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, return_ACPI_STATUS(status); } + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, + table_desc.pointer, + acpi_gbl_table_handler_context); + } + cleanup: if (ACPI_FAILURE(status)) { acpi_tb_delete_table(&table_desc); @@ -376,6 +391,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) acpi_status status = AE_OK; union acpi_operand_object *table_desc = ddb_handle; acpi_native_uint table_index; + struct acpi_table_header *table; ACPI_FUNCTION_TRACE(ex_unload_table); @@ -395,6 +411,17 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) table_index = (acpi_native_uint) table_desc->reference.object; + /* Invoke table handler if present */ + + if (acpi_gbl_table_handler) { + status = acpi_get_table_by_index(table_index, &table); + if (ACPI_SUCCESS(status)) { + (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, + table, + acpi_gbl_table_handler_context); + } + } + /* * Delete the entire namespace under this table Node * (Offset contains the table_id) @@ -407,5 +434,5 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) /* Delete the table descriptor (ddb_handle) */ acpi_ut_remove_reference(table_desc); - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index a9e3331fee5deade7a3e8047a3c9da980e103f25..5f2271542a9664b2d49cc2f793829fbeeca71591 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -635,6 +635,95 @@ acpi_status acpi_load_tables(void) ACPI_EXPORT_SYMBOL(acpi_load_tables) +/******************************************************************************* + * + * FUNCTION: acpi_install_table_handler + * + * PARAMETERS: Handler - Table event handler + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Install table event handler + * + ******************************************************************************/ +acpi_status +acpi_install_table_handler(acpi_tbl_handler handler, void *context) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_install_table_handler); + + if (!handler) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Don't allow more than one handler */ + + if (acpi_gbl_table_handler) { + status = AE_ALREADY_EXISTS; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_table_handler = handler; + acpi_gbl_table_handler_context = context; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_install_table_handler) + +/******************************************************************************* + * + * FUNCTION: acpi_remove_table_handler + * + * PARAMETERS: Handler - Table event handler that was installed + * previously. + * + * RETURN: Status + * + * DESCRIPTION: Remove table event handler + * + ******************************************************************************/ +acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_remove_table_handler); + + status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Make sure that the installed handler is the same */ + + if (!handler || handler != acpi_gbl_table_handler) { + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Remove the handler */ + + acpi_gbl_table_handler = NULL; + + cleanup: + (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) + + static int __init acpi_no_auto_ssdt_setup(char *s) { printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 630c9a2c5b7bd78887c4eab62924fcde075925b8..44425433075a72d72c2ff2f3d745b6d3e2f31ac1 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c @@ -675,12 +675,13 @@ void acpi_ut_init_globals(void) acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; - /* Global notify handlers */ + /* Global handlers */ acpi_gbl_system_notify.handler = NULL; acpi_gbl_device_notify.handler = NULL; acpi_gbl_exception_handler = NULL; acpi_gbl_init_handler = NULL; + acpi_gbl_table_handler = NULL; /* Global Lock support */ diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h index 75c354f7a0240cac82bb63b1239156302950cda7..67d152e7fa4443c307922afa1d7483748a6b1402 100644 --- a/include/acpi/acdisasm.h +++ b/include/acpi/acdisasm.h @@ -104,12 +104,12 @@ typedef const struct acpi_dmtable_info { #define ACPI_DMT_SIG 27 typedef -void (*ACPI_TABLE_HANDLER) (struct acpi_table_header * table); +void (*acpi_dmtable_handler) (struct acpi_table_header * table); struct acpi_dmtable_data { char *signature; struct acpi_dmtable_info *table_info; - ACPI_TABLE_HANDLER table_handler; + acpi_dmtable_handler table_handler; char *name; }; diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h index 44e718ee15797c4d8ff929a5e3b88cdecc75e517..862468616217bdf3b124bd429e35cabcf7a0f008 100644 --- a/include/acpi/acglobal.h +++ b/include/acpi/acglobal.h @@ -217,6 +217,8 @@ ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify; ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; +ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; +ACPI_EXTERN void *acpi_gbl_table_handler_context; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; /* Owner ID support */ diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index d970f7f99549639183b73d8324043c2805020dd5..c92acda1a77fbdc38bbb56b744d617e30bdf363d 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -119,6 +119,11 @@ acpi_status acpi_get_table_by_index(acpi_native_uint table_index, struct acpi_table_header **out_table); +acpi_status +acpi_install_table_handler(acpi_tbl_handler handler, void *context); + +acpi_status acpi_remove_table_handler(acpi_tbl_handler handler); + /* * Namespace and name interfaces */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 6182b57590ef03dedfc029f447b36912ab9c96a7..766178c6cc816d199569ce2b23e0570d7cfbd5c0 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -730,6 +730,12 @@ struct acpi_system_info { u32 debug_layer; }; +/* Table Event Types */ + +#define ACPI_TABLE_EVENT_LOAD 0x0 +#define ACPI_TABLE_EVENT_UNLOAD 0x1 +#define ACPI_NUM_TABLE_EVENTS 2 + /* * Types specific to the OS service interfaces */ @@ -759,6 +765,11 @@ acpi_status(*acpi_exception_handler) (acpi_status aml_status, u16 opcode, u32 aml_offset, void *context); +/* Table Event handler (Load, load_table etc) and types */ + +typedef +acpi_status(*acpi_tbl_handler) (u32 event, void *table, void *context); + /* Address Spaces (For Operation Regions) */ typedef