From e7fe5496087031c6e814e6672490fb8ace863f52 Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Fri, 17 Feb 2023 18:33:09 +0100 Subject: [PATCH 1/3] ACPI: EC: Add query notifier support Allow external drivers to register notifiers to act on query events and possibly override the query handler. Use the existing notifier infrastructure for this to ensure correct locking. Signed-off-by: Armin Wolf --- drivers/acpi/ec.c | 28 ++++++++++++++++++++++++---- drivers/acpi/internal.h | 5 +++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 105d2e795afa..dc7860a825a0 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -184,6 +185,8 @@ static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */ static int EC_FLAGS_TRUST_DSDT_GPE; /* Needs DSDT GPE as correction setting */ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ +static BLOCKING_NOTIFIER_HEAD(acpi_ec_chain_head); + /* -------------------------------------------------------------------------- * Logging/Debugging * -------------------------------------------------------------------------- */ @@ -1125,18 +1128,35 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) } EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); +int register_acpi_ec_query_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&acpi_ec_chain_head, nb); +} +EXPORT_SYMBOL_GPL(register_acpi_ec_query_notifier); + +int unregister_acpi_ec_query_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&acpi_ec_chain_head, nb); +} +EXPORT_SYMBOL_GPL(unregister_acpi_ec_query_notifier); + static void acpi_ec_event_processor(struct work_struct *work) { struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work); struct acpi_ec_query_handler *handler = q->handler; struct acpi_ec *ec = q->ec; + int ret; ec_dbg_evt("Query(0x%02x) started", handler->query_bit); - if (handler->func) - handler->func(handler->data); - else if (handler->handle) - acpi_evaluate_object(handler->handle, NULL, NULL, NULL); + /* Allow notifier handlers to override query handlers */ + ret = blocking_notifier_call_chain(&acpi_ec_chain_head, handler->query_bit, ec); + if (ret != NOTIFY_BAD) { + if (handler->func) + handler->func(handler->data); + else if (handler->handle) + acpi_evaluate_object(handler->handle, NULL, NULL, NULL); + } ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index ec584442fb29..6f41d42375ab 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -11,6 +11,8 @@ #include +struct notifier_block; + int early_acpi_osi_init(void); int acpi_osi_init(void); acpi_status acpi_os_initialize1(void); @@ -212,6 +214,9 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, void *data); void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); +int register_acpi_ec_query_notifier(struct notifier_block *nb); +int unregister_acpi_ec_query_notifier(struct notifier_block *nb); + #ifdef CONFIG_PM_SLEEP void acpi_ec_flush_work(void); bool acpi_ec_dispatch_gpe(void); -- 2.30.2