Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7777fab9 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds
Browse files

swsusp: remove code duplication between disk.c and user.c



Currently, much of the code in kernel/power/disk.c is duplicated in
kernel/power/user.c , mainly for historical reasons.  By eliminating this code
duplication we can reduce the size of user.c quite substantially and remove
the maintenance difficulty resulting from it.

[bunk@stusta.de: kernel/power/disk.c: make code static]
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Acked-by: default avatarPavel Machek <pavel@ucw.cz>
Cc: Nigel Cunningham <nigel@nigel.suspend2.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 127067a9
Loading
Loading
Loading
Loading
+104 −80
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ enum {

static int hibernation_mode = HIBERNATION_SHUTDOWN;

struct hibernation_ops *hibernation_ops;
static struct hibernation_ops *hibernation_ops;

/**
 * hibernation_set_ops - set the global hibernate operations
@@ -74,9 +74,9 @@ void hibernation_set_ops(struct hibernation_ops *ops)
 *	platform driver if so configured and return an error code if it fails
 */

static int platform_prepare(void)
static int platform_prepare(int platform_mode)
{
	return (hibernation_mode == HIBERNATION_PLATFORM && hibernation_ops) ?
	return (platform_mode && hibernation_ops) ?
		hibernation_ops->prepare() : 0;
}

@@ -85,12 +85,103 @@ static int platform_prepare(void)
 *	using the platform driver (must be called after platform_prepare())
 */

static void platform_finish(void)
static void platform_finish(int platform_mode)
{
	if (hibernation_mode == HIBERNATION_PLATFORM && hibernation_ops)
	if (platform_mode && hibernation_ops)
		hibernation_ops->finish();
}

/**
 *	hibernation_snapshot - quiesce devices and create the hibernation
 *	snapshot image.
 *	@platform_mode - if set, use the platform driver, if available, to
 *			 prepare the platform frimware for the power transition.
 *
 *	Must be called with pm_mutex held
 */

int hibernation_snapshot(int platform_mode)
{
	int error;

	/* Free memory before shutting down devices. */
	error = swsusp_shrink_memory();
	if (error)
		goto Finish;

	error = platform_prepare(platform_mode);
	if (error)
		goto Finish;

	suspend_console();
	error = device_suspend(PMSG_FREEZE);
	if (error)
		goto Resume_devices;

	error = disable_nonboot_cpus();
	if (!error) {
		if (hibernation_mode != HIBERNATION_TEST) {
			in_suspend = 1;
			error = swsusp_suspend();
			/* Control returns here after successful restore */
		} else {
			printk("swsusp debug: Waiting for 5 seconds.\n");
			mdelay(5000);
		}
	}
	enable_nonboot_cpus();
 Resume_devices:
	platform_finish(platform_mode);
	device_resume();
	resume_console();
 Finish:
	return error;
}

/**
 *	hibernation_restore - quiesce devices and restore the hibernation
 *	snapshot image.  If successful, control returns in hibernation_snaphot()
 *
 *	Must be called with pm_mutex held
 */

int hibernation_restore(void)
{
	int error;

	pm_prepare_console();
	suspend_console();
	error = device_suspend(PMSG_PRETHAW);
	if (error)
		goto Finish;

	error = disable_nonboot_cpus();
	if (!error)
		error = swsusp_resume();

	enable_nonboot_cpus();
 Finish:
	device_resume();
	resume_console();
	pm_restore_console();
	return error;
}

/**
 *	hibernation_platform_enter - enter the hibernation state using the
 *	platform driver (if available)
 */

int hibernation_platform_enter(void)
{
	if (hibernation_ops) {
		kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
		return hibernation_ops->enter();
	} else {
		return -ENOSYS;
	}
}

/**
 *	power_down - Shut the machine down for hibernation.
 *
@@ -111,11 +202,7 @@ static void power_down(void)
		kernel_restart(NULL);
		break;
	case HIBERNATION_PLATFORM:
		if (hibernation_ops) {
			kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
			hibernation_ops->enter();
			break;
		}
		hibernation_platform_enter();
	}
	kernel_halt();
	/*
@@ -171,62 +258,17 @@ int hibernate(void)
		mdelay(5000);
		goto Thaw;
	}

	/* Free memory before shutting down devices. */
	error = swsusp_shrink_memory();
	if (error)
		goto Thaw;

	error = platform_prepare();
	if (error)
		goto Thaw;

	suspend_console();
	error = device_suspend(PMSG_FREEZE);
	if (error) {
		printk(KERN_ERR "PM: Some devices failed to suspend\n");
		goto Resume_devices;
	}
	error = disable_nonboot_cpus();
	if (error)
		goto Enable_cpus;

	if (hibernation_mode == HIBERNATION_TEST) {
		printk("swsusp debug: Waiting for 5 seconds.\n");
		mdelay(5000);
		goto Enable_cpus;
	}

	pr_debug("PM: snapshotting memory.\n");
	in_suspend = 1;
	error = swsusp_suspend();
	if (error)
		goto Enable_cpus;

	if (in_suspend) {
		enable_nonboot_cpus();
		platform_finish();
		device_resume();
		resume_console();
	error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
	if (in_suspend && !error) {
		pr_debug("PM: writing image.\n");
		error = swsusp_write();
		swsusp_free();
		if (!error)
			power_down();
		else {
			swsusp_free();
			goto Thaw;
		}
	} else {
		pr_debug("PM: Image restored successfully.\n");
	}

		swsusp_free();
 Enable_cpus:
	enable_nonboot_cpus();
 Resume_devices:
	platform_finish();
	device_resume();
	resume_console();
	}
 Thaw:
	mutex_unlock(&pm_mutex);
	unprepare_processes();
@@ -301,29 +343,11 @@ static int software_resume(void)
	pr_debug("PM: Reading swsusp image.\n");

	error = swsusp_read();
	if (error) {
		swsusp_free();
		goto Thaw;
	}

	pr_debug("PM: Preparing devices for restore.\n");

	suspend_console();
	error = device_suspend(PMSG_PRETHAW);
	if (error)
		goto Free;

	error = disable_nonboot_cpus();
	if (!error)
		swsusp_resume();
		hibernation_restore();

	enable_nonboot_cpus();
 Free:
	swsusp_free();
	device_resume();
	resume_console();
 Thaw:
	printk(KERN_ERR "PM: Restore failed, recovering.\n");
	swsusp_free();
	unprepare_processes();
 Done:
	free_basic_memory_bitmaps();
@@ -333,7 +357,7 @@ static int software_resume(void)
 Unlock:
	mutex_unlock(&pm_mutex);
	pr_debug("PM: Resume from disk failed.\n");
	return 0;
	return error;
}

late_initcall(software_resume);
+4 −1
Original line number Diff line number Diff line
@@ -25,7 +25,10 @@ struct swsusp_info {
 */
#define SPARE_PAGES	((1024 * 1024) >> PAGE_SHIFT)

extern struct hibernation_ops *hibernation_ops;
/* kernel/power/disk.c */
extern int hibernation_snapshot(int platform_mode);
extern int hibernation_restore(void);
extern int hibernation_platform_enter(void);
#endif

extern int pfn_is_nosave(unsigned long);
+7 −89
Original line number Diff line number Diff line
@@ -128,83 +128,6 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf,
	return res;
}

static inline int platform_prepare(void)
{
	int error = 0;

	if (hibernation_ops)
		error = hibernation_ops->prepare();

	return error;
}

static inline void platform_finish(void)
{
	if (hibernation_ops)
		hibernation_ops->finish();
}

static inline int snapshot_suspend(int platform_suspend)
{
	int error;

	mutex_lock(&pm_mutex);
	/* Free memory before shutting down devices. */
	error = swsusp_shrink_memory();
	if (error)
		goto Finish;

	if (platform_suspend) {
		error = platform_prepare();
		if (error)
			goto Finish;
	}
	suspend_console();
	error = device_suspend(PMSG_FREEZE);
	if (error)
		goto Resume_devices;

	error = disable_nonboot_cpus();
	if (!error) {
		in_suspend = 1;
		error = swsusp_suspend();
	}
	enable_nonboot_cpus();
 Resume_devices:
	if (platform_suspend)
		platform_finish();

	device_resume();
	resume_console();
 Finish:
	mutex_unlock(&pm_mutex);
	return error;
}

static inline int snapshot_restore(void)
{
	int error;

	mutex_lock(&pm_mutex);
	pm_prepare_console();
	suspend_console();
	error = device_suspend(PMSG_PRETHAW);
	if (error)
		goto Finish;

	error = disable_nonboot_cpus();
	if (!error)
		error = swsusp_resume();

	enable_nonboot_cpus();
 Finish:
	device_resume();
	resume_console();
	pm_restore_console();
	mutex_unlock(&pm_mutex);
	return error;
}

static int snapshot_ioctl(struct inode *inode, struct file *filp,
                          unsigned int cmd, unsigned long arg)
{
@@ -251,7 +174,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
			error = -EPERM;
			break;
		}
		error = snapshot_suspend(data->platform_suspend);
		error = hibernation_snapshot(data->platform_suspend);
		if (!error)
			error = put_user(in_suspend, (unsigned int __user *)arg);
		if (!error)
@@ -265,7 +188,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
			error = -EPERM;
			break;
		}
		error = snapshot_restore();
		error = hibernation_restore();
		break;

	case SNAPSHOT_FREE:
@@ -377,19 +300,14 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
		switch (arg) {

		case PMOPS_PREPARE:
			if (hibernation_ops) {
			data->platform_suspend = 1;
			error = 0;
			} else {
				error = -ENOSYS;
			}
			break;

		case PMOPS_ENTER:
			if (data->platform_suspend) {
				kernel_shutdown_prepare(SYSTEM_SUSPEND_DISK);
				error = hibernation_ops->enter();
			}
			if (data->platform_suspend)
				error = hibernation_platform_enter();

			break;

		case PMOPS_FINISH: