From: Rafael J. Wysocki Date: Thu, 27 Jul 2017 21:14:08 +0000 (+0200) Subject: Merge branches 'acpi-pm' and 'acpi-numa' X-Git-Tag: v4.13-rc3~19^2 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=f6248dd88dba3aeb19351410a027d92eee7ceb72;hp=02cb489be7ad07e74ab40baa908d2e20460ebdb2;p=karo-tx-linux.git Merge branches 'acpi-pm' and 'acpi-numa' * acpi-pm: ACPI / PM / EC: Flush all EC work in acpi_freeze_sync() ACPI / EC: Add parameter to force disable the GPE on suspend * acpi-numa: ACPI: NUMA: Fix typo in the full name of SRAT ACPI: NUMA: add missing include in acpi_numa.h --- diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ddb01e9fa5b2..62068a5e814f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -151,6 +151,10 @@ static bool ec_freeze_events __read_mostly = false; module_param(ec_freeze_events, bool, 0644); MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume"); +static bool ec_no_wakeup __read_mostly; +module_param(ec_no_wakeup, bool, 0644); +MODULE_PARM_DESC(ec_no_wakeup, "Do not wake up from suspend-to-idle"); + struct acpi_ec_query_handler { struct list_head node; acpi_ec_query_func func; @@ -535,6 +539,14 @@ static void acpi_ec_disable_event(struct acpi_ec *ec) spin_unlock_irqrestore(&ec->lock, flags); __acpi_ec_flush_event(ec); } + +void acpi_ec_flush_work(void) +{ + if (first_ec) + __acpi_ec_flush_event(first_ec); + + flush_scheduled_work(); +} #endif /* CONFIG_PM_SLEEP */ static bool acpi_ec_guard_event(struct acpi_ec *ec) @@ -1880,6 +1892,32 @@ static int acpi_ec_suspend(struct device *dev) return 0; } +static int acpi_ec_suspend_noirq(struct device *dev) +{ + struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev)); + + /* + * The SCI handler doesn't run at this point, so the GPE can be + * masked at the low level without side effects. + */ + if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) && + ec->reference_count >= 1) + acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); + + return 0; +} + +static int acpi_ec_resume_noirq(struct device *dev) +{ + struct acpi_ec *ec = acpi_driver_data(to_acpi_device(dev)); + + if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) && + ec->reference_count >= 1) + acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE); + + return 0; +} + static int acpi_ec_resume(struct device *dev) { struct acpi_ec *ec = @@ -1891,6 +1929,7 @@ static int acpi_ec_resume(struct device *dev) #endif static const struct dev_pm_ops acpi_ec_pm = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend_noirq, acpi_ec_resume_noirq) SET_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend, acpi_ec_resume) }; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 9531d3276f65..58dd7ab3c653 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -193,6 +193,10 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, void *data); void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); +#ifdef CONFIG_PM_SLEEP +void acpi_ec_flush_work(void); +#endif + /*-------------------------------------------------------------------------- Suspend/Resume diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index be17664736b2..fa8243c5c062 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -777,11 +777,11 @@ static void acpi_freeze_sync(void) /* * Process all pending events in case there are any wakeup ones. * - * The EC driver uses the system workqueue, so that one needs to be - * flushed too. + * The EC driver uses the system workqueue and an additional special + * one, so those need to be flushed too. */ + acpi_ec_flush_work(); acpi_os_wait_events_complete(); - flush_scheduled_work(); s2idle_wakeup = false; }