From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Len Brown <lenb@kernel.org>
Cc: Alexey Starikovskiy <astarikovskiy@suse.de>,
ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
pm list <linux-pm@lists.linux-foundation.org>,
LKML <linux-kernel@vger.kernel.org>,
Maxim Levitsky <maximlevitsky@gmail.com>
Subject: Re: [Resend][PATCH] ACPI / EC: Remove race between EC driver and suspend process (rev. 3)
Date: Thu, 4 Mar 2010 01:52:58 +0100 [thread overview]
Message-ID: <201003040152.58437.rjw@sisk.pl> (raw)
In-Reply-To: <alpine.LFD.2.00.1003031644410.1044@localhost.localdomain>
On Wednesday 03 March 2010, Len Brown wrote:
> For the record, Rafael, Alexey and I discusseed this a bit further...
>
> We reasoned that this failure is impossible during the Suspend-to-RAM
> path, and the failure is specific to the hibernate reboot kernel handoff
> to the resume image.
Below is a simplified version of the patch that also should fix the problem.
Rafael
---
From: Rafael J. Wysocki <rjw@sisk.pl>
Subject: ACPI / EC / PM: Close race between EC and resume from hibernation
There is a race between resume from hibernation and the EC driver
that may result in restoring the hibernation image in the middle of
an EC transaction in progress, which in turn may lead to
unpredictable behavior of the platform.
To remove that race condition, add a helpers for suspending and
resuming EC transactions in a safe way to be executed by the ACPI
platform hibernate pre-restore and restore cleanup callbacks.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Reported-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
drivers/acpi/ec.c | 33 ++++++++++++++++++++++++++++++++-
drivers/acpi/internal.h | 2 ++
drivers/acpi/sleep.c | 19 ++++++++++++++-----
3 files changed, 48 insertions(+), 6 deletions(-)
Index: linux-2.6/drivers/acpi/ec.c
===================================================================
--- linux-2.6.orig/drivers/acpi/ec.c
+++ linux-2.6/drivers/acpi/ec.c
@@ -76,8 +76,9 @@ enum ec_command {
enum {
EC_FLAGS_QUERY_PENDING, /* Query is pending */
EC_FLAGS_GPE_STORM, /* GPE storm detected */
- EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and
+ EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
* OpReg are installed */
+ EC_FLAGS_FROZEN, /* Transactions are suspended */
};
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
@@ -291,6 +292,10 @@ static int acpi_ec_transaction(struct ac
if (t->rdata)
memset(t->rdata, 0, t->rlen);
mutex_lock(&ec->lock);
+ if (test_bit(EC_FLAGS_FROZEN, &ec->flags)) {
+ status = -EINVAL;
+ goto unlock;
+ }
if (ec->global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status)) {
@@ -453,6 +458,32 @@ int ec_transaction(u8 command,
EXPORT_SYMBOL(ec_transaction);
+void acpi_ec_suspend_transactions(void)
+{
+ struct acpi_ec *ec = first_ec;
+
+ if (!ec)
+ return;
+
+ mutex_lock(&ec->lock);
+ /* Prevent transactions from being carried out */
+ set_bit(EC_FLAGS_FROZEN, &ec->flags);
+ mutex_unlock(&ec->lock);
+}
+
+void acpi_ec_resume_transactions(void)
+{
+ struct acpi_ec *ec = first_ec;
+
+ if (!ec)
+ return;
+
+ mutex_lock(&ec->lock);
+ /* Allow transactions to be carried out again */
+ clear_bit(EC_FLAGS_FROZEN, &ec->flags);
+ mutex_unlock(&ec->lock);
+}
+
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
{
int result;
Index: linux-2.6/drivers/acpi/internal.h
===================================================================
--- linux-2.6.orig/drivers/acpi/internal.h
+++ linux-2.6/drivers/acpi/internal.h
@@ -49,6 +49,8 @@ void acpi_early_processor_set_pdc(void);
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);
/*--------------------------------------------------------------------------
Suspend/Resume
Index: linux-2.6/drivers/acpi/sleep.c
===================================================================
--- linux-2.6.orig/drivers/acpi/sleep.c
+++ linux-2.6/drivers/acpi/sleep.c
@@ -552,8 +552,17 @@ static void acpi_hibernation_leave(void)
hibernate_nvs_restore();
}
-static void acpi_pm_enable_gpes(void)
+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)
+{
+ acpi_ec_resume_transactions();
acpi_enable_all_runtime_gpes();
}
@@ -565,8 +574,8 @@ static struct platform_hibernation_ops a
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
- .pre_restore = acpi_pm_disable_gpes,
- .restore_cleanup = acpi_pm_enable_gpes,
+ .pre_restore = acpi_pm_pre_restore,
+ .restore_cleanup = acpi_pm_restore_cleanup,
};
/**
@@ -618,8 +627,8 @@ static struct platform_hibernation_ops a
.prepare = acpi_pm_disable_gpes,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
- .pre_restore = acpi_pm_disable_gpes,
- .restore_cleanup = acpi_pm_enable_gpes,
+ .pre_restore = acpi_pm_pre_restore,
+ .restore_cleanup = acpi_pm_restore_cleanup,
.recover = acpi_pm_finish,
};
#endif /* CONFIG_HIBERNATION */
next prev parent reply other threads:[~2010-03-04 0:50 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-27 20:40 [Resend][PATCH] ACPI / EC: Remove race between EC driver and suspend process (rev. 3) Rafael J. Wysocki
2010-03-03 21:49 ` Len Brown
2010-03-04 0:52 ` Rafael J. Wysocki [this message]
2010-03-04 5:55 ` Len Brown
2010-03-04 9:32 ` Alan Jenkins
2010-03-04 19:20 ` Rafael J. Wysocki
2010-03-08 21:10 ` Rafael J. Wysocki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201003040152.58437.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=astarikovskiy@suse.de \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@lists.linux-foundation.org \
--cc=maximlevitsky@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox