From cbbc0de700e61d0cdc854d435dbc2ef148de0e00 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 24 Feb 2010 00:52:08 +0100 Subject: 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 Signed-off-by: Jesse Barnes --- drivers/acpi/ec.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/acpi/ec.c') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 0fa65a8210d..27e0b92b2e3 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; } -- cgit v1.2.3