diff options
Diffstat (limited to 'drivers/acpi/ec.c')
| -rw-r--r-- | drivers/acpi/ec.c | 56 | 
1 files changed, 46 insertions, 10 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ddb01e9fa5b2..ae3d6d152633 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) @@ -1729,7 +1741,7 @@ error:   * functioning ECDT EC first in order to handle the events.   * https://bugzilla.kernel.org/show_bug.cgi?id=115021   */ -int __init acpi_ec_ecdt_start(void) +static int __init acpi_ec_ecdt_start(void)  {  	acpi_handle handle; @@ -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)  }; @@ -1964,20 +2003,17 @@ static inline void acpi_ec_query_exit(void)  int __init acpi_ec_init(void)  {  	int result; +	int ecdt_fail, dsdt_fail;  	/* register workqueue for _Qxx evaluations */  	result = acpi_ec_query_init();  	if (result) -		goto err_exit; -	/* Now register the driver for the EC */ -	result = acpi_bus_register_driver(&acpi_ec_driver); -	if (result) -		goto err_exit; +		return result; -err_exit: -	if (result) -		acpi_ec_query_exit(); -	return result; +	/* Drivers must be started after acpi_ec_query_init() */ +	ecdt_fail = acpi_ec_ecdt_start(); +	dsdt_fail = acpi_bus_register_driver(&acpi_ec_driver); +	return ecdt_fail && dsdt_fail ? -ENODEV : 0;  }  /* EC driver currently not unloadable */  | 
