2005-04-17 02:20:36 +04:00
/*
* kernel / power / main . c - PM subsystem core functionality .
*
* Copyright ( c ) 2003 Patrick Mochel
* Copyright ( c ) 2003 Open Source Development Lab
*
* This file is released under the GPLv2
*
*/
2006-12-07 07:36:06 +03:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/suspend.h>
# include <linux/kobject.h>
# include <linux/string.h>
# include <linux/delay.h>
# include <linux/errno.h>
# include <linux/init.h>
2006-06-23 01:47:18 +04:00
# include <linux/console.h>
2006-09-26 10:32:48 +04:00
# include <linux/cpu.h>
2006-09-26 10:32:58 +04:00
# include <linux/resume-trace.h>
2006-12-07 07:34:23 +03:00
# include <linux/freezer.h>
2007-02-10 12:43:03 +03:00
# include <linux/vmstat.h>
2007-10-18 14:04:44 +04:00
# include <linux/syscalls.h>
2005-04-17 02:20:36 +04:00
# include "power.h"
2006-12-07 07:34:35 +03:00
DEFINE_MUTEX ( pm_mutex ) ;
2005-04-17 02:20:36 +04:00
2007-12-14 01:38:03 +03:00
unsigned int pm_flags ;
EXPORT_SYMBOL ( pm_flags ) ;
2007-11-20 01:49:18 +03:00
# ifdef CONFIG_PM_SLEEP
/* Routines for PM-transition notifications */
static BLOCKING_NOTIFIER_HEAD ( pm_chain_head ) ;
int register_pm_notifier ( struct notifier_block * nb )
{
return blocking_notifier_chain_register ( & pm_chain_head , nb ) ;
}
EXPORT_SYMBOL_GPL ( register_pm_notifier ) ;
int unregister_pm_notifier ( struct notifier_block * nb )
{
return blocking_notifier_chain_unregister ( & pm_chain_head , nb ) ;
}
EXPORT_SYMBOL_GPL ( unregister_pm_notifier ) ;
int pm_notifier_call_chain ( unsigned long val )
{
return ( blocking_notifier_call_chain ( & pm_chain_head , val , NULL )
= = NOTIFY_BAD ) ? - EINVAL : 0 ;
}
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
# ifdef CONFIG_PM_DEBUG
int pm_test_level = TEST_NONE ;
static int suspend_test ( int level )
{
if ( pm_test_level = = level ) {
printk ( KERN_INFO " suspend debug: Waiting for 5 seconds. \n " ) ;
mdelay ( 5000 ) ;
return 1 ;
}
return 0 ;
}
static const char * const pm_tests [ __TEST_AFTER_LAST ] = {
[ TEST_NONE ] = " none " ,
[ TEST_CORE ] = " core " ,
[ TEST_CPUS ] = " processors " ,
[ TEST_PLATFORM ] = " platform " ,
[ TEST_DEVICES ] = " devices " ,
[ TEST_FREEZER ] = " freezer " ,
} ;
2008-01-29 02:29:06 +03:00
static ssize_t pm_test_show ( struct kobject * kobj , struct kobj_attribute * attr ,
char * buf )
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
{
char * s = buf ;
int level ;
for ( level = TEST_FIRST ; level < = TEST_MAX ; level + + )
if ( pm_tests [ level ] ) {
if ( level = = pm_test_level )
s + = sprintf ( s , " [%s] " , pm_tests [ level ] ) ;
else
s + = sprintf ( s , " %s " , pm_tests [ level ] ) ;
}
if ( s ! = buf )
/* convert the last space to a newline */
* ( s - 1 ) = ' \n ' ;
return ( s - buf ) ;
}
2008-01-29 02:29:06 +03:00
static ssize_t pm_test_store ( struct kobject * kobj , struct kobj_attribute * attr ,
const char * buf , size_t n )
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
{
const char * const * s ;
int level ;
char * p ;
int len ;
int error = - EINVAL ;
p = memchr ( buf , ' \n ' , n ) ;
len = p ? p - buf : n ;
mutex_lock ( & pm_mutex ) ;
level = TEST_FIRST ;
for ( s = & pm_tests [ level ] ; level < = TEST_MAX ; s + + , level + + )
if ( * s & & len = = strlen ( * s ) & & ! strncmp ( buf , * s , len ) ) {
pm_test_level = level ;
error = 0 ;
break ;
}
mutex_unlock ( & pm_mutex ) ;
return error ? error : n ;
}
power_attr ( pm_test ) ;
# else /* !CONFIG_PM_DEBUG */
static inline int suspend_test ( int level ) { return 0 ; }
# endif /* !CONFIG_PM_DEBUG */
2007-12-14 03:07:13 +03:00
# endif /* CONFIG_PM_SLEEP */
2008-01-29 02:29:06 +03:00
2007-07-30 01:27:18 +04:00
# ifdef CONFIG_SUSPEND
/* This is just an arbitrary number */
# define FREE_PAGE_NUMBER (100)
2007-10-18 14:04:41 +04:00
static struct platform_suspend_ops * suspend_ops ;
2005-04-17 02:20:36 +04:00
/**
2007-10-18 14:04:40 +04:00
* suspend_set_ops - Set the global suspend method table .
2005-04-17 02:20:36 +04:00
* @ ops : Pointer to ops structure .
*/
2007-10-18 14:04:40 +04:00
void suspend_set_ops ( struct platform_suspend_ops * ops )
2005-04-17 02:20:36 +04:00
{
2006-12-07 07:34:35 +03:00
mutex_lock ( & pm_mutex ) ;
2007-10-18 14:04:40 +04:00
suspend_ops = ops ;
2006-12-07 07:34:35 +03:00
mutex_unlock ( & pm_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2007-05-01 02:09:54 +04:00
/**
2007-10-18 14:04:40 +04:00
* suspend_valid_only_mem - generic memory - only valid callback
2007-05-01 02:09:54 +04:00
*
2007-10-18 14:04:40 +04:00
* Platform drivers that implement mem suspend only and only need
2007-05-01 02:09:54 +04:00
* to check for that in their . valid callback can use this instead
* of rolling their own . valid callback .
*/
2007-10-18 14:04:40 +04:00
int suspend_valid_only_mem ( suspend_state_t state )
2007-05-01 02:09:54 +04:00
{
return state = = PM_SUSPEND_MEM ;
}
2005-04-17 02:20:36 +04:00
/**
* suspend_prepare - Do prep work before entering low - power state .
*
2007-07-19 12:47:38 +04:00
* This is common code that is called for each state that we ' re entering .
* Run suspend notifiers , allocate a console and stop all processes .
2005-04-17 02:20:36 +04:00
*/
2007-07-19 12:47:38 +04:00
static int suspend_prepare ( void )
2005-04-17 02:20:36 +04:00
{
2006-09-26 10:32:48 +04:00
int error ;
2005-03-19 00:27:13 +03:00
unsigned int free_pages ;
2005-04-17 02:20:36 +04:00
2007-10-18 14:04:40 +04:00
if ( ! suspend_ops | | ! suspend_ops - > enter )
2005-04-17 02:20:36 +04:00
return - EPERM ;
2008-01-11 03:22:23 +03:00
pm_prepare_console ( ) ;
2007-07-19 12:47:36 +04:00
error = pm_notifier_call_chain ( PM_SUSPEND_PREPARE ) ;
if ( error )
goto Finish ;
2008-01-16 07:17:00 +03:00
if ( suspend_freeze_processes ( ) ) {
2005-04-17 02:20:36 +04:00
error = - EAGAIN ;
goto Thaw ;
}
2007-07-19 12:47:38 +04:00
free_pages = global_page_state ( NR_FREE_PAGES ) ;
if ( free_pages < FREE_PAGE_NUMBER ) {
2005-03-19 00:27:13 +03:00
pr_debug ( " PM: free some memory \n " ) ;
shrink_all_memory ( FREE_PAGE_NUMBER - free_pages ) ;
if ( nr_free_pages ( ) < FREE_PAGE_NUMBER ) {
error = - ENOMEM ;
printk ( KERN_ERR " PM: No enough memory \n " ) ;
}
}
2007-02-10 12:43:31 +03:00
if ( ! error )
return 0 ;
2005-04-17 02:20:36 +04:00
Thaw :
2008-01-16 07:17:00 +03:00
suspend_thaw_processes ( ) ;
2007-07-19 12:47:36 +04:00
Finish :
pm_notifier_call_chain ( PM_POST_SUSPEND ) ;
2008-01-11 03:22:23 +03:00
pm_restore_console ( ) ;
2005-04-17 02:20:36 +04:00
return error ;
}
2007-04-26 13:43:58 +04:00
/* default implementation */
void __attribute__ ( ( weak ) ) arch_suspend_disable_irqs ( void )
{
local_irq_disable ( ) ;
}
/* default implementation */
void __attribute__ ( ( weak ) ) arch_suspend_enable_irqs ( void )
{
local_irq_enable ( ) ;
}
2005-04-17 02:20:36 +04:00
2007-07-19 12:47:38 +04:00
/**
* suspend_enter - enter the desired system sleep state .
* @ state : state to enter
*
* This function should be called after devices have been suspended .
*/
2007-10-18 14:04:37 +04:00
static int suspend_enter ( suspend_state_t state )
2005-04-17 02:20:36 +04:00
{
int error = 0 ;
2007-04-26 13:43:58 +04:00
arch_suspend_disable_irqs ( ) ;
BUG_ON ( ! irqs_disabled ( ) ) ;
2005-04-17 02:20:36 +04:00
if ( ( error = device_power_down ( PMSG_SUSPEND ) ) ) {
2007-12-08 04:08:38 +03:00
printk ( KERN_ERR " PM: Some devices failed to power down \n " ) ;
2005-04-17 02:20:36 +04:00
goto Done ;
}
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
if ( ! suspend_test ( TEST_CORE ) )
error = suspend_ops - > enter ( state ) ;
2005-04-17 02:20:36 +04:00
device_power_up ( ) ;
Done :
2007-04-26 13:43:58 +04:00
arch_suspend_enable_irqs ( ) ;
BUG_ON ( irqs_disabled ( ) ) ;
2005-04-17 02:20:36 +04:00
return error ;
}
2007-07-19 12:47:38 +04:00
/**
2007-12-08 04:06:00 +03:00
* suspend_devices_and_enter - suspend devices and enter the desired system
* sleep state .
2007-07-19 12:47:38 +04:00
* @ state : state to enter
*/
int suspend_devices_and_enter ( suspend_state_t state )
{
int error ;
2007-10-18 14:04:40 +04:00
if ( ! suspend_ops )
2007-07-19 12:47:38 +04:00
return - ENOSYS ;
2008-01-08 02:04:17 +03:00
if ( suspend_ops - > begin ) {
error = suspend_ops - > begin ( state ) ;
2007-07-19 12:47:38 +04:00
if ( error )
2008-01-08 02:04:17 +03:00
goto Close ;
2007-07-19 12:47:38 +04:00
}
suspend_console ( ) ;
error = device_suspend ( PMSG_SUSPEND ) ;
if ( error ) {
2007-12-08 04:08:38 +03:00
printk ( KERN_ERR " PM: Some devices failed to suspend \n " ) ;
2007-07-19 12:47:38 +04:00
goto Resume_console ;
}
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
if ( suspend_test ( TEST_DEVICES ) )
goto Resume_devices ;
2007-10-18 14:04:40 +04:00
if ( suspend_ops - > prepare ) {
2007-10-18 14:04:41 +04:00
error = suspend_ops - > prepare ( ) ;
2007-07-19 12:47:38 +04:00
if ( error )
goto Resume_devices ;
}
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
if ( suspend_test ( TEST_PLATFORM ) )
goto Finish ;
2007-07-19 12:47:38 +04:00
error = disable_nonboot_cpus ( ) ;
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
if ( ! error & & ! suspend_test ( TEST_CPUS ) )
2007-07-19 12:47:38 +04:00
suspend_enter ( state ) ;
enable_nonboot_cpus ( ) ;
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
Finish :
2007-10-18 14:04:41 +04:00
if ( suspend_ops - > finish )
suspend_ops - > finish ( ) ;
2007-07-19 12:47:38 +04:00
Resume_devices :
device_resume ( ) ;
Resume_console :
resume_console ( ) ;
2008-01-08 02:04:17 +03:00
Close :
if ( suspend_ops - > end )
suspend_ops - > end ( ) ;
2007-07-19 12:47:38 +04:00
return error ;
}
2005-04-17 02:20:36 +04:00
/**
* suspend_finish - Do final work before exiting suspend sequence .
*
* Call platform code to clean up , restart processes , and free the
* console that we ' ve allocated . This is not called for suspend - to - disk .
*/
2007-07-19 12:47:38 +04:00
static void suspend_finish ( void )
2005-04-17 02:20:36 +04:00
{
2008-01-16 07:17:00 +03:00
suspend_thaw_processes ( ) ;
2007-07-19 12:47:36 +04:00
pm_notifier_call_chain ( PM_POST_SUSPEND ) ;
2008-01-11 03:22:23 +03:00
pm_restore_console ( ) ;
2005-04-17 02:20:36 +04:00
}
2006-06-25 16:47:56 +04:00
static const char * const pm_states [ PM_SUSPEND_MAX ] = {
2005-04-17 02:20:36 +04:00
[ PM_SUSPEND_STANDBY ] = " standby " ,
[ PM_SUSPEND_MEM ] = " mem " ,
} ;
2005-11-30 06:34:37 +03:00
static inline int valid_state ( suspend_state_t state )
{
2007-05-09 13:33:18 +04:00
/* All states need lowlevel support and need to be valid
* to the lowlevel implementation , no valid callback
2007-05-01 02:09:55 +04:00
* implies that none are valid . */
2007-10-18 14:04:40 +04:00
if ( ! suspend_ops | | ! suspend_ops - > valid | | ! suspend_ops - > valid ( state ) )
2005-11-30 06:34:37 +03:00
return 0 ;
return 1 ;
}
2005-04-17 02:20:36 +04:00
/**
* enter_state - Do common work of entering low - power state .
* @ state : pm_state structure for state we ' re entering .
*
* Make sure we ' re the only ones trying to enter a sleep state . Fail
* if someone has beat us to it , since we don ' t want anything weird to
* happen when we wake up .
* Then , do the setup for suspend , enter the state , and cleaup ( after
* we ' ve woken up ) .
*/
static int enter_state ( suspend_state_t state )
{
int error ;
2005-11-30 06:34:37 +03:00
if ( ! valid_state ( state ) )
2005-10-31 02:00:01 +03:00
return - ENODEV ;
2007-10-18 14:04:44 +04:00
2006-12-07 07:34:35 +03:00
if ( ! mutex_trylock ( & pm_mutex ) )
2005-04-17 02:20:36 +04:00
return - EBUSY ;
2007-12-08 04:08:38 +03:00
printk ( KERN_INFO " PM: Syncing filesystems ... " ) ;
2007-10-18 14:04:44 +04:00
sys_sync ( ) ;
printk ( " done. \n " ) ;
2005-05-09 19:07:00 +04:00
pr_debug ( " PM: Preparing system for %s sleep \n " , pm_states [ state ] ) ;
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
error = suspend_prepare ( ) ;
if ( error )
2005-04-17 02:20:36 +04:00
goto Unlock ;
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
if ( suspend_test ( TEST_FREEZER ) )
goto Finish ;
2005-05-09 19:07:00 +04:00
pr_debug ( " PM: Entering %s sleep \n " , pm_states [ state ] ) ;
2007-07-19 12:47:38 +04:00
error = suspend_devices_and_enter ( state ) ;
2005-04-17 02:20:36 +04:00
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
Finish :
2005-05-09 19:07:00 +04:00
pr_debug ( " PM: Finishing wakeup. \n " ) ;
2007-07-19 12:47:38 +04:00
suspend_finish ( ) ;
2005-04-17 02:20:36 +04:00
Unlock :
2006-12-07 07:34:35 +03:00
mutex_unlock ( & pm_mutex ) ;
2005-04-17 02:20:36 +04:00
return error ;
}
/**
* pm_suspend - Externally visible function for suspending system .
2007-05-09 13:33:18 +04:00
* @ state : Enumerated value of state to enter .
2005-04-17 02:20:36 +04:00
*
* Determine whether or not value is within range , get state
* structure , and enter ( above ) .
*/
int pm_suspend ( suspend_state_t state )
{
2005-03-19 00:20:46 +03:00
if ( state > PM_SUSPEND_ON & & state < = PM_SUSPEND_MAX )
2005-04-17 02:20:36 +04:00
return enter_state ( state ) ;
return - EINVAL ;
}
2006-12-07 07:36:06 +03:00
EXPORT_SYMBOL ( pm_suspend ) ;
2005-04-17 02:20:36 +04:00
2007-07-30 01:27:18 +04:00
# endif /* CONFIG_SUSPEND */
2007-11-27 22:28:26 +03:00
struct kobject * power_kobj ;
2005-04-17 02:20:36 +04:00
/**
* state - control system power state .
*
* show ( ) returns what states are supported , which is hard - coded to
* ' standby ' ( Power - On Suspend ) , ' mem ' ( Suspend - to - RAM ) , and
* ' disk ' ( Suspend - to - Disk ) .
*
* store ( ) accepts one of those strings , translates it into the
* proper enumerated value , and initiates a suspend transition .
*/
2007-11-02 15:47:53 +03:00
static ssize_t state_show ( struct kobject * kobj , struct kobj_attribute * attr ,
char * buf )
2005-04-17 02:20:36 +04:00
{
2007-07-30 01:27:18 +04:00
char * s = buf ;
# ifdef CONFIG_SUSPEND
2005-04-17 02:20:36 +04:00
int i ;
for ( i = 0 ; i < PM_SUSPEND_MAX ; i + + ) {
2005-11-30 06:34:37 +03:00
if ( pm_states [ i ] & & valid_state ( i ) )
s + = sprintf ( s , " %s " , pm_states [ i ] ) ;
2005-04-17 02:20:36 +04:00
}
2007-07-30 01:27:18 +04:00
# endif
2007-07-30 01:24:36 +04:00
# ifdef CONFIG_HIBERNATION
2007-05-09 13:33:18 +04:00
s + = sprintf ( s , " %s \n " , " disk " ) ;
# else
if ( s ! = buf )
/* convert the last space to a newline */
* ( s - 1 ) = ' \n ' ;
# endif
2005-04-17 02:20:36 +04:00
return ( s - buf ) ;
}
2007-11-02 15:47:53 +03:00
static ssize_t state_store ( struct kobject * kobj , struct kobj_attribute * attr ,
const char * buf , size_t n )
2005-04-17 02:20:36 +04:00
{
2007-07-30 01:27:18 +04:00
# ifdef CONFIG_SUSPEND
2005-04-17 02:20:36 +04:00
suspend_state_t state = PM_SUSPEND_STANDBY ;
2006-06-25 16:47:56 +04:00
const char * const * s ;
2007-07-30 01:27:18 +04:00
# endif
2005-04-17 02:20:36 +04:00
char * p ;
int len ;
2007-07-30 01:27:18 +04:00
int error = - EINVAL ;
2005-04-17 02:20:36 +04:00
p = memchr ( buf , ' \n ' , n ) ;
len = p ? p - buf : n ;
2007-05-09 13:33:18 +04:00
/* First, check if we are requested to hibernate */
2007-05-17 09:11:19 +04:00
if ( len = = 4 & & ! strncmp ( buf , " disk " , len ) ) {
2007-05-09 13:33:18 +04:00
error = hibernate ( ) ;
2007-07-30 01:27:18 +04:00
goto Exit ;
2007-05-09 13:33:18 +04:00
}
2007-07-30 01:27:18 +04:00
# ifdef CONFIG_SUSPEND
2005-04-17 02:20:36 +04:00
for ( s = & pm_states [ state ] ; state < PM_SUSPEND_MAX ; s + + , state + + ) {
2007-05-17 09:11:19 +04:00
if ( * s & & len = = strlen ( * s ) & & ! strncmp ( buf , * s , len ) )
2005-04-17 02:20:36 +04:00
break ;
}
2006-04-28 05:39:17 +04:00
if ( state < PM_SUSPEND_MAX & & * s )
2005-04-17 02:20:36 +04:00
error = enter_state ( state ) ;
2007-07-30 01:27:18 +04:00
# endif
Exit :
2005-04-17 02:20:36 +04:00
return error ? error : n ;
}
power_attr ( state ) ;
2006-09-26 10:32:58 +04:00
# ifdef CONFIG_PM_TRACE
int pm_trace_enabled ;
2007-11-02 15:47:53 +03:00
static ssize_t pm_trace_show ( struct kobject * kobj , struct kobj_attribute * attr ,
char * buf )
2006-09-26 10:32:58 +04:00
{
return sprintf ( buf , " %d \n " , pm_trace_enabled ) ;
}
static ssize_t
2007-11-02 15:47:53 +03:00
pm_trace_store ( struct kobject * kobj , struct kobj_attribute * attr ,
const char * buf , size_t n )
2006-09-26 10:32:58 +04:00
{
int val ;
if ( sscanf ( buf , " %d " , & val ) = = 1 ) {
pm_trace_enabled = ! ! val ;
return n ;
}
return - EINVAL ;
}
power_attr ( pm_trace ) ;
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
# endif /* CONFIG_PM_TRACE */
2006-09-26 10:32:58 +04:00
static struct attribute * g [ ] = {
& state_attr . attr ,
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
# ifdef CONFIG_PM_TRACE
2006-09-26 10:32:58 +04:00
& pm_trace_attr . attr ,
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
# endif
2007-12-14 03:07:13 +03:00
# if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_DEBUG)
Suspend: Testing facility (rev. 2)
Introduce sysfs attribute /sys/power/pm_test allowing one to test the suspend
core code. Namely, writing one of the strings:
freezer
devices
platform
processors
core
to this file causes the suspend code to work in one of the test modes defined as
follows:
freezer
- test the freezing of processes
devices
- test the freezing of processes and suspending of devices
platform
- test the freezing of processes, suspending of devices and platform global
control methods(*)
processors
- test the freezing of processes, suspending of devices, platform global
control methods and the disabling of nonboot CPUs
core
- test the freezing of processes, suspending of devices, platform global
control methods, the disabling of nonboot CPUs and suspending of
platform/system devices
(*) These are ACPI global control methods on ACPI systems
Then, if a suspend is started by normal means, the suspend core will perform
its normal operations up to the point indicated by given test level. Next, it
will wait for 5 seconds and carry out the resume operations needed to transition
the system back to the fully functional state.
Writing "none" to /sys/power/pm_test turns the testing off.
When open for reading, /sys/power/pm_test contains a space-separated list of all
available tests (including "none" that represents the normal functionality) in
which the current test level is indicated by square brackets.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Len Brown <len.brown@intel.com>
2007-11-20 01:41:19 +03:00
& pm_test_attr . attr ,
# endif
2006-09-26 10:32:58 +04:00
NULL ,
} ;
2005-04-17 02:20:36 +04:00
static struct attribute_group attr_group = {
. attrs = g ,
} ;
static int __init pm_init ( void )
{
2007-11-27 22:28:26 +03:00
power_kobj = kobject_create_and_add ( " power " , NULL ) ;
if ( ! power_kobj )
2007-11-01 20:39:50 +03:00
return - ENOMEM ;
2007-11-27 22:28:26 +03:00
return sysfs_create_group ( power_kobj , & attr_group ) ;
2005-04-17 02:20:36 +04:00
}
core_initcall ( pm_init ) ;