Subject: [PATCH] [acpi driver events] Add support for fixed events in core - Check for fixed events on acpi_device_event_{add,remove}() - Install generic fixed event handler that passes event down to driver's notify handler - Create {install,remove}_notify() helpers to ease in installing and removing handlers with fixed event (and its error handling). Signed-off-by: Patrick Mochel --- drivers/acpi/drivers/core/event.c | 87 ++++++++++++++++++++++++++++++++----- 1 files changed, 76 insertions(+), 11 deletions(-) applies-to: 45767c969587d1b7ba3e3d62b800b20a7e5f804c f93e01828dbafafdf95b71283fd3de67621f7f91 diff --git a/drivers/acpi/drivers/core/event.c b/drivers/acpi/drivers/core/event.c index acc4eb6..c5a7686 100644 --- a/drivers/acpi/drivers/core/event.c +++ b/drivers/acpi/drivers/core/event.c @@ -7,6 +7,54 @@ #include "core.h" +static int install_notify(struct acpi_dev * ad, struct acpi_device_event * e) +{ + acpi_status status; + + status = acpi_install_notify_handler(ad->acpi_device->handle, + e->e_type, + e->e_handler, + ad); + return ACPI_SUCCESS(status) ? 0 : -EIO; +} + +static void remove_notify(struct acpi_dev * ad, struct acpi_device_event * e) +{ + acpi_remove_notify_handler(ad->acpi_device->handle, + e->e_type, e->e_handler); +} + + +static acpi_status notify_fixed(void * data) +{ + struct acpi_dev * ad = data; + struct acpi_device_driver * drv = to_acpi_driver(ad->dev.driver); + struct acpi_device_event * e = drv->d_event; + + ACPI_FUNCTION_TRACE(__FUNCTION__); + + e->e_handler(ad->acpi_device->handle, + e->e_fixed_event, ad); + + return_ACPI_STATUS(AE_OK); +} + +static int install_fixed(struct acpi_dev * ad, u32 event) +{ + acpi_status status; + + status = acpi_install_fixed_event_handler(event, + notify_fixed, + ad); + return ACPI_SUCCESS(status) ? 0 : -EIO; +} + + +static void remove_fixed(struct acpi_dev * ad, u32 event) +{ + acpi_remove_fixed_event_handler(event, notify_fixed); +} + /** * acpi_device_event_add - Register a driver's event handler @@ -26,20 +74,34 @@ int acpi_device_event_add(struct acpi_de struct acpi_device_driver * drv = to_acpi_driver(ad->dev.driver); struct acpi_device_event * e = drv->d_event; int ret = 0; + int i; if (e && e->e_handler) { - acpi_status status; - - status = acpi_install_notify_handler(ad->acpi_device->handle, - e->e_type, - e->e_handler, - ad); - if (ACPI_FAILURE(status)) { - err("Installing notify handler failed for [%s] [%s]", + ret = install_notify(ad, e); + if (ret) { + err("Install notify handler failed [%s] [%s]", drv->d_drv.name, ad->dev.bus_id); - ret = -EIO; + return -EIO; + } + for (i = 0; i < e->e_num_fixed; i++) { + ret = install_fixed(ad, e->e_fixed[i]); + if (ret) { + err("Install fixed handler failed [%s] [%s]", + drv->d_drv.name, ad->dev.bus_id); + goto FixedFailed; + } } } + return 0; + + FixedFailed: + /* + * Installing a fixed event handler failed. + * Remove the events that we've already installed. + */ + while (--i > 0) + remove_fixed(ad, e->e_fixed[i]); + remove_notify(ad, e); return ret; } @@ -54,9 +116,12 @@ void acpi_device_event_remove(struct acp { struct acpi_device_driver * drv = to_acpi_driver(ad->dev.driver); struct acpi_device_event * e = drv->d_event; + int i; if (e && e->e_handler) { - acpi_remove_notify_handler(ad->acpi_device->handle, - e->e_type, e->e_handler); + remove_notify(ad, e); + + for (i = 0; i < e->e_num_fixed; i++) + remove_fixed(ad, e->e_fixed[i]); } } --- 0.99.9.GIT