aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c106
1 files changed, 50 insertions, 56 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 469f3f57f881..56bee9e065cf 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -471,7 +471,6 @@ static void acpi_ec_gpe_query(void *ec_cxt)
471 } 471 }
472 } 472 }
473 mutex_unlock(&ec->lock); 473 mutex_unlock(&ec->lock);
474 printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value);
475} 474}
476 475
477static u32 acpi_ec_gpe_handler(void *data) 476static u32 acpi_ec_gpe_handler(void *data)
@@ -665,30 +664,44 @@ acpi_ec_register_query_methods(acpi_handle handle, u32 level,
665 return AE_OK; 664 return AE_OK;
666} 665}
667 666
668static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle) 667static acpi_status
668ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
669{ 669{
670 if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS, 670 acpi_status status;
671 ec_parse_io_ports, ec))) 671
672 return -EINVAL; 672 struct acpi_ec *ec = context;
673 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
674 ec_parse_io_ports, ec);
675 if (ACPI_FAILURE(status))
676 return status;
673 677
674 /* Get GPE bit assignment (EC events). */ 678 /* Get GPE bit assignment (EC events). */
675 /* TODO: Add support for _GPE returning a package */ 679 /* TODO: Add support for _GPE returning a package */
676 if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe))) 680 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
677 return -EINVAL; 681 if (ACPI_FAILURE(status))
678 682 return status;
679 /* Use the global lock for all EC transactions? */
680 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
681 683
682 /* Find and register all query methods */ 684 /* Find and register all query methods */
683 acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, 685 acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
684 acpi_ec_register_query_methods, ec, NULL); 686 acpi_ec_register_query_methods, ec, NULL);
685 687
688 /* Use the global lock for all EC transactions? */
689 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
690
686 ec->handle = handle; 691 ec->handle = handle;
687 692
688 printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx", 693 printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
689 ec->gpe, ec->command_addr, ec->data_addr); 694 ec->gpe, ec->command_addr, ec->data_addr);
690 695
691 return 0; 696 return AE_CTRL_TERMINATE;
697}
698
699static void ec_remove_handlers(struct acpi_ec *ec)
700{
701 acpi_remove_address_space_handler(ec->handle,
702 ACPI_ADR_SPACE_EC,
703 &acpi_ec_space_handler);
704 acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
692} 705}
693 706
694static int acpi_ec_add(struct acpi_device *device) 707static int acpi_ec_add(struct acpi_device *device)
@@ -705,7 +718,8 @@ static int acpi_ec_add(struct acpi_device *device)
705 if (!ec) 718 if (!ec)
706 return -ENOMEM; 719 return -ENOMEM;
707 720
708 if (ec_parse_device(ec, device->handle)) { 721 if (ec_parse_device(device->handle, 0, ec, NULL) !=
722 AE_CTRL_TERMINATE) {
709 kfree(ec); 723 kfree(ec);
710 return -EINVAL; 724 return -EINVAL;
711 } 725 }
@@ -713,16 +727,13 @@ static int acpi_ec_add(struct acpi_device *device)
713 /* Check if we found the boot EC */ 727 /* Check if we found the boot EC */
714 if (boot_ec) { 728 if (boot_ec) {
715 if (boot_ec->gpe == ec->gpe) { 729 if (boot_ec->gpe == ec->gpe) {
716 /* We might have incorrect info for GL at boot time */ 730 ec_remove_handlers(boot_ec);
717 mutex_lock(&boot_ec->lock); 731 mutex_destroy(&boot_ec->lock);
718 boot_ec->global_lock = ec->global_lock; 732 kfree(boot_ec);
719 /* Copy handlers from new ec into boot ec */ 733 first_ec = boot_ec = NULL;
720 list_splice(&ec->list, &boot_ec->list);
721 mutex_unlock(&boot_ec->lock);
722 kfree(ec);
723 ec = boot_ec;
724 } 734 }
725 } else 735 }
736 if (!first_ec)
726 first_ec = ec; 737 first_ec = ec;
727 ec->handle = device->handle; 738 ec->handle = device->handle;
728 acpi_driver_data(device) = ec; 739 acpi_driver_data(device) = ec;
@@ -734,14 +745,14 @@ static int acpi_ec_add(struct acpi_device *device)
734static int acpi_ec_remove(struct acpi_device *device, int type) 745static int acpi_ec_remove(struct acpi_device *device, int type)
735{ 746{
736 struct acpi_ec *ec; 747 struct acpi_ec *ec;
737 struct acpi_ec_query_handler *handler; 748 struct acpi_ec_query_handler *handler, *tmp;
738 749
739 if (!device) 750 if (!device)
740 return -EINVAL; 751 return -EINVAL;
741 752
742 ec = acpi_driver_data(device); 753 ec = acpi_driver_data(device);
743 mutex_lock(&ec->lock); 754 mutex_lock(&ec->lock);
744 list_for_each_entry(handler, &ec->list, node) { 755 list_for_each_entry_safe(handler, tmp, &ec->list, node) {
745 list_del(&handler->node); 756 list_del(&handler->node);
746 kfree(handler); 757 kfree(handler);
747 } 758 }
@@ -751,9 +762,6 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
751 if (ec == first_ec) 762 if (ec == first_ec)
752 first_ec = NULL; 763 first_ec = NULL;
753 764
754 /* Don't touch boot EC */
755 if (boot_ec != ec)
756 kfree(ec);
757 return 0; 765 return 0;
758} 766}
759 767
@@ -817,9 +825,7 @@ static int acpi_ec_start(struct acpi_device *device)
817 if (!ec) 825 if (!ec)
818 return -EINVAL; 826 return -EINVAL;
819 827
820 /* Boot EC is already working */ 828 ret = ec_install_handlers(ec);
821 if (ec != boot_ec)
822 ret = ec_install_handlers(ec);
823 829
824 /* EC is fully operational, allow queries */ 830 /* EC is fully operational, allow queries */
825 atomic_set(&ec->query_pending, 0); 831 atomic_set(&ec->query_pending, 0);
@@ -829,7 +835,6 @@ static int acpi_ec_start(struct acpi_device *device)
829 835
830static int acpi_ec_stop(struct acpi_device *device, int type) 836static int acpi_ec_stop(struct acpi_device *device, int type)
831{ 837{
832 acpi_status status;
833 struct acpi_ec *ec; 838 struct acpi_ec *ec;
834 839
835 if (!device) 840 if (!device)
@@ -838,21 +843,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
838 ec = acpi_driver_data(device); 843 ec = acpi_driver_data(device);
839 if (!ec) 844 if (!ec)
840 return -EINVAL; 845 return -EINVAL;
841 846 ec_remove_handlers(ec);
842 /* Don't touch boot EC */
843 if (ec == boot_ec)
844 return 0;
845
846 status = acpi_remove_address_space_handler(ec->handle,
847 ACPI_ADR_SPACE_EC,
848 &acpi_ec_space_handler);
849 if (ACPI_FAILURE(status))
850 return -ENODEV;
851
852 status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
853 if (ACPI_FAILURE(status))
854 return -ENODEV;
855
856 return 0; 847 return 0;
857} 848}
858 849
@@ -868,18 +859,21 @@ int __init acpi_ec_ecdt_probe(void)
868 /* 859 /*
869 * Generate a boot ec context 860 * Generate a boot ec context
870 */ 861 */
871
872 status = acpi_get_table(ACPI_SIG_ECDT, 1, 862 status = acpi_get_table(ACPI_SIG_ECDT, 1,
873 (struct acpi_table_header **)&ecdt_ptr); 863 (struct acpi_table_header **)&ecdt_ptr);
874 if (ACPI_FAILURE(status)) 864 if (ACPI_SUCCESS(status)) {
875 goto error; 865 printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n\n");
876 866 boot_ec->command_addr = ecdt_ptr->control.address;
877 printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); 867 boot_ec->data_addr = ecdt_ptr->data.address;
878 868 boot_ec->gpe = ecdt_ptr->gpe;
879 boot_ec->command_addr = ecdt_ptr->control.address; 869 boot_ec->handle = ACPI_ROOT_OBJECT;
880 boot_ec->data_addr = ecdt_ptr->data.address; 870 } else {
881 boot_ec->gpe = ecdt_ptr->gpe; 871 printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
882 boot_ec->handle = ACPI_ROOT_OBJECT; 872 status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
873 boot_ec, NULL);
874 if (ACPI_FAILURE(status))
875 goto error;
876 }
883 877
884 ret = ec_install_handlers(boot_ec); 878 ret = ec_install_handlers(boot_ec);
885 if (!ret) { 879 if (!ret) {