d5a64513c6
There still is a race that may result in suspending the system in the middle of an EC transaction in progress, which leads to problems (like the kernel thinking that the ACPI global lock is held during resume while in fact it's not). To remove the race condition, modify the ACPI platform suspend and hibernate callbacks so that EC transactions are blocked right after executing the _PTS global control method and are allowed to happen again right after the low-level wakeup. Introduce acpi_pm_freeze() that will disable GPEs, wait until the event queues are empty and block EC transactions. Use it wherever GPEs are disabled in preparation for switching local interrupts off. Introduce acpi_pm_thaw() that will allow EC transactions to happen again and enable runtime GPEs. Use it to balance acpi_pm_freeze() wherever necessary. In addition to that use acpi_ec_resume_transactions_early() to unblock EC transactions as early as reasonably possible during resume. Also unblock EC transactions in acpi_hibernation_finish() and in the analogous suspend routine to make sure that the EC transactions are enabled in all error paths. Fixes https://bugzilla.kernel.org/show_bug.cgi?id=14668 Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Reported-and-tested-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Len Brown <len.brown@intel.com>
66 lines
2.4 KiB
C
66 lines
2.4 KiB
C
/*
|
|
* acpi/internal.h
|
|
* For use by Linux/ACPI infrastructure, not drivers
|
|
*
|
|
* Copyright (c) 2009, Intel Corporation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#define PREFIX "ACPI: "
|
|
|
|
int init_acpi_device_notify(void);
|
|
int acpi_scan_init(void);
|
|
int acpi_system_init(void);
|
|
|
|
#ifdef CONFIG_ACPI_DEBUG
|
|
int acpi_debug_init(void);
|
|
#else
|
|
static inline int acpi_debug_init(void) { return 0; }
|
|
#endif
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Power Resource
|
|
-------------------------------------------------------------------------- */
|
|
int acpi_power_init(void);
|
|
int acpi_device_sleep_wake(struct acpi_device *dev,
|
|
int enable, int sleep_state, int dev_state);
|
|
int acpi_power_get_inferred_state(struct acpi_device *device);
|
|
int acpi_power_transition(struct acpi_device *device, int state);
|
|
extern int acpi_power_nocheck;
|
|
|
|
int acpi_wakeup_device_init(void);
|
|
void acpi_early_processor_set_pdc(void);
|
|
|
|
/* --------------------------------------------------------------------------
|
|
Embedded Controller
|
|
-------------------------------------------------------------------------- */
|
|
int acpi_ec_init(void);
|
|
int acpi_ec_ecdt_probe(void);
|
|
int acpi_boot_ec_enable(void);
|
|
void acpi_ec_suspend_transactions(void);
|
|
void acpi_ec_resume_transactions(void);
|
|
void acpi_ec_resume_transactions_early(void);
|
|
|
|
/*--------------------------------------------------------------------------
|
|
Suspend/Resume
|
|
-------------------------------------------------------------------------- */
|
|
extern int acpi_sleep_init(void);
|
|
|
|
#ifdef CONFIG_ACPI_SLEEP
|
|
int acpi_sleep_proc_init(void);
|
|
#else
|
|
static inline int acpi_sleep_proc_init(void) { return 0; }
|
|
#endif
|