aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2015-01-14 06:28:28 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-01-23 16:06:48 -0500
commit01305d4139cd345aa9f64cecfd7fc7b237e1444e (patch)
tree1e86972559a9927f8fbbbcfba8f0c497ab1cb922
parent0c78808f51d11564a29728091e87b80d6e54d499 (diff)
ACPI / EC: Add reference counting for query handlers
This patch adds reference counting for query handlers in order to eliminate kmalloc()/kfree() usage. Signed-off-by: Lv Zheng <lv.zheng@intel.com> Tested-by: Steffen Weber <steffen.weber@gmail.com> Tested-by: Ortwin Glück <odi@odi.ch> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/ec.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 3e19123bb183..87b9911c9039 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -105,6 +105,7 @@ struct acpi_ec_query_handler {
105 acpi_handle handle; 105 acpi_handle handle;
106 void *data; 106 void *data;
107 u8 query_bit; 107 u8 query_bit;
108 struct kref kref;
108}; 109};
109 110
110struct transaction { 111struct transaction {
@@ -580,6 +581,27 @@ static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data)
580/* -------------------------------------------------------------------------- 581/* --------------------------------------------------------------------------
581 Event Management 582 Event Management
582 -------------------------------------------------------------------------- */ 583 -------------------------------------------------------------------------- */
584static struct acpi_ec_query_handler *
585acpi_ec_get_query_handler(struct acpi_ec_query_handler *handler)
586{
587 if (handler)
588 kref_get(&handler->kref);
589 return handler;
590}
591
592static void acpi_ec_query_handler_release(struct kref *kref)
593{
594 struct acpi_ec_query_handler *handler =
595 container_of(kref, struct acpi_ec_query_handler, kref);
596
597 kfree(handler);
598}
599
600static void acpi_ec_put_query_handler(struct acpi_ec_query_handler *handler)
601{
602 kref_put(&handler->kref, acpi_ec_query_handler_release);
603}
604
583int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, 605int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
584 acpi_handle handle, acpi_ec_query_func func, 606 acpi_handle handle, acpi_ec_query_func func,
585 void *data) 607 void *data)
@@ -595,6 +617,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
595 handler->func = func; 617 handler->func = func;
596 handler->data = data; 618 handler->data = data;
597 mutex_lock(&ec->mutex); 619 mutex_lock(&ec->mutex);
620 kref_init(&handler->kref);
598 list_add(&handler->node, &ec->list); 621 list_add(&handler->node, &ec->list);
599 mutex_unlock(&ec->mutex); 622 mutex_unlock(&ec->mutex);
600 return 0; 623 return 0;
@@ -604,15 +627,18 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
604void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) 627void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
605{ 628{
606 struct acpi_ec_query_handler *handler, *tmp; 629 struct acpi_ec_query_handler *handler, *tmp;
630 LIST_HEAD(free_list);
607 631
608 mutex_lock(&ec->mutex); 632 mutex_lock(&ec->mutex);
609 list_for_each_entry_safe(handler, tmp, &ec->list, node) { 633 list_for_each_entry_safe(handler, tmp, &ec->list, node) {
610 if (query_bit == handler->query_bit) { 634 if (query_bit == handler->query_bit) {
611 list_del(&handler->node); 635 list_del_init(&handler->node);
612 kfree(handler); 636 list_add(&handler->node, &free_list);
613 } 637 }
614 } 638 }
615 mutex_unlock(&ec->mutex); 639 mutex_unlock(&ec->mutex);
640 list_for_each_entry(handler, &free_list, node)
641 acpi_ec_put_query_handler(handler);
616} 642}
617EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); 643EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
618 644
@@ -628,14 +654,14 @@ static void acpi_ec_run(void *cxt)
628 else if (handler->handle) 654 else if (handler->handle)
629 acpi_evaluate_object(handler->handle, NULL, NULL, NULL); 655 acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
630 pr_debug("##### Query(0x%02x) stopped #####\n", handler->query_bit); 656 pr_debug("##### Query(0x%02x) stopped #####\n", handler->query_bit);
631 kfree(handler); 657 acpi_ec_put_query_handler(handler);
632} 658}
633 659
634static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data) 660static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
635{ 661{
636 u8 value = 0; 662 u8 value = 0;
637 int status; 663 int status;
638 struct acpi_ec_query_handler *handler, *copy; 664 struct acpi_ec_query_handler *handler;
639 665
640 status = acpi_ec_query_unlocked(ec, &value); 666 status = acpi_ec_query_unlocked(ec, &value);
641 if (data) 667 if (data)
@@ -646,15 +672,12 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
646 list_for_each_entry(handler, &ec->list, node) { 672 list_for_each_entry(handler, &ec->list, node) {
647 if (value == handler->query_bit) { 673 if (value == handler->query_bit) {
648 /* have custom handler for this bit */ 674 /* have custom handler for this bit */
649 copy = kmalloc(sizeof(*handler), GFP_KERNEL); 675 handler = acpi_ec_get_query_handler(handler);
650 if (!copy)
651 return -ENOMEM;
652 memcpy(copy, handler, sizeof(*copy));
653 pr_debug("##### Query(0x%02x) scheduled #####\n", 676 pr_debug("##### Query(0x%02x) scheduled #####\n",
654 handler->query_bit); 677 handler->query_bit);
655 return acpi_os_execute((copy->func) ? 678 return acpi_os_execute((handler->func) ?
656 OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, 679 OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
657 acpi_ec_run, copy); 680 acpi_ec_run, handler);
658 } 681 }
659 } 682 }
660 return 0; 683 return 0;