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 | |
| 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>
| -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 | ||
