aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-29 22:05:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-29 22:05:41 -0400
commit02529ba26f444e2a214c3dcacd866928e9edcfc0 (patch)
tree967038230377c4a0e495258dd38e904faba958fb
parent15114c7e1cf41e7e3a792b1cf6b815b947ef6d1e (diff)
parent75cc52358799bd6001e7d1a47847f997f5ae99f0 (diff)
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
-rw-r--r--drivers/acpi/processor_idle.c32
-rw-r--r--drivers/base/power/main.c6
2 files changed, 34 insertions, 4 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f3decb30223f..47a8caa89dbe 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -224,6 +224,7 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
224/* 224/*
225 * Suspend / resume control 225 * Suspend / resume control
226 */ 226 */
227static int acpi_idle_suspend;
227static u32 saved_bm_rld; 228static u32 saved_bm_rld;
228 229
229static void acpi_idle_bm_rld_save(void) 230static void acpi_idle_bm_rld_save(void)
@@ -242,13 +243,21 @@ static void acpi_idle_bm_rld_restore(void)
242 243
243int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) 244int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
244{ 245{
246 if (acpi_idle_suspend == 1)
247 return 0;
248
245 acpi_idle_bm_rld_save(); 249 acpi_idle_bm_rld_save();
250 acpi_idle_suspend = 1;
246 return 0; 251 return 0;
247} 252}
248 253
249int acpi_processor_resume(struct acpi_device * device) 254int acpi_processor_resume(struct acpi_device * device)
250{ 255{
256 if (acpi_idle_suspend == 0)
257 return 0;
258
251 acpi_idle_bm_rld_restore(); 259 acpi_idle_bm_rld_restore();
260 acpi_idle_suspend = 0;
252 return 0; 261 return 0;
253} 262}
254 263
@@ -754,6 +763,12 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
754 763
755 local_irq_disable(); 764 local_irq_disable();
756 765
766 if (acpi_idle_suspend) {
767 local_irq_enable();
768 cpu_relax();
769 return -EBUSY;
770 }
771
757 lapic_timer_state_broadcast(pr, cx, 1); 772 lapic_timer_state_broadcast(pr, cx, 1);
758 kt1 = ktime_get_real(); 773 kt1 = ktime_get_real();
759 acpi_idle_do_entry(cx); 774 acpi_idle_do_entry(cx);
@@ -823,6 +838,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
823 838
824 local_irq_disable(); 839 local_irq_disable();
825 840
841 if (acpi_idle_suspend) {
842 local_irq_enable();
843 cpu_relax();
844 return -EBUSY;
845 }
846
826 if (cx->entry_method != ACPI_CSTATE_FFH) { 847 if (cx->entry_method != ACPI_CSTATE_FFH) {
827 current_thread_info()->status &= ~TS_POLLING; 848 current_thread_info()->status &= ~TS_POLLING;
828 /* 849 /*
@@ -907,14 +928,21 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
907 drv, drv->safe_state_index); 928 drv, drv->safe_state_index);
908 } else { 929 } else {
909 local_irq_disable(); 930 local_irq_disable();
910 acpi_safe_halt(); 931 if (!acpi_idle_suspend)
932 acpi_safe_halt();
911 local_irq_enable(); 933 local_irq_enable();
912 return -EINVAL; 934 return -EBUSY;
913 } 935 }
914 } 936 }
915 937
916 local_irq_disable(); 938 local_irq_disable();
917 939
940 if (acpi_idle_suspend) {
941 local_irq_enable();
942 cpu_relax();
943 return -EBUSY;
944 }
945
918 if (cx->entry_method != ACPI_CSTATE_FFH) { 946 if (cx->entry_method != ACPI_CSTATE_FFH) {
919 current_thread_info()->status &= ~TS_POLLING; 947 current_thread_info()->status &= ~TS_POLLING;
920 /* 948 /*
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index e0fb5b0435a3..9cb845e49334 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1031,7 +1031,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
1031 dpm_wait_for_children(dev, async); 1031 dpm_wait_for_children(dev, async);
1032 1032
1033 if (async_error) 1033 if (async_error)
1034 return 0; 1034 goto Complete;
1035 1035
1036 pm_runtime_get_noresume(dev); 1036 pm_runtime_get_noresume(dev);
1037 if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) 1037 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)
1040 if (pm_wakeup_pending()) { 1040 if (pm_wakeup_pending()) {
1041 pm_runtime_put_sync(dev); 1041 pm_runtime_put_sync(dev);
1042 async_error = -EBUSY; 1042 async_error = -EBUSY;
1043 return 0; 1043 goto Complete;
1044 } 1044 }
1045 1045
1046 device_lock(dev); 1046 device_lock(dev);
@@ -1097,6 +1097,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
1097 } 1097 }
1098 1098
1099 device_unlock(dev); 1099 device_unlock(dev);
1100
1101 Complete:
1100 complete_all(&dev->power.completion); 1102 complete_all(&dev->power.completion);
1101 1103
1102 if (error) { 1104 if (error) {