diff options
author | Alexey Starikovskiy <astarikivskiy@suse.de> | 2007-08-03 17:57:53 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-08-03 17:57:53 -0400 |
commit | 7c010de7506954e973abfab5c5999c5a97f7a73e (patch) | |
tree | bfb188b086c2a912936883d47b0756f8755cbdef /drivers | |
parent | 52fe4bdf40bc07498c5f7935551774e8f8458190 (diff) |
ACPI: EC: Switch from boot_ec as soon as we find its desc in DSDT.
Some ASUS laptops fail to use boot time EC
and need to eventually switch to one described in DSDT.
http://bugzilla.kernel.org/show_bug.cgi?id=8709
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/ec.c | 45 |
1 files changed, 16 insertions, 29 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 629289034b61..71caa7d983a3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -679,6 +679,14 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | |||
679 | return AE_CTRL_TERMINATE; | 679 | return AE_CTRL_TERMINATE; |
680 | } | 680 | } |
681 | 681 | ||
682 | static 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); | ||
688 | } | ||
689 | |||
682 | static int acpi_ec_add(struct acpi_device *device) | 690 | static int acpi_ec_add(struct acpi_device *device) |
683 | { | 691 | { |
684 | struct acpi_ec *ec = NULL; | 692 | struct acpi_ec *ec = NULL; |
@@ -702,16 +710,15 @@ static int acpi_ec_add(struct acpi_device *device) | |||
702 | /* Check if we found the boot EC */ | 710 | /* Check if we found the boot EC */ |
703 | if (boot_ec) { | 711 | if (boot_ec) { |
704 | if (boot_ec->gpe == ec->gpe) { | 712 | if (boot_ec->gpe == ec->gpe) { |
705 | /* We might have incorrect info for GL at boot time */ | ||
706 | mutex_lock(&boot_ec->lock); | 713 | mutex_lock(&boot_ec->lock); |
707 | boot_ec->global_lock = ec->global_lock; | 714 | ec_remove_handlers(boot_ec); |
708 | /* Copy handlers from new ec into boot ec */ | ||
709 | list_splice(&ec->list, &boot_ec->list); | ||
710 | mutex_unlock(&boot_ec->lock); | 715 | mutex_unlock(&boot_ec->lock); |
711 | kfree(ec); | 716 | mutex_destroy(&boot_ec->lock); |
712 | ec = boot_ec; | 717 | kfree(boot_ec); |
718 | first_ec = boot_ec = NULL; | ||
713 | } | 719 | } |
714 | } else | 720 | } |
721 | if (!first_ec) | ||
715 | first_ec = ec; | 722 | first_ec = ec; |
716 | ec->handle = device->handle; | 723 | ec->handle = device->handle; |
717 | acpi_driver_data(device) = ec; | 724 | acpi_driver_data(device) = ec; |
@@ -740,9 +747,6 @@ static int acpi_ec_remove(struct acpi_device *device, int type) | |||
740 | if (ec == first_ec) | 747 | if (ec == first_ec) |
741 | first_ec = NULL; | 748 | first_ec = NULL; |
742 | 749 | ||
743 | /* Don't touch boot EC */ | ||
744 | if (boot_ec != ec) | ||
745 | kfree(ec); | ||
746 | return 0; | 750 | return 0; |
747 | } | 751 | } |
748 | 752 | ||
@@ -806,9 +810,7 @@ static int acpi_ec_start(struct acpi_device *device) | |||
806 | if (!ec) | 810 | if (!ec) |
807 | return -EINVAL; | 811 | return -EINVAL; |
808 | 812 | ||
809 | /* Boot EC is already working */ | 813 | ret = ec_install_handlers(ec); |
810 | if (ec != boot_ec) | ||
811 | ret = ec_install_handlers(ec); | ||
812 | 814 | ||
813 | /* EC is fully operational, allow queries */ | 815 | /* EC is fully operational, allow queries */ |
814 | atomic_set(&ec->query_pending, 0); | 816 | atomic_set(&ec->query_pending, 0); |
@@ -818,7 +820,6 @@ static int acpi_ec_start(struct acpi_device *device) | |||
818 | 820 | ||
819 | static int acpi_ec_stop(struct acpi_device *device, int type) | 821 | static int acpi_ec_stop(struct acpi_device *device, int type) |
820 | { | 822 | { |
821 | acpi_status status; | ||
822 | struct acpi_ec *ec; | 823 | struct acpi_ec *ec; |
823 | 824 | ||
824 | if (!device) | 825 | if (!device) |
@@ -827,21 +828,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type) | |||
827 | ec = acpi_driver_data(device); | 828 | ec = acpi_driver_data(device); |
828 | if (!ec) | 829 | if (!ec) |
829 | return -EINVAL; | 830 | return -EINVAL; |
830 | 831 | ec_remove_handlers(ec); | |
831 | /* Don't touch boot EC */ | ||
832 | if (ec == boot_ec) | ||
833 | return 0; | ||
834 | |||
835 | status = acpi_remove_address_space_handler(ec->handle, | ||
836 | ACPI_ADR_SPACE_EC, | ||
837 | &acpi_ec_space_handler); | ||
838 | if (ACPI_FAILURE(status)) | ||
839 | return -ENODEV; | ||
840 | |||
841 | status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); | ||
842 | if (ACPI_FAILURE(status)) | ||
843 | return -ENODEV; | ||
844 | |||
845 | return 0; | 832 | return 0; |
846 | } | 833 | } |
847 | 834 | ||