aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-02-17 17:41:07 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-22 19:20:45 -0500
commit9630bdd9b15d2f489c646d8bc04b60e53eb5ec78 (patch)
treeed99f729cb9142492e0cdf2f7d19f2f33069a3f4 /drivers/acpi/ec.c
parentc39fae1416d59fd565606793f090cebe3720d50d (diff)
ACPI: Use GPE reference counting to support shared GPEs
ACPI GPEs may map to multiple devices. The current GPE interface only provides a mechanism for enabling and disabling GPEs, making it difficult to change the state of GPEs at runtime without extensive cooperation between devices. Add an API to allow devices to indicate whether or not they want their device's GPE to be enabled for both runtime and wakeup events. Remove the old GPE type handling entirely, which gets rid of various quirks, like the implicit disabling with GPE type setting. This requires a small amount of rework in order to ensure that non-wake GPEs are enabled by default to preserve existing behaviour. Based on patches from Matthew Garrett <mjg@redhat.com>. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index d6471bb6852f..0fa65a8210da 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -307,7 +307,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
307 pr_debug(PREFIX "transaction start\n"); 307 pr_debug(PREFIX "transaction start\n");
308 /* disable GPE during transaction if storm is detected */ 308 /* disable GPE during transaction if storm is detected */
309 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { 309 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
310 acpi_disable_gpe(NULL, ec->gpe); 310 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
311 } 311 }
312 312
313 status = acpi_ec_transaction_unlocked(ec, t); 313 status = acpi_ec_transaction_unlocked(ec, t);
@@ -317,7 +317,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
317 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { 317 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
318 msleep(1); 318 msleep(1);
319 /* it is safe to enable GPE outside of transaction */ 319 /* it is safe to enable GPE outside of transaction */
320 acpi_enable_gpe(NULL, ec->gpe); 320 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
321 } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { 321 } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
322 pr_info(PREFIX "GPE storm detected, " 322 pr_info(PREFIX "GPE storm detected, "
323 "transactions will use polling mode\n"); 323 "transactions will use polling mode\n");
@@ -788,8 +788,8 @@ static int ec_install_handlers(struct acpi_ec *ec)
788 &acpi_ec_gpe_handler, ec); 788 &acpi_ec_gpe_handler, ec);
789 if (ACPI_FAILURE(status)) 789 if (ACPI_FAILURE(status))
790 return -ENODEV; 790 return -ENODEV;
791 acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); 791
792 acpi_enable_gpe(NULL, ec->gpe); 792 acpi_enable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
793 status = acpi_install_address_space_handler(ec->handle, 793 status = acpi_install_address_space_handler(ec->handle,
794 ACPI_ADR_SPACE_EC, 794 ACPI_ADR_SPACE_EC,
795 &acpi_ec_space_handler, 795 &acpi_ec_space_handler,
@@ -806,6 +806,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
806 } else { 806 } else {
807 acpi_remove_gpe_handler(NULL, ec->gpe, 807 acpi_remove_gpe_handler(NULL, ec->gpe,
808 &acpi_ec_gpe_handler); 808 &acpi_ec_gpe_handler);
809 acpi_disable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
809 return -ENODEV; 810 return -ENODEV;
810 } 811 }
811 } 812 }
@@ -816,6 +817,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
816 817
817static void ec_remove_handlers(struct acpi_ec *ec) 818static void ec_remove_handlers(struct acpi_ec *ec)
818{ 819{
820 acpi_disable_gpe(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
819 if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, 821 if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
820 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) 822 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
821 pr_err(PREFIX "failed to remove space handler\n"); 823 pr_err(PREFIX "failed to remove space handler\n");
@@ -1058,7 +1060,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
1058{ 1060{
1059 struct acpi_ec *ec = acpi_driver_data(device); 1061 struct acpi_ec *ec = acpi_driver_data(device);
1060 /* Stop using GPE */ 1062 /* Stop using GPE */
1061 acpi_disable_gpe(NULL, ec->gpe); 1063 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
1062 return 0; 1064 return 0;
1063} 1065}
1064 1066
@@ -1066,7 +1068,7 @@ static int acpi_ec_resume(struct acpi_device *device)
1066{ 1068{
1067 struct acpi_ec *ec = acpi_driver_data(device); 1069 struct acpi_ec *ec = acpi_driver_data(device);
1068 /* Enable use of GPE back */ 1070 /* Enable use of GPE back */
1069 acpi_enable_gpe(NULL, ec->gpe); 1071 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
1070 return 0; 1072 return 0;
1071} 1073}
1072 1074