summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/ec.c10
-rw-r--r--drivers/acpi/internal.h1
-rw-r--r--drivers/acpi/sleep.c55
3 files changed, 40 insertions, 26 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index f2234db..2c2b73a 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -485,6 +485,16 @@ void acpi_ec_resume_transactions(void)
mutex_unlock(&ec->lock);
}
+void acpi_ec_resume_transactions_early(void)
+{
+ /*
+ * Allow transactions to happen again (this function is called from
+ * atomic context during wakeup, so we don't need to acquire the mutex).
+ */
+ if (first_ec)
+ clear_bit(EC_FLAGS_FROZEN, &first_ec->flags);
+}
+
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
{
int result;
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index e284113..0ec48c7 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -51,6 +51,7 @@ 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
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index baa76bb..24741ac 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -110,11 +110,13 @@ void __init acpi_old_suspend_ordering(void)
}
/**
- * acpi_pm_disable_gpes - Disable the GPEs.
+ * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
*/
-static int acpi_pm_disable_gpes(void)
+static int acpi_pm_freeze(void)
{
acpi_disable_all_gpes();
+ acpi_os_wait_events_complete(NULL);
+ acpi_ec_suspend_transactions();
return 0;
}
@@ -142,7 +144,8 @@ static int acpi_pm_prepare(void)
int error = __acpi_pm_prepare();
if (!error)
- acpi_disable_all_gpes();
+ acpi_pm_freeze();
+
return error;
}
@@ -275,6 +278,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
* acpi_leave_sleep_state will reenable specific GPEs later
*/
acpi_disable_all_gpes();
+ /* Allow EC transactions to happen. */
+ acpi_ec_resume_transactions_early();
local_irq_restore(flags);
printk(KERN_DEBUG "Back to C!\n");
@@ -286,6 +291,12 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
+static void acpi_suspend_finish(void)
+{
+ acpi_ec_resume_transactions();
+ acpi_pm_finish();
+}
+
static int acpi_suspend_state_valid(suspend_state_t pm_state)
{
u32 acpi_state;
@@ -307,7 +318,7 @@ static struct platform_suspend_ops acpi_suspend_ops = {
.begin = acpi_suspend_begin,
.prepare_late = acpi_pm_prepare,
.enter = acpi_suspend_enter,
- .wake = acpi_pm_finish,
+ .wake = acpi_suspend_finish,
.end = acpi_pm_end,
};
@@ -333,9 +344,9 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state)
static struct platform_suspend_ops acpi_suspend_ops_old = {
.valid = acpi_suspend_state_valid,
.begin = acpi_suspend_begin_old,
- .prepare_late = acpi_pm_disable_gpes,
+ .prepare_late = acpi_pm_freeze,
.enter = acpi_suspend_enter,
- .wake = acpi_pm_finish,
+ .wake = acpi_suspend_finish,
.end = acpi_pm_end,
.recover = acpi_pm_finish,
};
@@ -586,6 +597,7 @@ static int acpi_hibernation_enter(void)
static void acpi_hibernation_finish(void)
{
hibernate_nvs_free();
+ acpi_ec_resume_transactions();
acpi_pm_finish();
}
@@ -606,17 +618,11 @@ static void acpi_hibernation_leave(void)
}
/* Restore the NVS memory area */
hibernate_nvs_restore();
+ /* Allow EC transactions to happen. */
+ acpi_ec_resume_transactions_early();
}
-static int acpi_pm_pre_restore(void)
-{
- acpi_disable_all_gpes();
- acpi_os_wait_events_complete(NULL);
- acpi_ec_suspend_transactions();
- return 0;
-}
-
-static void acpi_pm_restore_cleanup(void)
+static void acpi_pm_thaw(void)
{
acpi_ec_resume_transactions();
acpi_enable_all_runtime_gpes();
@@ -630,8 +636,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
- .pre_restore = acpi_pm_pre_restore,
- .restore_cleanup = acpi_pm_restore_cleanup,
+ .pre_restore = acpi_pm_freeze,
+ .restore_cleanup = acpi_pm_thaw,
};
/**
@@ -663,12 +669,9 @@ static int acpi_hibernation_begin_old(void)
static int acpi_hibernation_pre_snapshot_old(void)
{
- int error = acpi_pm_disable_gpes();
-
- if (!error)
- hibernate_nvs_save();
-
- return error;
+ acpi_pm_freeze();
+ hibernate_nvs_save();
+ return 0;
}
/*
@@ -680,11 +683,11 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot_old,
.finish = acpi_hibernation_finish,
- .prepare = acpi_pm_disable_gpes,
+ .prepare = acpi_pm_freeze,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
- .pre_restore = acpi_pm_pre_restore,
- .restore_cleanup = acpi_pm_restore_cleanup,
+ .pre_restore = acpi_pm_freeze,
+ .restore_cleanup = acpi_pm_thaw,
.recover = acpi_pm_finish,
};
#endif /* CONFIG_HIBERNATION */
OpenPOWER on IntegriCloud