[kernel/f13/master] acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch
Chuck Ebbert
cebbert at fedoraproject.org
Sat Sep 4 03:34:57 UTC 2010
commit e00d73683c8da6ce617075c4613a690c14c82d6b
Author: Chuck Ebbert <cebbert at redhat.com>
Date: Fri Sep 3 23:35:20 2010 -0400
acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch
another possible fix for suspend/resume problems.
...etween-ec-transactions-and-system-suspend.patch | 215 ++++++++++++++++++++
kernel.spec | 16 ++-
2 files changed, 228 insertions(+), 3 deletions(-)
---
diff --git a/acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch b/acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch
new file mode 100644
index 0000000..85d6756
--- /dev/null
+++ b/acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch
@@ -0,0 +1,215 @@
+From: Rafael J. Wysocki <rjw at sisk.pl>
+Date: Thu, 8 Apr 2010 23:39:40 +0000 (+0200)
+Subject: ACPI / EC / PM: Fix race between EC transactions and system suspend
+X-Git-Tag: v2.6.35-rc2~39^2~3
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=d5a64513c6a171262082c250592c062e97a2c693
+
+ACPI / EC / PM: Fix race between EC transactions and system suspend
+
+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 at sisk.pl>
+Reported-and-tested-by: Maxim Levitsky <maximlevitsky at gmail.com>
+Signed-off-by: Len Brown <len.brown at intel.com>
+---
+
+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 */
diff --git a/kernel.spec b/kernel.spec
index af501ab..275872d 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -48,7 +48,7 @@ Summary: The Linux kernel
# reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec).
# scripts/rebase.sh should be made to do that for you, actually.
#
-%global baserelease 51
+%global baserelease 52
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@@ -771,10 +771,13 @@ Patch12480: kprobes-x86-fix-kprobes-to-skip-prefixes-correctly.patch
Patch12490: dell-wmi-add-support-for-eject-key.patch
Patch12500: irda-correctly-clean-up-self-ias_obj-on-irda_bind-failure.patch
Patch12510: wireless-extensions-fix-kernel-heap-content-leak.patch
+
Patch12515: sanity-check-bond-proc_entry.patch
Patch12516: asix-use-eth_mac_addr.patch
Patch12517: flexcop-fix-xlate_proc_name-warning.patch
+Patch12520: acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch
+
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1454,6 +1457,9 @@ ApplyPatch asix-use-eth_mac_addr.patch
# bz #575873
ApplyPatch flexcop-fix-xlate_proc_name-warning.patch
+# another fix for suspend/resume bugs
+ApplyPatch acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -2075,9 +2081,13 @@ fi
%changelog
-* Fri Sep 03 2010 Kyle McMartin <kmcmartin at redhat.com> 2.6.34.6-52
+* Fri Sep 03 2010 Chuck Ebbert <cebbert at redhat.com> 2.6.34.6-52
+- acpi-ec-pm-fix-race-between-ec-transactions-and-system-suspend.patch:
+ another possible fix for suspend/resume problems.
+
+* Fri Sep 03 2010 Kyle McMartin <kmcmartin at redhat.com>
- sanity-check-bond-proc_entry.patch (rhbz#604630)
-- asix.c: stub out set_mac_address in case it's breaking things (rhbz#629871)
+- asix.c: stub out set_mac_address in case it's breaking things (rhbz#625479)
- default to pci=nocrs
- flexcop: fix registering braindead stupid names (#575873)
More information about the scm-commits
mailing list