summary refs log tree commit diff
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 08:14:53 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 08:14:53 -0800
commitc8940eca75e6d1ea57f6c491a30bd1023c64c9ad (patch)
treed68944ab9fa8ba3c77b18edc2bd836c7e355b23e /kernel
parent78c92a9fd4b6abbbc1fe1ec335c697cb4e63f252 (diff)
parent3ae22e8c8ac39daf88ae32f047fb23825be7c646 (diff)
downloadlinux-c8940eca75e6d1ea57f6c491a30bd1023c64c9ad.tar.gz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6:
  spi / PM: Support dev_pm_ops
  PM: Prototype the pm_generic_ operations
  PM / Runtime: Generic resume shouldn't set RPM_ACTIVE unconditionally
  PM: Use dev_name() in core device suspend and resume routines
  PM: Permit registration of parentless devices during system suspend
  PM: Replace the device power.status field with a bit field
  PM: Remove redundant checks from core device resume routines
  PM: Use a different list of devices for each stage of device suspend
  PM: Avoid compiler warning in pm_noirq_op()
  PM: Use pm_wakeup_pending() in __device_suspend()
  PM / Wakeup: Replace pm_check_wakeup_events() with pm_wakeup_pending()
  PM: Prevent dpm_prepare() from returning errors unnecessarily
  PM: Fix references to basic-pm-debugging.txt in drivers-testing.txt
  PM / Runtime: Add synchronous runtime interface for interrupt handlers (v3)
  PM / Hibernate: When failed, in_suspend should be reset
  PM / Hibernate: hibernation_ops->leave should be checked too
  Freezer: Fix a race during freezing of TASK_STOPPED tasks
  PM: Use proper ccflag flag in kernel/power/Makefile
  PM / Runtime: Fix comments to match runtime callback code
Diffstat (limited to 'kernel')
-rw-r--r--kernel/freezer.c9
-rw-r--r--kernel/power/Makefile5
-rw-r--r--kernel/power/hibernate.c7
-rw-r--r--kernel/power/process.c8
-rw-r--r--kernel/power/suspend.c2
5 files changed, 20 insertions, 11 deletions
diff --git a/kernel/freezer.c b/kernel/freezer.c
index bd1d42b17cb2..66ecd2ead215 100644
--- a/kernel/freezer.c
+++ b/kernel/freezer.c
@@ -104,8 +104,13 @@ bool freeze_task(struct task_struct *p, bool sig_only)
 	}
 
 	if (should_send_signal(p)) {
-		if (!signal_pending(p))
-			fake_signal_wake_up(p);
+		fake_signal_wake_up(p);
+		/*
+		 * fake_signal_wake_up() goes through p's scheduler
+		 * lock and guarantees that TASK_STOPPED/TRACED ->
+		 * TASK_RUNNING transition can't race with task state
+		 * testing in try_to_freeze_tasks().
+		 */
 	} else if (sig_only) {
 		return false;
 	} else {
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index f9063c6b185d..b75597235d85 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -1,7 +1,4 @@
-
-ifeq ($(CONFIG_PM_DEBUG),y)
-EXTRA_CFLAGS	+=	-DDEBUG
-endif
+ccflags-$(CONFIG_PM_DEBUG)	:=	-DDEBUG
 
 obj-$(CONFIG_PM)		+= main.o
 obj-$(CONFIG_PM_SLEEP)		+= console.o
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 048d0b514831..870f72bc72ae 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -62,7 +62,7 @@ void hibernation_set_ops(struct platform_hibernation_ops *ops)
 {
 	if (ops && !(ops->begin && ops->end &&  ops->pre_snapshot
 	    && ops->prepare && ops->finish && ops->enter && ops->pre_restore
-	    && ops->restore_cleanup)) {
+	    && ops->restore_cleanup && ops->leave)) {
 		WARN_ON(1);
 		return;
 	}
@@ -278,7 +278,7 @@ static int create_image(int platform_mode)
 		goto Enable_irqs;
 	}
 
-	if (hibernation_test(TEST_CORE) || !pm_check_wakeup_events())
+	if (hibernation_test(TEST_CORE) || pm_wakeup_pending())
 		goto Power_up;
 
 	in_suspend = 1;
@@ -516,7 +516,7 @@ int hibernation_platform_enter(void)
 
 	local_irq_disable();
 	sysdev_suspend(PMSG_HIBERNATE);
-	if (!pm_check_wakeup_events()) {
+	if (pm_wakeup_pending()) {
 		error = -EAGAIN;
 		goto Power_up;
 	}
@@ -647,6 +647,7 @@ int hibernate(void)
 		swsusp_free();
 		if (!error)
 			power_down();
+		in_suspend = 0;
 		pm_restore_gfp_mask();
 	} else {
 		pr_debug("PM: Image restored successfully.\n");
diff --git a/kernel/power/process.c b/kernel/power/process.c
index e50b4c1b2a0f..d6d2a10320e0 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -64,6 +64,12 @@ static int try_to_freeze_tasks(bool sig_only)
 			 * perturb a task in TASK_STOPPED or TASK_TRACED.
 			 * It is "frozen enough".  If the task does wake
 			 * up, it will immediately call try_to_freeze.
+			 *
+			 * Because freeze_task() goes through p's
+			 * scheduler lock after setting TIF_FREEZE, it's
+			 * guaranteed that either we see TASK_RUNNING or
+			 * try_to_stop() after schedule() in ptrace/signal
+			 * stop sees TIF_FREEZE.
 			 */
 			if (!task_is_stopped_or_traced(p) &&
 			    !freezer_should_skip(p))
@@ -79,7 +85,7 @@ static int try_to_freeze_tasks(bool sig_only)
 		if (!todo || time_after(jiffies, end_time))
 			break;
 
-		if (!pm_check_wakeup_events()) {
+		if (pm_wakeup_pending()) {
 			wakeup = true;
 			break;
 		}
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 031d5e3a6197..8850df68794d 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -164,7 +164,7 @@ static int suspend_enter(suspend_state_t state)
 
 	error = sysdev_suspend(PMSG_SUSPEND);
 	if (!error) {
-		if (!suspend_test(TEST_CORE) && pm_check_wakeup_events()) {
+		if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
 			error = suspend_ops->enter(state);
 			events_check_enabled = false;
 		}