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
Kirill Smelkov
linux
Commits
a841bc4c
Commit
a841bc4c
authored
Aug 18, 2003
by
Patrick Mochel
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net//home/mochel/linux-2.5-power
into osdl.org:/home/mochel/src/kernel/linux-2.5-power
parents
de9974b1
0a7bf909
Changes
3
Show 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 @
a841bc4c
...
...
@@ -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 @
a841bc4c
...
...
@@ -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 @
a841bc4c
...
...
@@ -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
;
}
/**
* 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
hibernate
(
void
)
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
)
{
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
)
{
return
state
->
fn
();
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
;
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