Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
f5268fce
Commit
f5268fce
authored
Aug 20, 2003
by
Patrick Mochel
Browse files
Options
Browse Files
Download
Plain Diff
Merge osdl.org:/home/mochel/src/kernel/linux-2.5-virgin
into osdl.org:/home/mochel/src/kernel/linux-2.5-power
parents
be974925
0e59015e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
204 additions
and
20 deletions
+204
-20
drivers/base/power/main.c
drivers/base/power/main.c
+1
-0
include/linux/pm.h
include/linux/pm.h
+27
-0
kernel/power/main.c
kernel/power/main.c
+176
-20
No files found.
drivers/base/power/main.c
View file @
f5268fce
...
...
@@ -76,6 +76,7 @@ int device_pm_add(struct device * dev)
pr_debug
(
"PM: Adding info for %s:%s
\n
"
,
dev
->
bus
?
dev
->
bus
->
name
:
"No Bus"
,
dev
->
kobj
.
name
);
atomic_set
(
&
dev
->
power
.
pm_users
,
0
);
down
(
&
dpm_sem
);
list_add_tail
(
&
dev
->
power
.
entry
,
&
dpm_active
);
device_pm_set_parent
(
dev
,
dev
->
parent
);
...
...
include/linux/pm.h
View file @
f5268fce
...
...
@@ -186,9 +186,36 @@ static inline void pm_dev_idle(struct pm_dev *dev) {}
#endif
/* CONFIG_PM */
/*
* Callbacks for platform drivers to implement.
*/
extern
void
(
*
pm_idle
)(
void
);
extern
void
(
*
pm_power_off
)(
void
);
enum
{
PM_SUSPEND_ON
,
PM_SUSPEND_STANDBY
,
PM_SUSPEND_MEM
,
PM_SUSPEND_DISK
,
PM_SUSPEND_MAX
,
};
struct
pm_ops
{
int
(
*
prepare
)(
u32
state
);
int
(
*
enter
)(
u32
state
);
int
(
*
finish
)(
u32
state
);
};
extern
void
pm_set_ops
(
struct
pm_ops
*
);
extern
int
pm_suspend
(
u32
state
);
/*
* Device power management
*/
struct
device
;
struct
dev_pm_info
{
...
...
kernel/power/main.c
View file @
f5268fce
...
...
@@ -8,6 +8,7 @@
*
*/
#include <linux/suspend.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/errno.h>
...
...
@@ -15,42 +16,194 @@
#include <linux/pm.h>
static
DECLARE_MUTEX
(
pm_sem
);
static
int
standby
(
void
)
static
struct
pm_ops
*
pm_ops
=
NULL
;
/**
* pm_set_ops - Set the global power method table.
* @ops: Pointer to ops structure.
*/
void
pm_set_ops
(
struct
pm_ops
*
ops
)
{
return
0
;
down
(
&
pm_sem
);
pm_ops
=
ops
;
up
(
&
pm_sem
);
}
static
int
suspend
(
void
)
/**
* pm_suspend_standby - Enter 'standby' state.
*
* 'standby' is also known as 'Power-On Suspend'. Here, we power down
* devices, disable interrupts, and enter the state.
*/
static
int
pm_suspend_standby
(
void
)
{
return
0
;
int
error
=
0
;
unsigned
long
flags
;
if
(
!
pm_ops
||
!
pm_ops
->
enter
)
return
-
EPERM
;
if
((
error
=
device_pm_power_down
(
PM_SUSPEND_STANDBY
)))
goto
Done
;
local_irq_save
(
flags
);
error
=
pm_ops
->
enter
(
PM_SUSPEND_STANDBY
);
local_irq_restore
(
flags
);
device_pm_power_up
();
Done:
return
error
;
}
static
int
hibernate
(
void
)
/**
* pm_suspend_mem - Enter suspend-to-RAM state.
*
* Identical to pm_suspend_standby() - we power down devices, disable
* interrupts, and enter the low-power state.
*/
static
int
pm_suspend_mem
(
void
)
{
int
error
=
0
;
unsigned
long
flags
;
if
(
!
pm_ops
||
!
pm_ops
->
enter
)
return
-
EPERM
;
if
((
error
=
device_pm_power_down
(
PM_SUSPEND_STANDBY
)))
goto
Done
;
local_irq_save
(
flags
);
error
=
pm_ops
->
enter
(
PM_SUSPEND_STANDBY
);
local_irq_restore
(
flags
);
device_pm_power_up
();
Done:
return
error
;
}
static
int
pm_suspend_disk
(
void
)
{
return
0
;
}
#define decl_state(_name) \
{ .name = __stringify(_name), .fn = _name }
{ .name = __stringify(_name), .fn =
pm_suspend_##
_name }
struct
pm_state
{
char
*
name
;
int
(
*
fn
)(
void
);
}
pm_states
[]
=
{
decl_state
(
standby
),
decl_state
(
suspend
),
decl_state
(
hibernate
),
[
PM_SUSPEND_STANDBY
]
=
decl_state
(
standby
),
[
PM_SUSPEND_MEM
]
=
decl_state
(
mem
),
[
PM_SUSPEND_DISK
]
=
decl_state
(
disk
),
{
NULL
},
};
static
int
enter_state
(
struct
pm_state
*
state
)
/**
* suspend_prepare - Do prep work before entering low-power state.
* @state: State we're entering.
*
* This is common code that is called for each state that we're
* entering. Allocate a console, stop all processes, then make sure
* the platform can enter the requested state.
*/
static
int
suspend_prepare
(
u32
state
)
{
return
state
->
fn
();
int
error
=
0
;
pm_prepare_console
();
if
(
freeze_processes
())
{
error
=
-
EAGAIN
;
goto
Thaw
;
}
if
(
pm_ops
&&
pm_ops
->
prepare
)
{
if
((
error
=
pm_ops
->
prepare
(
state
)))
goto
Thaw
;
}
Done:
pm_restore_console
();
return
error
;
Thaw:
thaw_processes
();
goto
Done
;
}
/**
* suspend_finish - Do final work before exiting suspend sequence.
* @state: State we're coming out of.
*
* Call platform code to clean up, restart processes, and free the
* console that we've allocated.
*/
static
void
suspend_finish
(
u32
state
)
{
if
(
pm_ops
&&
pm_ops
->
finish
)
pm_ops
->
finish
(
state
);
thaw_processes
();
pm_restore_console
();
}
/**
* 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
(
u32
state
)
{
int
error
;
struct
pm_state
*
s
=
&
pm_states
[
state
];
if
(
down_trylock
(
&
pm_sem
))
return
-
EBUSY
;
if
((
error
=
suspend_prepare
(
state
)))
goto
Unlock
;
if
((
error
=
device_pm_suspend
(
state
)))
goto
Finish
;
error
=
s
->
fn
();
device_pm_resume
();
Finish:
suspend_finish
(
state
);
Unlock:
up
(
&
pm_sem
);
return
error
;
}
/**
* pm_suspend - Externally visible function for suspending system.
* @state: Enumarted value of state to enter.
*
* Determine whether or not value is within range, get state
* structure, and enter (above).
*/
int
pm_suspend
(
u32
state
)
{
if
(
state
>
PM_SUSPEND_ON
&&
state
<
PM_SUSPEND_MAX
)
return
enter_state
(
state
);
return
-
EINVAL
;
}
decl_subsys
(
power
,
NULL
,
NULL
);
...
...
@@ -69,8 +222,8 @@ static struct subsys_attribute _name##_attr = { \
* state - control system power state.
*
* show() returns what states are supported, which is hard-coded to
* 'standby' (Power-On Suspend), '
suspend
' (Suspend-to-RAM), and
* '
hibernate
' (Suspend-to-Disk).
* '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.
...
...
@@ -87,22 +240,25 @@ static ssize_t state_show(struct subsystem * subsys, char * buf)
return
(
s
-
buf
);
}
static
ssize_t
state_store
(
struct
subsystem
*
s
,
const
char
*
buf
,
size_t
n
)
static
ssize_t
state_store
(
struct
subsystem
*
s
ubsys
,
const
char
*
buf
,
size_t
n
)
{
struct
pm_state
*
state
;
u32
state
;
struct
pm_state
*
s
;
int
error
;
char
*
end
=
strchr
(
buf
,
'\n'
);
if
(
end
)
*
end
=
'\0'
;
for
(
state
=
&
pm_states
[
0
];
state
;
state
++
)
{
if
(
!
strcmp
(
buf
,
state
->
name
))
for
(
state
=
0
;
state
<
PM_SUSPEND_MAX
;
state
++
)
{
s
=
&
pm_states
[
state
];
if
(
s
->
name
&&
!
strcmp
(
buf
,
s
->
name
))
break
;
}
if
(
!
state
)
return
-
EINVAL
;
error
=
enter_state
(
state
);
if
(
s
)
error
=
enter_state
(
state
);
else
error
=
-
EINVAL
;
return
error
?
error
:
n
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment