diff options
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r-- | drivers/acpi/ec.c | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 928899ab9502..660834a49c1f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -662,21 +662,6 @@ static void advance_transaction(struct acpi_ec *ec, bool interrupt) ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id()); - /* - * Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1 - * changes to always trigger a GPE interrupt. - * - * GPE STS is a W1C register, which means: - * - * 1. Software can clear it without worrying about clearing the other - * GPEs' STS bits when the hardware sets them in parallel. - * - * 2. As long as software can ensure only clearing it when it is set, - * hardware won't set it in parallel. - */ - if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec)) - acpi_clear_gpe(NULL, ec->gpe); - status = acpi_ec_read_status(ec); /* @@ -1282,12 +1267,34 @@ static void acpi_ec_event_handler(struct work_struct *work) spin_unlock_irq(&ec->lock); } +static void clear_gpe_and_advance_transaction(struct acpi_ec *ec, bool interrupt) +{ + /* + * Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1 + * changes to always trigger a GPE interrupt. + * + * GPE STS is a W1C register, which means: + * + * 1. Software can clear it without worrying about clearing the other + * GPEs' STS bits when the hardware sets them in parallel. + * + * 2. As long as software can ensure only clearing it when it is set, + * hardware won't set it in parallel. + */ + if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec)) + acpi_clear_gpe(NULL, ec->gpe); + + advance_transaction(ec, true); +} + static void acpi_ec_handle_interrupt(struct acpi_ec *ec) { unsigned long flags; spin_lock_irqsave(&ec->lock, flags); - advance_transaction(ec, true); + + clear_gpe_and_advance_transaction(ec, true); + spin_unlock_irqrestore(&ec->lock, flags); } @@ -2082,7 +2089,7 @@ bool acpi_ec_dispatch_gpe(void) if (acpi_ec_gpe_status_set(first_ec)) { pm_pr_dbg("ACPI EC GPE status set\n"); - advance_transaction(first_ec, false); + clear_gpe_and_advance_transaction(first_ec, false); work_in_progress = acpi_ec_work_in_progress(first_ec); } |