2005-04-16 15:20:36 -07: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
*
*/
# include <linux/kobject.h>
# include <linux/string.h>
2006-09-25 23:32:58 -07:00
# include <linux/resume-trace.h>
2009-08-18 23:38:32 +02:00
# include <linux/workqueue.h>
2005-04-16 15:20:36 -07:00
# include "power.h"
2006-12-06 20:34:35 -08:00
DEFINE_MUTEX ( pm_mutex ) ;
2005-04-16 15:20:36 -07:00
2007-12-13 17:38:03 -05:00
unsigned int pm_flags ;
EXPORT_SYMBOL ( pm_flags ) ;
2007-11-19 23:49:18 +01: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-19 23:41:19 +01:00
# ifdef CONFIG_PM_DEBUG
int pm_test_level = TEST_NONE ;
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 00:29:06 +01: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-19 23:41:19 +01: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 00:29:06 +01: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-19 23:41:19 +01: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 ) ;
2009-01-17 00:10:45 +01:00
# endif /* 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-19 23:41:19 +01:00
2007-12-14 01:07:13 +01:00
# endif /* CONFIG_PM_SLEEP */
2008-01-29 00:29:06 +01:00
2007-11-27 11:28:26 -08:00
struct kobject * power_kobj ;
2005-04-16 15:20:36 -07: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 13:47:53 +01:00
static ssize_t state_show ( struct kobject * kobj , struct kobj_attribute * attr ,
char * buf )
2005-04-16 15:20:36 -07:00
{
2007-07-29 23:27:18 +02:00
char * s = buf ;
# ifdef CONFIG_SUSPEND
2005-04-16 15:20:36 -07:00
int i ;
for ( i = 0 ; i < PM_SUSPEND_MAX ; i + + ) {
2005-11-29 19:34:37 -08:00
if ( pm_states [ i ] & & valid_state ( i ) )
s + = sprintf ( s , " %s " , pm_states [ i ] ) ;
2005-04-16 15:20:36 -07:00
}
2007-07-29 23:27:18 +02:00
# endif
2007-07-29 23:24:36 +02:00
# ifdef CONFIG_HIBERNATION
2007-05-09 02:33:18 -07:00
s + = sprintf ( s , " %s \n " , " disk " ) ;
# else
if ( s ! = buf )
/* convert the last space to a newline */
* ( s - 1 ) = ' \n ' ;
# endif
2005-04-16 15:20:36 -07:00
return ( s - buf ) ;
}
2007-11-02 13:47:53 +01:00
static ssize_t state_store ( struct kobject * kobj , struct kobj_attribute * attr ,
const char * buf , size_t n )
2005-04-16 15:20:36 -07:00
{
2007-07-29 23:27:18 +02:00
# ifdef CONFIG_SUSPEND
2005-04-16 15:20:36 -07:00
suspend_state_t state = PM_SUSPEND_STANDBY ;
2006-06-25 05:47:56 -07:00
const char * const * s ;
2007-07-29 23:27:18 +02:00
# endif
2005-04-16 15:20:36 -07:00
char * p ;
int len ;
2007-07-29 23:27:18 +02:00
int error = - EINVAL ;
2005-04-16 15:20:36 -07:00
p = memchr ( buf , ' \n ' , n ) ;
len = p ? p - buf : n ;
2007-05-09 02:33:18 -07:00
/* First, check if we are requested to hibernate */
2007-05-16 22:11:19 -07:00
if ( len = = 4 & & ! strncmp ( buf , " disk " , len ) ) {
2007-05-09 02:33:18 -07:00
error = hibernate ( ) ;
2007-07-29 23:27:18 +02:00
goto Exit ;
2007-05-09 02:33:18 -07:00
}
2007-07-29 23:27:18 +02:00
# ifdef CONFIG_SUSPEND
2005-04-16 15:20:36 -07:00
for ( s = & pm_states [ state ] ; state < PM_SUSPEND_MAX ; s + + , state + + ) {
2007-05-16 22:11:19 -07:00
if ( * s & & len = = strlen ( * s ) & & ! strncmp ( buf , * s , len ) )
2005-04-16 15:20:36 -07:00
break ;
}
2006-04-27 18:39:17 -07:00
if ( state < PM_SUSPEND_MAX & & * s )
2005-04-16 15:20:36 -07:00
error = enter_state ( state ) ;
2007-07-29 23:27:18 +02:00
# endif
Exit :
2005-04-16 15:20:36 -07:00
return error ? error : n ;
}
power_attr ( state ) ;
2006-09-25 23:32:58 -07:00
# ifdef CONFIG_PM_TRACE
int pm_trace_enabled ;
2007-11-02 13:47:53 +01:00
static ssize_t pm_trace_show ( struct kobject * kobj , struct kobj_attribute * attr ,
char * buf )
2006-09-25 23:32:58 -07:00
{
return sprintf ( buf , " %d \n " , pm_trace_enabled ) ;
}
static ssize_t
2007-11-02 13:47:53 +01:00
pm_trace_store ( struct kobject * kobj , struct kobj_attribute * attr ,
const char * buf , size_t n )
2006-09-25 23:32:58 -07: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-19 23:41:19 +01:00
# endif /* CONFIG_PM_TRACE */
2006-09-25 23:32:58 -07: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-19 23:41:19 +01:00
# ifdef CONFIG_PM_TRACE
2006-09-25 23:32:58 -07: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-19 23:41:19 +01:00
# endif
2007-12-14 01:07:13 +01: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-19 23:41:19 +01:00
& pm_test_attr . attr ,
# endif
2006-09-25 23:32:58 -07:00
NULL ,
} ;
2005-04-16 15:20:36 -07:00
static struct attribute_group attr_group = {
. attrs = g ,
} ;
2009-08-18 23:38:32 +02:00
# ifdef CONFIG_PM_RUNTIME
struct workqueue_struct * pm_wq ;
static int __init pm_start_workqueue ( void )
{
pm_wq = create_freezeable_workqueue ( " pm " ) ;
return pm_wq ? 0 : - ENOMEM ;
}
# else
static inline int pm_start_workqueue ( void ) { return 0 ; }
# endif
2005-04-16 15:20:36 -07:00
static int __init pm_init ( void )
{
2009-08-18 23:38:32 +02:00
int error = pm_start_workqueue ( ) ;
if ( error )
return error ;
2007-11-27 11:28:26 -08:00
power_kobj = kobject_create_and_add ( " power " , NULL ) ;
if ( ! power_kobj )
2007-11-01 10:39:50 -07:00
return - ENOMEM ;
2007-11-27 11:28:26 -08:00
return sysfs_create_group ( power_kobj , & attr_group ) ;
2005-04-16 15:20:36 -07:00
}
core_initcall ( pm_init ) ;