Commit 76380636 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

ACPI / EC: Add parameter to force disable the GPE on suspend

After commit 8110dd28 (ACPI / sleep: EC-based wakeup from
suspend-to-idle on recent systems) the configuration of GPEs,
including the EC one, is not changed during suspend-to-idle on
recent systems.  That's in order to make system wakeup events
generated by the EC work, in particular.

However, on some of the systems in question (for example on Dell
XPS13 9365), in addition to generating system wakeup events the
EC generates a heartbeat sequence of interrupts that have nothing
to do with wakeup while suspended, and the Low Power Idle S0 _DSM
interface doesn't change that behavior.

The users of those systems may prefer to disable the EC GPE during
system suspend, for the cost of non-functional power button wakeup
or similar, but currently there is no way to do that.

For this reason, add a new module parameter, ec_no_wakeup, for the
EC driver module that, if set, will cause the EC GPE to be disabled
during system suspend and re-enabled during the subsequent system
resume.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=192591#c106
Amends: 8110dd28 (ACPI / sleep: EC-based wakeup from suspend-to-idle on recent systems)
Reported-and-tested-by: default avatarPatrik Kullman <patrik.kullman@gmail.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 9c40f956
...@@ -151,6 +151,10 @@ static bool ec_freeze_events __read_mostly = false; ...@@ -151,6 +151,10 @@ static bool ec_freeze_events __read_mostly = false;
module_param(ec_freeze_events, bool, 0644); module_param(ec_freeze_events, bool, 0644);
MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume"); 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 acpi_ec_query_handler {
struct list_head node; struct list_head node;
acpi_ec_query_func func; acpi_ec_query_func func;
...@@ -1880,6 +1884,32 @@ static int acpi_ec_suspend(struct device *dev) ...@@ -1880,6 +1884,32 @@ static int acpi_ec_suspend(struct device *dev)
return 0; 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) static int acpi_ec_resume(struct device *dev)
{ {
struct acpi_ec *ec = struct acpi_ec *ec =
...@@ -1891,6 +1921,7 @@ static int acpi_ec_resume(struct device *dev) ...@@ -1891,6 +1921,7 @@ static int acpi_ec_resume(struct device *dev)
#endif #endif
static const struct dev_pm_ops acpi_ec_pm = { 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) SET_SYSTEM_SLEEP_PM_OPS(acpi_ec_suspend, acpi_ec_resume)
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment