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.c93
1 files changed, 40 insertions, 53 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 3f7935ab0cf5..7b4178393e34 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -121,6 +121,7 @@ static struct acpi_ec {
121 atomic_t event_count; 121 atomic_t event_count;
122 wait_queue_head_t wait; 122 wait_queue_head_t wait;
123 struct list_head list; 123 struct list_head list;
124 u8 handlers_installed;
124} *boot_ec, *first_ec; 125} *boot_ec, *first_ec;
125 126
126/* -------------------------------------------------------------------------- 127/* --------------------------------------------------------------------------
@@ -425,7 +426,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
425 handler->func = func; 426 handler->func = func;
426 handler->data = data; 427 handler->data = data;
427 mutex_lock(&ec->lock); 428 mutex_lock(&ec->lock);
428 list_add_tail(&handler->node, &ec->list); 429 list_add(&handler->node, &ec->list);
429 mutex_unlock(&ec->lock); 430 mutex_unlock(&ec->lock);
430 return 0; 431 return 0;
431} 432}
@@ -440,7 +441,6 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
440 if (query_bit == handler->query_bit) { 441 if (query_bit == handler->query_bit) {
441 list_del(&handler->node); 442 list_del(&handler->node);
442 kfree(handler); 443 kfree(handler);
443 break;
444 } 444 }
445 } 445 }
446 mutex_unlock(&ec->lock); 446 mutex_unlock(&ec->lock);
@@ -680,32 +680,50 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
680 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); 680 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
681 if (ACPI_FAILURE(status)) 681 if (ACPI_FAILURE(status))
682 return status; 682 return status;
683
684 /* Find and register all query methods */ 683 /* Find and register all query methods */
685 acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, 684 acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
686 acpi_ec_register_query_methods, ec, NULL); 685 acpi_ec_register_query_methods, ec, NULL);
687
688 /* Use the global lock for all EC transactions? */ 686 /* Use the global lock for all EC transactions? */
689 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); 687 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
690
691 ec->handle = handle; 688 ec->handle = handle;
692
693 printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
694 ec->gpe, ec->command_addr, ec->data_addr);
695
696 return AE_CTRL_TERMINATE; 689 return AE_CTRL_TERMINATE;
697} 690}
698 691
692static void ec_remove_handlers(struct acpi_ec *ec)
693{
694 if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
695 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
696 printk(KERN_ERR PREFIX "failed to remove space handler\n");
697 if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
698 &acpi_ec_gpe_handler)))
699 printk(KERN_ERR PREFIX "failed to remove gpe handler\n");
700 ec->handlers_installed = 0;
701}
702
699static int acpi_ec_add(struct acpi_device *device) 703static int acpi_ec_add(struct acpi_device *device)
700{ 704{
701 struct acpi_ec *ec = NULL; 705 struct acpi_ec *ec = NULL;
702 706
703 if (!device) 707 if (!device)
704 return -EINVAL; 708 return -EINVAL;
705
706 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); 709 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
707 strcpy(acpi_device_class(device), ACPI_EC_CLASS); 710 strcpy(acpi_device_class(device), ACPI_EC_CLASS);
708 711
712 /* Check for boot EC */
713 if (boot_ec) {
714 if (boot_ec->handle == device->handle) {
715 /* Pre-loaded EC from DSDT, just move pointer */
716 ec = boot_ec;
717 boot_ec = NULL;
718 goto end;
719 } else if (boot_ec->handle == ACPI_ROOT_OBJECT) {
720 /* ECDT-based EC, time to shut it down */
721 ec_remove_handlers(boot_ec);
722 kfree(boot_ec);
723 first_ec = boot_ec = NULL;
724 }
725 }
726
709 ec = make_acpi_ec(); 727 ec = make_acpi_ec();
710 if (!ec) 728 if (!ec)
711 return -ENOMEM; 729 return -ENOMEM;
@@ -715,25 +733,14 @@ static int acpi_ec_add(struct acpi_device *device)
715 kfree(ec); 733 kfree(ec);
716 return -EINVAL; 734 return -EINVAL;
717 } 735 }
718
719 /* Check if we found the boot EC */
720 if (boot_ec) {
721 if (boot_ec->gpe == ec->gpe) {
722 /* We might have incorrect info for GL at boot time */
723 mutex_lock(&boot_ec->lock);
724 boot_ec->global_lock = ec->global_lock;
725 /* Copy handlers from new ec into boot ec */
726 list_splice(&ec->list, &boot_ec->list);
727 mutex_unlock(&boot_ec->lock);
728 kfree(ec);
729 ec = boot_ec;
730 }
731 } else
732 first_ec = ec;
733 ec->handle = device->handle; 736 ec->handle = device->handle;
737 end:
738 if (!first_ec)
739 first_ec = ec;
734 acpi_driver_data(device) = ec; 740 acpi_driver_data(device) = ec;
735
736 acpi_ec_add_fs(device); 741 acpi_ec_add_fs(device);
742 printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
743 ec->gpe, ec->command_addr, ec->data_addr);
737 return 0; 744 return 0;
738} 745}
739 746
@@ -756,10 +763,7 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
756 acpi_driver_data(device) = NULL; 763 acpi_driver_data(device) = NULL;
757 if (ec == first_ec) 764 if (ec == first_ec)
758 first_ec = NULL; 765 first_ec = NULL;
759 766 kfree(ec);
760 /* Don't touch boot EC */
761 if (boot_ec != ec)
762 kfree(ec);
763 return 0; 767 return 0;
764} 768}
765 769
@@ -789,6 +793,8 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
789static int ec_install_handlers(struct acpi_ec *ec) 793static int ec_install_handlers(struct acpi_ec *ec)
790{ 794{
791 acpi_status status; 795 acpi_status status;
796 if (ec->handlers_installed)
797 return 0;
792 status = acpi_install_gpe_handler(NULL, ec->gpe, 798 status = acpi_install_gpe_handler(NULL, ec->gpe,
793 ACPI_GPE_EDGE_TRIGGERED, 799 ACPI_GPE_EDGE_TRIGGERED,
794 &acpi_ec_gpe_handler, ec); 800 &acpi_ec_gpe_handler, ec);
@@ -807,6 +813,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
807 return -ENODEV; 813 return -ENODEV;
808 } 814 }
809 815
816 ec->handlers_installed = 1;
810 return 0; 817 return 0;
811} 818}
812 819
@@ -823,41 +830,22 @@ static int acpi_ec_start(struct acpi_device *device)
823 if (!ec) 830 if (!ec)
824 return -EINVAL; 831 return -EINVAL;
825 832
826 /* Boot EC is already working */ 833 ret = ec_install_handlers(ec);
827 if (ec != boot_ec)
828 ret = ec_install_handlers(ec);
829 834
830 /* EC is fully operational, allow queries */ 835 /* EC is fully operational, allow queries */
831 atomic_set(&ec->query_pending, 0); 836 atomic_set(&ec->query_pending, 0);
832
833 return ret; 837 return ret;
834} 838}
835 839
836static int acpi_ec_stop(struct acpi_device *device, int type) 840static int acpi_ec_stop(struct acpi_device *device, int type)
837{ 841{
838 acpi_status status;
839 struct acpi_ec *ec; 842 struct acpi_ec *ec;
840
841 if (!device) 843 if (!device)
842 return -EINVAL; 844 return -EINVAL;
843
844 ec = acpi_driver_data(device); 845 ec = acpi_driver_data(device);
845 if (!ec) 846 if (!ec)
846 return -EINVAL; 847 return -EINVAL;
847 848 ec_remove_handlers(ec);
848 /* Don't touch boot EC */
849 if (ec == boot_ec)
850 return 0;
851
852 status = acpi_remove_address_space_handler(ec->handle,
853 ACPI_ADR_SPACE_EC,
854 &acpi_ec_space_handler);
855 if (ACPI_FAILURE(status))
856 return -ENODEV;
857
858 status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
859 if (ACPI_FAILURE(status))
860 return -ENODEV;
861 849
862 return 0; 850 return 0;
863} 851}
@@ -877,7 +865,7 @@ int __init acpi_ec_ecdt_probe(void)
877 status = acpi_get_table(ACPI_SIG_ECDT, 1, 865 status = acpi_get_table(ACPI_SIG_ECDT, 1,
878 (struct acpi_table_header **)&ecdt_ptr); 866 (struct acpi_table_header **)&ecdt_ptr);
879 if (ACPI_SUCCESS(status)) { 867 if (ACPI_SUCCESS(status)) {
880 printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n\n"); 868 printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");
881 boot_ec->command_addr = ecdt_ptr->control.address; 869 boot_ec->command_addr = ecdt_ptr->control.address;
882 boot_ec->data_addr = ecdt_ptr->data.address; 870 boot_ec->data_addr = ecdt_ptr->data.address;
883 boot_ec->gpe = ecdt_ptr->gpe; 871 boot_ec->gpe = ecdt_ptr->gpe;
@@ -899,7 +887,6 @@ int __init acpi_ec_ecdt_probe(void)
899 error: 887 error:
900 kfree(boot_ec); 888 kfree(boot_ec);
901 boot_ec = NULL; 889 boot_ec = NULL;
902
903 return -ENODEV; 890 return -ENODEV;
904} 891}
905 892