[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <2852781.TfChGuuEkJ@vostro.rjw.lan>
Date: Tue, 20 Aug 2013 01:47:57 +0200
From: "Rafael J. Wysocki" <rjw@...k.pl>
To: ACPI Devel Maling List <linux-acpi@...r.kernel.org>
Cc: LKML <linux-kernel@...r.kernel.org>,
Linux PCI <linux-pci@...r.kernel.org>,
Linux PM list <linux-pm@...r.kernel.org>,
Bjorn Helgaas <bhelgaas@...gle.com>,
Toshi Kani <toshi.kani@...com>,
Mika Westerberg <mika.westerberg@...ux.intel.com>
Subject: [PATCH] ACPI / PM: Hold acpi_scan_lock over system PM transitions
From: Rafael J. Wysocki <rafael.j.wysocki@...el.com>
Bad things happen if ACPI hotplug events are handled during system
PM transitions, especially if devices are removed as a result.
To prevent those bad things from happening, acquire acpi_scan_lock
when a transition is started and release it when that transition
is complete or has been aborted.
This fixes resume lockup on my test-bed Acer Aspire S5 that happens
when Thunderbolt devices are disconnected from the machine while
suspended.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@...el.com>
---
Applies on top of the linux-next branch of the linux-pm.git tree.
Thanks,
Rafael
---
drivers/acpi/sleep.c | 39 ++++++++++++++++++++++++---------------
1 file changed, 24 insertions(+), 15 deletions(-)
Index: linux-pm/drivers/acpi/sleep.c
===================================================================
--- linux-pm.orig/drivers/acpi/sleep.c
+++ linux-pm/drivers/acpi/sleep.c
@@ -420,10 +420,21 @@ static void acpi_pm_finish(void)
}
/**
- * acpi_pm_end - Finish up suspend sequence.
+ * acpi_pm_start - Start system PM transition.
+ */
+static void acpi_pm_start(u32 acpi_state)
+{
+ acpi_target_sleep_state = acpi_state;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
+ acpi_scan_lock_acquire();
+}
+
+/**
+ * acpi_pm_end - Finish up system PM transition.
*/
static void acpi_pm_end(void)
{
+ acpi_scan_lock_release();
/*
* This is necessary in case acpi_pm_finish() is not called during a
* failing transition to a sleep state.
@@ -451,21 +462,19 @@ static u32 acpi_suspend_states[] = {
static int acpi_suspend_begin(suspend_state_t pm_state)
{
u32 acpi_state = acpi_suspend_states[pm_state];
- int error = 0;
+ int error;
error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
if (error)
return error;
- if (sleep_states[acpi_state]) {
- acpi_target_sleep_state = acpi_state;
- acpi_sleep_tts_switch(acpi_target_sleep_state);
- } else {
- printk(KERN_ERR "ACPI does not support this state: %d\n",
- pm_state);
- error = -ENOSYS;
+ if (!sleep_states[acpi_state]) {
+ pr_err("ACPI does not support sleep state S%u\n", acpi_state);
+ return -ENOSYS;
}
- return error;
+
+ acpi_pm_start(acpi_state);
+ return 0;
}
/**
@@ -631,10 +640,8 @@ static int acpi_hibernation_begin(void)
int error;
error = nvs_nosave ? 0 : suspend_nvs_alloc();
- if (!error) {
- acpi_target_sleep_state = ACPI_STATE_S4;
- acpi_sleep_tts_switch(acpi_target_sleep_state);
- }
+ if (!error)
+ acpi_pm_start(ACPI_STATE_S4);
return error;
}
@@ -713,8 +720,10 @@ static int acpi_hibernation_begin_old(vo
if (!error) {
if (!nvs_nosave)
error = suspend_nvs_alloc();
- if (!error)
+ if (!error) {
acpi_target_sleep_state = ACPI_STATE_S4;
+ acpi_scan_lock_acquire();
+ }
}
return error;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists