diff options
Diffstat (limited to 'kernel/power/hibernate.c')
| -rw-r--r-- | kernel/power/hibernate.c | 50 | 
1 files changed, 42 insertions, 8 deletions
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 8b53db38a279..b26f5f1e773e 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.   */ @@ -27,7 +28,6 @@  #include <linux/syscore_ops.h>  #include <linux/ctype.h>  #include <linux/genhd.h> -#include <scsi/scsi_scan.h>  #include "power.h" @@ -46,6 +46,9 @@ enum {  	HIBERNATION_PLATFORM,  	HIBERNATION_SHUTDOWN,  	HIBERNATION_REBOOT, +#ifdef CONFIG_SUSPEND +	HIBERNATION_SUSPEND, +#endif  	/* keep last */  	__HIBERNATION_AFTER_LAST  }; @@ -354,6 +357,7 @@ int hibernation_snapshot(int platform_mode)  	}  	suspend_console(); +	ftrace_stop();  	pm_restrict_gfp_mask();  	error = dpm_suspend(PMSG_FREEZE); @@ -379,6 +383,7 @@ int hibernation_snapshot(int platform_mode)  	if (error || !in_suspend)  		pm_restore_gfp_mask(); +	ftrace_start();  	resume_console();  	dpm_complete(msg); @@ -481,6 +486,7 @@ int hibernation_restore(int platform_mode)  	pm_prepare_console();  	suspend_console(); +	ftrace_stop();  	pm_restrict_gfp_mask();  	error = dpm_suspend_start(PMSG_QUIESCE);  	if (!error) { @@ -488,6 +494,7 @@ int hibernation_restore(int platform_mode)  		dpm_resume_end(PMSG_RECOVER);  	}  	pm_restore_gfp_mask(); +	ftrace_start();  	resume_console();  	pm_restore_console();  	return error; @@ -514,6 +521,7 @@ int hibernation_platform_enter(void)  	entering_platform_hibernation = true;  	suspend_console(); +	ftrace_stop();  	error = dpm_suspend_start(PMSG_HIBERNATE);  	if (error) {  		if (hibernation_ops->recover) @@ -557,6 +565,7 @@ int hibernation_platform_enter(void)   Resume_devices:  	entering_platform_hibernation = false;  	dpm_resume_end(PMSG_RESTORE); +	ftrace_start();  	resume_console();   Close: @@ -574,6 +583,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); @@ -583,6 +596,25 @@ static void power_down(void)  	case HIBERNATION_SHUTDOWN:  		kernel_power_off();  		break; +#ifdef CONFIG_SUSPEND +	case HIBERNATION_SUSPEND: +		error = suspend_devices_and_enter(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();  	/* @@ -748,13 +780,6 @@ static int software_resume(void)  			async_synchronize_full();  		} -		/* -		 * We can't depend on SCSI devices being available after loading -		 * one of their modules until scsi_complete_async_scans() is -		 * called and the resume device usually is a SCSI one. -		 */ -		scsi_complete_async_scans(); -  		swsusp_resume_device = name_to_dev_t(resume_file);  		if (!swsusp_resume_device) {  			error = -ENODEV; @@ -827,6 +852,9 @@ static const char * const hibernation_modes[] = {  	[HIBERNATION_PLATFORM]	= "platform",  	[HIBERNATION_SHUTDOWN]	= "shutdown",  	[HIBERNATION_REBOOT]	= "reboot", +#ifdef CONFIG_SUSPEND +	[HIBERNATION_SUSPEND]	= "suspend", +#endif  };  /* @@ -867,6 +895,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) @@ -907,6 +938,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:  | 
