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