All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bojan Smojver <bojan@rexursive.com>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
	"Rafael J. Wysocki" <rjw@sisk.pl>,
	Linux PM list <linux-pm@vger.kernel.org>,
	Kernel development list <linux-kernel@vger.kernel.org>,
	bp@alien8.de
Subject: Re: [PATCH]: In kernel hibernation, suspend to both
Date: Mon, 14 May 2012 21:11:30 +1000	[thread overview]
Message-ID: <1336993890.1662.1.camel@shrek.rexursive.com> (raw)
In-Reply-To: <1336981522.1678.0.camel@shrek.rexursive.com>

On Mon, 2012-05-14 at 17:45 +1000, Bojan Smojver wrote:
> On Mon, 2012-05-14 at 12:58 +1000, Bojan Smojver wrote:
> > +               error = pm_suspend(PM_SUSPEND_MEM);
> 
> Er, that won't work. The lock is being held by the caller. OK, we'll
> have to make it complicated, I guess...

Totally untested...
-------------------
 Documentation/power/swsusp.txt |    5 +++
 kernel/power/hibernate.c       |   36 ++++++++++++++++++++
 kernel/power/power.h           |    6 ++++
 kernel/power/suspend.c         |   71 ++++++++++++++++++++++++++++++++--------
 kernel/power/swap.c            |   28 ++++++++++++++++
 5 files changed, 133 insertions(+), 13 deletions(-)

diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index ac190cf..92341b8 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -33,6 +33,11 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
 
 echo platform > /sys/power/disk; echo disk > /sys/power/state
 
+. If you would like to write hibernation image to swap and then suspend
+to RAM (provided your platform supports it), you can try
+
+echo suspend > /sys/power/disk; echo disk > /sys/power/state
+
 . If you have SATA disks, you'll need recent kernels with SATA suspend
 support. For suspend and resume to work, make sure your disk drivers
 are built into kernel -- not modules. [There's way to make
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index e09dfbf..f48a9ba 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2003 Open Source Development Lab
  * Copyright (c) 2004 Pavel Machek <pavel@ucw.cz>
  * Copyright (c) 2009 Rafael J. Wysocki, Novell Inc.
+ * Copyright (C) 2012 Bojan Smojver <bojan@rexursive.com>
  *
  * This file is released under the GPLv2.
  */
@@ -44,6 +45,9 @@ enum {
 	HIBERNATION_PLATFORM,
 	HIBERNATION_SHUTDOWN,
 	HIBERNATION_REBOOT,
+#ifdef CONFIG_SUSPEND
+	HIBERNATION_SUSPEND,
+#endif
 	/* keep last */
 	__HIBERNATION_AFTER_LAST
 };
@@ -572,6 +576,10 @@ int hibernation_platform_enter(void)
  */
 static void power_down(void)
 {
+#ifdef CONFIG_SUSPEND
+	int error;
+#endif
+
 	switch (hibernation_mode) {
 	case HIBERNATION_REBOOT:
 		kernel_restart(NULL);
@@ -581,6 +589,25 @@ static void power_down(void)
 	case HIBERNATION_SHUTDOWN:
 		kernel_power_off();
 		break;
+#ifdef CONFIG_SUSPEND
+	case HIBERNATION_SUSPEND:
+		error = suspend_locked(PM_SUSPEND_MEM);
+		if (error) {
+			if (hibernation_ops)
+				hibernation_mode = HIBERNATION_PLATFORM;
+			else
+				hibernation_mode = HIBERNATION_SHUTDOWN;
+			power_down();
+		}
+		/*
+		 * Restore swap signature.
+		 */
+		error = swsusp_unmark();
+		if (error)
+			printk(KERN_ERR "PM: Swap will be unusable! "
+			                "Try swapon -a.\n");
+		return;
+#endif
 	}
 	kernel_halt();
 	/*
@@ -814,6 +841,9 @@ static const char * const hibernation_modes[] = {
 	[HIBERNATION_PLATFORM]	= "platform",
 	[HIBERNATION_SHUTDOWN]	= "shutdown",
 	[HIBERNATION_REBOOT]	= "reboot",
+#ifdef CONFIG_SUSPEND
+	[HIBERNATION_SUSPEND]	= "suspend",
+#endif
 };
 
 /*
@@ -854,6 +884,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
 		switch (i) {
 		case HIBERNATION_SHUTDOWN:
 		case HIBERNATION_REBOOT:
+#ifdef CONFIG_SUSPEND
+		case HIBERNATION_SUSPEND:
+#endif
 			break;
 		case HIBERNATION_PLATFORM:
 			if (hibernation_ops)
@@ -894,6 +927,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
 		switch (mode) {
 		case HIBERNATION_SHUTDOWN:
 		case HIBERNATION_REBOOT:
+#ifdef CONFIG_SUSPEND
+		case HIBERNATION_SUSPEND:
+#endif
 			hibernation_mode = mode;
 			break;
 		case HIBERNATION_PLATFORM:
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 98f3622..cb8e09e 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -156,6 +156,9 @@ extern void swsusp_free(void);
 extern int swsusp_read(unsigned int *flags_p);
 extern int swsusp_write(unsigned int flags);
 extern void swsusp_close(fmode_t);
+#ifdef CONFIG_SUSPEND
+extern int swsusp_unmark(void);
+#endif
 
 /* kernel/power/block_io.c */
 extern struct block_device *hib_resume_bdev;
@@ -177,6 +180,9 @@ extern const char *const pm_states[];
 
 extern bool valid_state(suspend_state_t state);
 extern int suspend_devices_and_enter(suspend_state_t state);
+#ifdef CONFIG_HIBERNATION
+extern int suspend_locked(suspend_state_t state);
+#endif
 #else /* !CONFIG_SUSPEND */
 static inline int suspend_devices_and_enter(suspend_state_t state)
 {
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 396d262..de4fedb 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -261,20 +261,15 @@ static void suspend_finish(void)
  * enter_state - Do common work needed to enter system sleep state.
  * @state: System sleep state to enter.
  *
- * Make sure that no one else is trying to put the system into a sleep state.
- * Fail if that's not the case.  Otherwise, prepare for system suspend, make the
- * system enter the given sleep state and clean up after wakeup.
+ * The system lock needs to be held already when this function is called.
  */
-static int enter_state(suspend_state_t state)
+static int enter_state_locked(suspend_state_t state)
 {
 	int error;
 
 	if (!valid_state(state))
 		return -ENODEV;
 
-	if (!mutex_trylock(&pm_mutex))
-		return -EBUSY;
-
 	printk(KERN_INFO "PM: Syncing filesystems ... ");
 	sys_sync();
 	printk("done.\n");
@@ -282,7 +277,7 @@ static int enter_state(suspend_state_t state)
 	pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
 	error = suspend_prepare();
 	if (error)
-		goto Unlock;
+		return error;
 
 	if (suspend_test(TEST_FREEZER))
 		goto Finish;
@@ -295,26 +290,50 @@ static int enter_state(suspend_state_t state)
  Finish:
 	pr_debug("PM: Finishing wakeup.\n");
 	suspend_finish();
- Unlock:
+	return error;
+}
+
+/**
+ * enter_state - Do common work needed to enter system sleep state.
+ * @state: System sleep state to enter.
+ *
+ * Make sure that no one else is trying to put the system into a sleep state.
+ * Fail if that's not the case.  Otherwise, prepare for system suspend, make the
+ * system enter the given sleep state and clean up after wakeup.
+ */
+static int enter_state(suspend_state_t state)
+{
+	int error;
+
+	if (!valid_state(state))
+		return -ENODEV;
+
+	if (!mutex_trylock(&pm_mutex))
+		return -EBUSY;
+
+	error = enter_state_locked(state);
+
 	mutex_unlock(&pm_mutex);
 	return error;
 }
 
 /**
- * pm_suspend - Externally visible function for suspending the system.
+ * suspend - Suspend the system.
  * @state: System sleep state to enter.
+ * @lock:  Whether to acquire a system lock.
  *
  * Check if the value of @state represents one of the supported states,
- * execute enter_state() and update system suspend statistics.
+ * execute enter_state() or enter_state_locked() and update system suspend
+ * statistics.
  */
-int pm_suspend(suspend_state_t state)
+static int suspend(suspend_state_t state, int lock)
 {
 	int error;
 
 	if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
 		return -EINVAL;
 
-	error = enter_state(state);
+	error = lock ? enter_state(state) : enter_state_locked(state);
 	if (error) {
 		suspend_stats.fail++;
 		dpm_save_failed_errno(error);
@@ -323,4 +342,30 @@ int pm_suspend(suspend_state_t state)
 	}
 	return error;
 }
+
+/**
+ * suspend_locked - Suspend the system when the system lock is already held.
+ * @state: System sleep state to enter.
+ *
+ * Check if the value of @state represents one of the supported states,
+ * execute enter_state_locked() and update system suspend statistics.
+ */
+#ifdef CONFIG_HIBERNATION
+int suspend_locked(suspend_state_t state)
+{
+	return suspend(state, 0);
+}
+#endif
+
+/**
+ * pm_suspend - Externally visible function for suspending the system.
+ * @state: System sleep state to enter.
+ *
+ * Check if the value of @state represents one of the supported states,
+ * execute enter_state() and update system suspend statistics.
+ */
+int pm_suspend(suspend_state_t state)
+{
+	return suspend(state, 1);
+}
 EXPORT_SYMBOL(pm_suspend);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index eef311a..1027da8 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -1456,6 +1456,34 @@ void swsusp_close(fmode_t mode)
 	blkdev_put(hib_resume_bdev, mode);
 }
 
+/**
+ *      swsusp_unmark - Unmark swsusp signature in the resume device
+ */
+
+#ifdef CONFIG_SUSPEND
+int swsusp_unmark(void)
+{
+	int error;
+
+	hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL);
+	if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) {
+		memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10);
+		error = hib_bio_write_page(swsusp_resume_block,
+					swsusp_header, NULL);
+	} else {
+		printk(KERN_ERR "PM: Cannot find swsusp signature!\n");
+		error = -ENODEV;
+	}
+
+	/*
+	 * We just returned from suspend, we don't need the image any more.
+	 */
+	free_all_swap_pages(root_swap);
+
+	return error;
+}
+#endif
+
 static int swsusp_header_init(void)
 {
 	swsusp_header = (struct swsusp_header*) __get_free_page(GFP_KERNEL);
-------------------

-- 
Bojan


  reply	other threads:[~2012-05-14 11:11 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-08 22:22 [PATCH]: In kernel hibernation, suspend to both Bojan Smojver
2012-05-09  8:10 ` Srivatsa S. Bhat
2012-05-09 10:49   ` Bojan Smojver
2012-05-09 11:11     ` Bojan Smojver
2012-05-13 23:32       ` Srivatsa S. Bhat
2012-05-14  1:02         ` Bojan Smojver
2012-05-14  2:25           ` Alan Stern
2012-05-14  2:37             ` Bojan Smojver
2012-05-14  2:46               ` Bojan Smojver
2012-05-14  2:58                 ` Bojan Smojver
2012-05-14  7:45                   ` Bojan Smojver
2012-05-14 11:11                     ` Bojan Smojver [this message]
2012-05-14 11:47                       ` Bojan Smojver
2012-05-14 23:59                         ` Bojan Smojver
2012-05-15 14:26                           ` Alan Stern
2012-05-15 14:35                           ` Srivatsa S. Bhat
2012-05-15 17:42                             ` Rafael J. Wysocki
2012-05-15 18:23                               ` Srivatsa S. Bhat
2012-05-15 22:23                               ` Bojan Smojver
2012-05-21  4:38                                 ` Bojan Smojver
2012-05-21  8:18                                   ` Borislav Petkov
2012-05-21 13:18                                   ` Rafael J. Wysocki
2012-05-21 21:43                                     ` Bojan Smojver
2012-05-21 21:53                                       ` Rafael J. Wysocki
2012-05-21 21:55                                         ` Bojan Smojver
2012-05-24 14:51                                           ` Borislav Petkov
2012-05-25  2:02                                             ` Bojan Smojver
2012-05-31 16:23                                               ` Borislav Petkov
2012-06-01  2:03                                                 ` Bojan Smojver
2012-06-01  8:48                                                   ` Borislav Petkov
2012-06-01  8:57                                                     ` Bojan Smojver
2012-06-01  9:03                                                       ` Borislav Petkov
2012-06-16 13:59                                               ` Rafael J. Wysocki
2012-06-16 17:39                                                 ` Borislav Petkov
2012-06-16 19:17                                                   ` Rafael J. Wysocki
2012-06-16 20:09                                                     ` Bojan Smojver
2012-06-16 20:19                                                       ` Alan Stern
2012-06-16 23:07                                                         ` Borislav Petkov
2012-06-17  3:21                                                           ` Bojan Smojver
2012-06-17 10:31                                                             ` Borislav Petkov
2012-06-17 20:21                                                             ` Rafael J. Wysocki
2012-06-18  0:33                                                               ` Bojan Smojver
2012-06-18 12:32                                                                 ` Borislav Petkov
2012-06-18 20:29                                                                   ` Rafael J. Wysocki
2012-06-18 21:08                                                                     ` Bojan Smojver
2012-06-18 21:28                                                                       ` Rafael J. Wysocki
2012-06-19  2:09                                                                         ` Bojan Smojver
2012-06-19 14:21                                                                           ` Borislav Petkov
2012-06-19 14:32                                                                             ` Bojan Smojver
2012-06-19 20:23                                                                               ` Rafael J. Wysocki
2012-06-19 21:32                                                                                 ` Bojan Smojver
2012-06-19 22:35                                                                         ` Bojan Smojver
2012-05-12 21:47     ` Rafael J. Wysocki
2012-05-13  1:37       ` Bojan Smojver
2012-05-13 13:10         ` Rafael J. Wysocki
2012-05-13 23:18           ` Bojan Smojver
2012-05-13 23:49             ` Srivatsa S. Bhat
2012-05-14  0:39               ` Bojan Smojver

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1336993890.1662.1.camel@shrek.rexursive.com \
    --to=bojan@rexursive.com \
    --cc=bp@alien8.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rjw@sisk.pl \
    --cc=srivatsa.bhat@linux.vnet.ibm.com \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.