Skip to content

Commit 02529ba

Browse files
committed
Merge tag 'pm-for-3.5-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael J. Wysocki: * Fix for a bug in async suspend error code path causing parents to wait forever for their children in case of a suspend error from Mandeep Singh Baines (-stable metarial). * Fix for a suspend regression related to earlier changes in the ACPI cpuidle driver from Deepthi Dharwar. * tag 'pm-for-3.5-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PM / ACPI: Fix suspend/resume regression caused by cpuidle cleanup. PM / Sleep: Prevent waiting forever on asynchronous suspend after abort
2 parents 15114c7 + 75cc523 commit 02529ba

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

drivers/acpi/processor_idle.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
224224
/*
225225
* Suspend / resume control
226226
*/
227+
static int acpi_idle_suspend;
227228
static u32 saved_bm_rld;
228229

229230
static void acpi_idle_bm_rld_save(void)
@@ -242,13 +243,21 @@ static void acpi_idle_bm_rld_restore(void)
242243

243244
int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
244245
{
246+
if (acpi_idle_suspend == 1)
247+
return 0;
248+
245249
acpi_idle_bm_rld_save();
250+
acpi_idle_suspend = 1;
246251
return 0;
247252
}
248253

249254
int acpi_processor_resume(struct acpi_device * device)
250255
{
256+
if (acpi_idle_suspend == 0)
257+
return 0;
258+
251259
acpi_idle_bm_rld_restore();
260+
acpi_idle_suspend = 0;
252261
return 0;
253262
}
254263

@@ -754,6 +763,12 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
754763

755764
local_irq_disable();
756765

766+
if (acpi_idle_suspend) {
767+
local_irq_enable();
768+
cpu_relax();
769+
return -EBUSY;
770+
}
771+
757772
lapic_timer_state_broadcast(pr, cx, 1);
758773
kt1 = ktime_get_real();
759774
acpi_idle_do_entry(cx);
@@ -823,6 +838,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
823838

824839
local_irq_disable();
825840

841+
if (acpi_idle_suspend) {
842+
local_irq_enable();
843+
cpu_relax();
844+
return -EBUSY;
845+
}
846+
826847
if (cx->entry_method != ACPI_CSTATE_FFH) {
827848
current_thread_info()->status &= ~TS_POLLING;
828849
/*
@@ -907,14 +928,21 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
907928
drv, drv->safe_state_index);
908929
} else {
909930
local_irq_disable();
910-
acpi_safe_halt();
931+
if (!acpi_idle_suspend)
932+
acpi_safe_halt();
911933
local_irq_enable();
912-
return -EINVAL;
934+
return -EBUSY;
913935
}
914936
}
915937

916938
local_irq_disable();
917939

940+
if (acpi_idle_suspend) {
941+
local_irq_enable();
942+
cpu_relax();
943+
return -EBUSY;
944+
}
945+
918946
if (cx->entry_method != ACPI_CSTATE_FFH) {
919947
current_thread_info()->status &= ~TS_POLLING;
920948
/*

drivers/base/power/main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
10311031
dpm_wait_for_children(dev, async);
10321032

10331033
if (async_error)
1034-
return 0;
1034+
goto Complete;
10351035

10361036
pm_runtime_get_noresume(dev);
10371037
if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
@@ -1040,7 +1040,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
10401040
if (pm_wakeup_pending()) {
10411041
pm_runtime_put_sync(dev);
10421042
async_error = -EBUSY;
1043-
return 0;
1043+
goto Complete;
10441044
}
10451045

10461046
device_lock(dev);
@@ -1097,6 +1097,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
10971097
}
10981098

10991099
device_unlock(dev);
1100+
1101+
Complete:
11001102
complete_all(&dev->power.completion);
11011103

11021104
if (error) {

0 commit comments

Comments
 (0)