Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
3cc8a5f4
Commit
3cc8a5f4
authored
Jan 09, 2009
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'suspend' into release
parents
d0302bc6
ada9cfdd
Changes
9
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
446 additions
and
201 deletions
+446
-201
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+26
-19
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/acpi/sleep.c
+2
-0
arch/x86/kernel/e820.c
arch/x86/kernel/e820.c
+21
-0
drivers/acpi/main.c
drivers/acpi/main.c
+59
-8
include/linux/acpi.h
include/linux/acpi.h
+1
-0
include/linux/suspend.h
include/linux/suspend.h
+13
-0
kernel/power/disk.c
kernel/power/disk.c
+3
-3
kernel/power/snapshot.c
kernel/power/snapshot.c
+199
-171
kernel/power/swsusp.c
kernel/power/swsusp.c
+122
-0
No files found.
Documentation/kernel-parameters.txt
View file @
3cc8a5f4
...
@@ -150,16 +150,20 @@ and is between 256 and 4096 characters. It is defined in the file
...
@@ -150,16 +150,20 @@ and is between 256 and 4096 characters. It is defined in the file
default: 0
default: 0
acpi_sleep= [HW,ACPI] Sleep options
acpi_sleep= [HW,ACPI] Sleep options
Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, old_ordering }
Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
See Documentation/power/video.txt for s3_bios and s3_mode.
old_ordering, s4_nonvs }
See Documentation/power/video.txt for information on
s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep
s3_beep is for debugging; it makes the PC's speaker beep
as soon as the kernel's real-mode entry point is called.
as soon as the kernel's real-mode entry point is called.
s4_nohwsig prevents ACPI hardware signature from being
s4_nohwsig prevents ACPI hardware signature from being
used during resume from hibernation.
used during resume from hibernation.
old_ordering causes the ACPI 1.0 ordering of the _PTS
old_ordering causes the ACPI 1.0 ordering of the _PTS
control method, wrt putting devices into low power
control method, with respect to putting devices into
states, to be enforced (the ACPI 2.0 ordering of _PTS is
low power states, to be enforced (the ACPI 2.0 ordering
used by default).
of _PTS is used by default).
s4_nonvs prevents the kernel from saving/restoring the
ACPI NVS memory during hibernation.
acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
Format: { level | edge | high | low }
Format: { level | edge | high | low }
...
@@ -194,7 +198,7 @@ and is between 256 and 4096 characters. It is defined in the file
...
@@ -194,7 +198,7 @@ and is between 256 and 4096 characters. It is defined in the file
acpi_skip_timer_override [HW,ACPI]
acpi_skip_timer_override [HW,ACPI]
Recognize and ignore IRQ0/pin2 Interrupt Override.
Recognize and ignore IRQ0/pin2 Interrupt Override.
For broken nForce2 BIOS resulting in XT-PIC timer.
For broken nForce2 BIOS resulting in XT-PIC timer.
acpi_use_timer_override [HW,ACPI
}
acpi_use_timer_override [HW,ACPI
]
Use timer override. For some broken Nvidia NF5 boards
Use timer override. For some broken Nvidia NF5 boards
that require a timer override, but don't have
that require a timer override, but don't have
HPET
HPET
...
@@ -861,17 +865,19 @@ and is between 256 and 4096 characters. It is defined in the file
...
@@ -861,17 +865,19 @@ and is between 256 and 4096 characters. It is defined in the file
See Documentation/ide/ide.txt.
See Documentation/ide/ide.txt.
idle= [X86]
idle= [X86]
Format: idle=poll or idle=mwait, idle=halt, idle=nomwait
Format: idle=poll, idle=mwait, idle=halt, idle=nomwait
Poll forces a polling idle loop that can slightly improves the performance
Poll forces a polling idle loop that can slightly
of waking up a idle CPU, but will use a lot of power and make the system
improve the performance of waking up a idle CPU, but
run hot. Not recommended.
will use a lot of power and make the system run hot.
idle=mwait. On systems which support MONITOR/MWAIT but the kernel chose
Not recommended.
to not use it because it doesn't save as much power as a normal idle
idle=mwait: On systems which support MONITOR/MWAIT but
loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
the kernel chose to not use it because it doesn't save
as idle=poll.
as much power as a normal idle loop, use the
idle=halt. Halt is forced to be used for CPU idle.
MONITOR/MWAIT idle loop anyways. Performance should be
the same as idle=poll.
idle=halt: Halt is forced to be used for CPU idle.
In such case C2/C3 won't be used again.
In such case C2/C3 won't be used again.
idle=nomwait
.
Disable mwait for CPU C-states
idle=nomwait
:
Disable mwait for CPU C-states
ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
Claim all unknown PCI IDE storage controllers.
Claim all unknown PCI IDE storage controllers.
...
@@ -1053,8 +1059,8 @@ and is between 256 and 4096 characters. It is defined in the file
...
@@ -1053,8 +1059,8 @@ and is between 256 and 4096 characters. It is defined in the file
lapic [X86-32,APIC] Enable the local APIC even if BIOS
lapic [X86-32,APIC] Enable the local APIC even if BIOS
disabled it.
disabled it.
lapic_timer_c2_ok [X86-32,x86-64,APIC] trust the local apic timer
in
lapic_timer_c2_ok [X86-32,x86-64,APIC] trust the local apic timer
C2 power state.
in
C2 power state.
libata.dma= [LIBATA] DMA control
libata.dma= [LIBATA] DMA control
libata.dma=0 Disable all PATA and SATA DMA
libata.dma=0 Disable all PATA and SATA DMA
...
@@ -2242,7 +2248,8 @@ and is between 256 and 4096 characters. It is defined in the file
...
@@ -2242,7 +2248,8 @@ and is between 256 and 4096 characters. It is defined in the file
thermal.psv= [HW,ACPI]
thermal.psv= [HW,ACPI]
-1: disable all passive trip points
-1: disable all passive trip points
<degrees C>: override all passive trip points to this value
<degrees C>: override all passive trip points to this
value
thermal.tzp= [HW,ACPI]
thermal.tzp= [HW,ACPI]
Specify global default ACPI thermal zone polling rate
Specify global default ACPI thermal zone polling rate
...
...
arch/x86/kernel/acpi/sleep.c
View file @
3cc8a5f4
...
@@ -159,6 +159,8 @@ static int __init acpi_sleep_setup(char *str)
...
@@ -159,6 +159,8 @@ static int __init acpi_sleep_setup(char *str)
#endif
#endif
if
(
strncmp
(
str
,
"old_ordering"
,
12
)
==
0
)
if
(
strncmp
(
str
,
"old_ordering"
,
12
)
==
0
)
acpi_old_suspend_ordering
();
acpi_old_suspend_ordering
();
if
(
strncmp
(
str
,
"s4_nonvs"
,
8
)
==
0
)
acpi_s4_no_nvs
();
str
=
strchr
(
str
,
','
);
str
=
strchr
(
str
,
','
);
if
(
str
!=
NULL
)
if
(
str
!=
NULL
)
str
+=
strspn
(
str
,
",
\t
"
);
str
+=
strspn
(
str
,
",
\t
"
);
...
...
arch/x86/kernel/e820.c
View file @
3cc8a5f4
...
@@ -665,6 +665,27 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)
...
@@ -665,6 +665,27 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)
}
}
#endif
#endif
#ifdef CONFIG_HIBERNATION
/**
* Mark ACPI NVS memory region, so that we can save/restore it during
* hibernation and the subsequent resume.
*/
static
int
__init
e820_mark_nvs_memory
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
e820
.
nr_map
;
i
++
)
{
struct
e820entry
*
ei
=
&
e820
.
map
[
i
];
if
(
ei
->
type
==
E820_NVS
)
hibernate_nvs_register
(
ei
->
addr
,
ei
->
size
);
}
return
0
;
}
core_initcall
(
e820_mark_nvs_memory
);
#endif
/*
/*
* Early reserved memory areas.
* Early reserved memory areas.
*/
*/
...
...
drivers/acpi/main.c
View file @
3cc8a5f4
...
@@ -101,6 +101,19 @@ void __init acpi_old_suspend_ordering(void)
...
@@ -101,6 +101,19 @@ void __init acpi_old_suspend_ordering(void)
* cases.
* cases.
*/
*/
static
bool
set_sci_en_on_resume
;
static
bool
set_sci_en_on_resume
;
/*
* The ACPI specification wants us to save NVS memory regions during hibernation
* and to restore them during the subsequent resume. However, it is not certain
* if this mechanism is going to work on all machines, so we allow the user to
* disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
* option.
*/
static
bool
s4_no_nvs
;
void
__init
acpi_s4_no_nvs
(
void
)
{
s4_no_nvs
=
true
;
}
/**
/**
* acpi_pm_disable_gpes - Disable the GPEs.
* acpi_pm_disable_gpes - Disable the GPEs.
...
@@ -394,9 +407,25 @@ void __init acpi_no_s4_hw_signature(void)
...
@@ -394,9 +407,25 @@ void __init acpi_no_s4_hw_signature(void)
static
int
acpi_hibernation_begin
(
void
)
static
int
acpi_hibernation_begin
(
void
)
{
{
int
error
;
error
=
s4_no_nvs
?
0
:
hibernate_nvs_alloc
();
if
(
!
error
)
{
acpi_target_sleep_state
=
ACPI_STATE_S4
;
acpi_target_sleep_state
=
ACPI_STATE_S4
;
acpi_sleep_tts_switch
(
acpi_target_sleep_state
);
acpi_sleep_tts_switch
(
acpi_target_sleep_state
);
return
0
;
}
return
error
;
}
static
int
acpi_hibernation_pre_snapshot
(
void
)
{
int
error
=
acpi_pm_prepare
();
if
(
!
error
)
hibernate_nvs_save
();
return
error
;
}
}
static
int
acpi_hibernation_enter
(
void
)
static
int
acpi_hibernation_enter
(
void
)
...
@@ -417,6 +446,12 @@ static int acpi_hibernation_enter(void)
...
@@ -417,6 +446,12 @@ static int acpi_hibernation_enter(void)
return
ACPI_SUCCESS
(
status
)
?
0
:
-
EFAULT
;
return
ACPI_SUCCESS
(
status
)
?
0
:
-
EFAULT
;
}
}
static
void
acpi_hibernation_finish
(
void
)
{
hibernate_nvs_free
();
acpi_pm_finish
();
}
static
void
acpi_hibernation_leave
(
void
)
static
void
acpi_hibernation_leave
(
void
)
{
{
/*
/*
...
@@ -432,6 +467,8 @@ static void acpi_hibernation_leave(void)
...
@@ -432,6 +467,8 @@ static void acpi_hibernation_leave(void)
"cannot resume!
\n
"
);
"cannot resume!
\n
"
);
panic
(
"ACPI S4 hardware signature mismatch"
);
panic
(
"ACPI S4 hardware signature mismatch"
);
}
}
/* Restore the NVS memory area */
hibernate_nvs_restore
();
}
}
static
void
acpi_pm_enable_gpes
(
void
)
static
void
acpi_pm_enable_gpes
(
void
)
...
@@ -442,8 +479,8 @@ static void acpi_pm_enable_gpes(void)
...
@@ -442,8 +479,8 @@ static void acpi_pm_enable_gpes(void)
static
struct
platform_hibernation_ops
acpi_hibernation_ops
=
{
static
struct
platform_hibernation_ops
acpi_hibernation_ops
=
{
.
begin
=
acpi_hibernation_begin
,
.
begin
=
acpi_hibernation_begin
,
.
end
=
acpi_pm_end
,
.
end
=
acpi_pm_end
,
.
pre_snapshot
=
acpi_
pm_prepare
,
.
pre_snapshot
=
acpi_
hibernation_pre_snapshot
,
.
finish
=
acpi_
pm
_finish
,
.
finish
=
acpi_
hibernation
_finish
,
.
prepare
=
acpi_pm_prepare
,
.
prepare
=
acpi_pm_prepare
,
.
enter
=
acpi_hibernation_enter
,
.
enter
=
acpi_hibernation_enter
,
.
leave
=
acpi_hibernation_leave
,
.
leave
=
acpi_hibernation_leave
,
...
@@ -469,8 +506,22 @@ static int acpi_hibernation_begin_old(void)
...
@@ -469,8 +506,22 @@ static int acpi_hibernation_begin_old(void)
error
=
acpi_sleep_prepare
(
ACPI_STATE_S4
);
error
=
acpi_sleep_prepare
(
ACPI_STATE_S4
);
if
(
!
error
)
{
if
(
!
s4_no_nvs
)
error
=
hibernate_nvs_alloc
();
if
(
!
error
)
if
(
!
error
)
acpi_target_sleep_state
=
ACPI_STATE_S4
;
acpi_target_sleep_state
=
ACPI_STATE_S4
;
}
return
error
;
}
static
int
acpi_hibernation_pre_snapshot_old
(
void
)
{
int
error
=
acpi_pm_disable_gpes
();
if
(
!
error
)
hibernate_nvs_save
();
return
error
;
return
error
;
}
}
...
@@ -481,8 +532,8 @@ static int acpi_hibernation_begin_old(void)
...
@@ -481,8 +532,8 @@ static int acpi_hibernation_begin_old(void)
static
struct
platform_hibernation_ops
acpi_hibernation_ops_old
=
{
static
struct
platform_hibernation_ops
acpi_hibernation_ops_old
=
{
.
begin
=
acpi_hibernation_begin_old
,
.
begin
=
acpi_hibernation_begin_old
,
.
end
=
acpi_pm_end
,
.
end
=
acpi_pm_end
,
.
pre_snapshot
=
acpi_
pm_disable_gpes
,
.
pre_snapshot
=
acpi_
hibernation_pre_snapshot_old
,
.
finish
=
acpi_
pm
_finish
,
.
finish
=
acpi_
hibernation
_finish
,
.
prepare
=
acpi_pm_disable_gpes
,
.
prepare
=
acpi_pm_disable_gpes
,
.
enter
=
acpi_hibernation_enter
,
.
enter
=
acpi_hibernation_enter
,
.
leave
=
acpi_hibernation_leave
,
.
leave
=
acpi_hibernation_leave
,
...
...
include/linux/acpi.h
View file @
3cc8a5f4
...
@@ -270,6 +270,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
...
@@ -270,6 +270,7 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM_SLEEP
void
__init
acpi_no_s4_hw_signature
(
void
);
void
__init
acpi_no_s4_hw_signature
(
void
);
void
__init
acpi_old_suspend_ordering
(
void
);
void
__init
acpi_old_suspend_ordering
(
void
);
void
__init
acpi_s4_no_nvs
(
void
);
#endif
/* CONFIG_PM_SLEEP */
#endif
/* CONFIG_PM_SLEEP */
#else
/* CONFIG_ACPI */
#else
/* CONFIG_ACPI */
...
...
include/linux/suspend.h
View file @
3cc8a5f4
...
@@ -232,6 +232,11 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
...
@@ -232,6 +232,11 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
extern
void
hibernation_set_ops
(
struct
platform_hibernation_ops
*
ops
);
extern
void
hibernation_set_ops
(
struct
platform_hibernation_ops
*
ops
);
extern
int
hibernate
(
void
);
extern
int
hibernate
(
void
);
extern
int
hibernate_nvs_register
(
unsigned
long
start
,
unsigned
long
size
);
extern
int
hibernate_nvs_alloc
(
void
);
extern
void
hibernate_nvs_free
(
void
);
extern
void
hibernate_nvs_save
(
void
);
extern
void
hibernate_nvs_restore
(
void
);
#else
/* CONFIG_HIBERNATION */
#else
/* CONFIG_HIBERNATION */
static
inline
int
swsusp_page_is_forbidden
(
struct
page
*
p
)
{
return
0
;
}
static
inline
int
swsusp_page_is_forbidden
(
struct
page
*
p
)
{
return
0
;
}
static
inline
void
swsusp_set_page_free
(
struct
page
*
p
)
{}
static
inline
void
swsusp_set_page_free
(
struct
page
*
p
)
{}
...
@@ -239,6 +244,14 @@ static inline void swsusp_unset_page_free(struct page *p) {}
...
@@ -239,6 +244,14 @@ static inline void swsusp_unset_page_free(struct page *p) {}
static
inline
void
hibernation_set_ops
(
struct
platform_hibernation_ops
*
ops
)
{}
static
inline
void
hibernation_set_ops
(
struct
platform_hibernation_ops
*
ops
)
{}
static
inline
int
hibernate
(
void
)
{
return
-
ENOSYS
;
}
static
inline
int
hibernate
(
void
)
{
return
-
ENOSYS
;
}
static
inline
int
hibernate_nvs_register
(
unsigned
long
a
,
unsigned
long
b
)
{
return
0
;
}
static
inline
int
hibernate_nvs_alloc
(
void
)
{
return
0
;
}
static
inline
void
hibernate_nvs_free
(
void
)
{}
static
inline
void
hibernate_nvs_save
(
void
)
{}
static
inline
void
hibernate_nvs_restore
(
void
)
{}
#endif
/* CONFIG_HIBERNATION */
#endif
/* CONFIG_HIBERNATION */
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM_SLEEP
...
...
kernel/power/disk.c
View file @
3cc8a5f4
...
@@ -259,12 +259,12 @@ int hibernation_snapshot(int platform_mode)
...
@@ -259,12 +259,12 @@ int hibernation_snapshot(int platform_mode)
{
{
int
error
,
ftrace_save
;
int
error
,
ftrace_save
;
/* Free memory before shutting down devices. */
error
=
platform_begin
(
platform_mode
);
error
=
swsusp_shrink_memory
();
if
(
error
)
if
(
error
)
return
error
;
return
error
;
error
=
platform_begin
(
platform_mode
);
/* Free memory before shutting down devices. */
error
=
swsusp_shrink_memory
();
if
(
error
)
if
(
error
)
goto
Close
;
goto
Close
;
...
...
kernel/power/snapshot.c
View file @
3cc8a5f4
This diff is collapsed.
Click to expand it.
kernel/power/swsusp.c
View file @
3cc8a5f4
...
@@ -262,3 +262,125 @@ int swsusp_shrink_memory(void)
...
@@ -262,3 +262,125 @@ int swsusp_shrink_memory(void)
return
0
;
return
0
;
}
}
/*
* Platforms, like ACPI, may want us to save some memory used by them during
* hibernation and to restore the contents of this memory during the subsequent
* resume. The code below implements a mechanism allowing us to do that.
*/
struct
nvs_page
{
unsigned
long
phys_start
;
unsigned
int
size
;
void
*
kaddr
;
void
*
data
;
struct
list_head
node
;
};
static
LIST_HEAD
(
nvs_list
);
/**
* hibernate_nvs_register - register platform NVS memory region to save
* @start - physical address of the region
* @size - size of the region
*
* The NVS region need not be page-aligned (both ends) and we arrange
* things so that the data from page-aligned addresses in this region will
* be copied into separate RAM pages.
*/
int
hibernate_nvs_register
(
unsigned
long
start
,
unsigned
long
size
)
{
struct
nvs_page
*
entry
,
*
next
;
while
(
size
>
0
)
{
unsigned
int
nr_bytes
;
entry
=
kzalloc
(
sizeof
(
struct
nvs_page
),
GFP_KERNEL
);
if
(
!
entry
)
goto
Error
;
list_add_tail
(
&
entry
->
node
,
&
nvs_list
);
entry
->
phys_start
=
start
;
nr_bytes
=
PAGE_SIZE
-
(
start
&
~
PAGE_MASK
);
entry
->
size
=
(
size
<
nr_bytes
)
?
size
:
nr_bytes
;
start
+=
entry
->
size
;
size
-=
entry
->
size
;
}
return
0
;
Error:
list_for_each_entry_safe
(
entry
,
next
,
&
nvs_list
,
node
)
{
list_del
(
&
entry
->
node
);
kfree
(
entry
);
}
return
-
ENOMEM
;
}
/**
* hibernate_nvs_free - free data pages allocated for saving NVS regions
*/
void
hibernate_nvs_free
(
void
)
{
struct
nvs_page
*
entry
;
list_for_each_entry
(
entry
,
&
nvs_list
,
node
)
if
(
entry
->
data
)
{
free_page
((
unsigned
long
)
entry
->
data
);
entry
->
data
=
NULL
;
if
(
entry
->
kaddr
)
{
iounmap
(
entry
->
kaddr
);
entry
->
kaddr
=
NULL
;
}
}
}
/**
* hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
*/
int
hibernate_nvs_alloc
(
void
)
{
struct
nvs_page
*
entry
;
list_for_each_entry
(
entry
,
&
nvs_list
,
node
)
{
entry
->
data
=
(
void
*
)
__get_free_page
(
GFP_KERNEL
);
if
(
!
entry
->
data
)
{
hibernate_nvs_free
();
return
-
ENOMEM
;
}
}
return
0
;
}
/**
* hibernate_nvs_save - save NVS memory regions
*/
void
hibernate_nvs_save
(
void
)
{
struct
nvs_page
*
entry
;
printk
(
KERN_INFO
"PM: Saving platform NVS memory
\n
"
);
list_for_each_entry
(
entry
,
&
nvs_list
,
node
)
if
(
entry
->
data
)
{
entry
->
kaddr
=
ioremap
(
entry
->
phys_start
,
entry
->
size
);
memcpy
(
entry
->
data
,
entry
->
kaddr
,
entry
->
size
);
}
}
/**
* hibernate_nvs_restore - restore NVS memory regions
*
* This function is going to be called with interrupts disabled, so it
* cannot iounmap the virtual addresses used to access the NVS region.
*/
void
hibernate_nvs_restore
(
void
)
{
struct
nvs_page
*
entry
;
printk
(
KERN_INFO
"PM: Restoring platform NVS memory
\n
"
);
list_for_each_entry
(
entry
,
&
nvs_list
,
node
)
if
(
entry
->
data
)
memcpy
(
entry
->
kaddr
,
entry
->
data
,
entry
->
size
);
}
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