summaryrefslogtreecommitdiff
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-02-24 00:52:08 +0100
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-24 14:25:23 -0800
commitcbbc0de700e61d0cdc854d435dbc2ef148de0e00 (patch)
tree9a645bbdab91e1a00446680a95f2b86e741e0de4 /drivers/acpi/ec.c
parent7bc5e3f2be32ae6fb0c74cd0f707f986b3a01a26 (diff)
downloadlinux-rpi-cbbc0de700e61d0cdc854d435dbc2ef148de0e00.tar.gz
linux-rpi-cbbc0de700e61d0cdc854d435dbc2ef148de0e00.tar.bz2
linux-rpi-cbbc0de700e61d0cdc854d435dbc2ef148de0e00.zip
ACPI: Use GPE reference counting to support shared GPEs
To fix a bug and address the reviewers' comments regarding the ACPI GPE refcounting patch, do the following additional changes: o Remove the second argument of acpi_ev_enable_gpe(), 'write_to_hardware', because it is not necessary any more. o Add the "bad parameter" test against 'type' in acpi_enable_gpe() and acpi_disable_gpe(). o Make acpi_enable_gpe() only check 'status' for runtime GPEs if acpi_ev_enable_gpe() was actually called. o Make acpi_disable_gpe() return 'status' returned by acpi_ev_disable_gpe() and fix a bug where ACPI_GPE_TYPE_WAKE and ACPI_GPE_TYPE_RUNTIME were exchanged by mistake. o Add comments explaining why acpi_set_gpe() is used by the ACPI EC driver. 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, 11 insertions, 3 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 0fa65a8210da..27e0b92b2e39 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -307,6 +307,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
pr_debug(PREFIX "transaction start\n");
/* disable GPE during transaction if storm is detected */
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
+ /*
+ * It has to be disabled at the hardware level regardless of the
+ * GPE reference counting, so that it doesn't trigger.
+ */
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
}
@@ -316,7 +320,11 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
ec_check_sci_sync(ec, acpi_ec_read_status(ec));
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
msleep(1);
- /* it is safe to enable GPE outside of transaction */
+ /*
+ * It is safe to enable the GPE outside of the transaction. Use
+ * acpi_set_gpe() for that, since we used it to disable the GPE
+ * above.
+ */
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
pr_info(PREFIX "GPE storm detected, "
@@ -1059,7 +1067,7 @@ error:
static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
{
struct acpi_ec *ec = acpi_driver_data(device);
- /* Stop using GPE */
+ /* Stop using the GPE, but keep it reference counted. */
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
return 0;
}
@@ -1067,7 +1075,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
static int acpi_ec_resume(struct acpi_device *device)
{
struct acpi_ec *ec = acpi_driver_data(device);
- /* Enable use of GPE back */
+ /* Enable the GPE again, but don't reference count it once more. */
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
return 0;
}