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
a5950f26
Commit
a5950f26
authored
Oct 09, 2017
by
Rafael J. Wysocki
Browse files
Options
Browse Files
Download
Plain Diff
Merge back suspend/resume/hibernate material for v4.15.
parents
87cbde8d
eb672c02
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
101 additions
and
117 deletions
+101
-117
Documentation/driver-api/pm/devices.rst
Documentation/driver-api/pm/devices.rst
+24
-1
arch/arm/common/locomo.c
arch/arm/common/locomo.c
+0
-24
arch/arm/include/asm/hardware/locomo.h
arch/arm/include/asm/hardware/locomo.h
+0
-2
kernel/power/qos.c
kernel/power/qos.c
+2
-2
kernel/power/snapshot.c
kernel/power/snapshot.c
+18
-17
kernel/power/swap.c
kernel/power/swap.c
+57
-71
No files found.
Documentation/driver-api/pm/devices.rst
View file @
a5950f26
...
...
@@ -328,7 +328,10 @@ the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``.
After the ``->prepare`` callback method returns, no new children may be
registered below the device. The method may also prepare the device or
driver in some way for the upcoming system power transition, but it
should not put the device into a low-power state.
should not put the device into a low-power state. Moreover, if the
device supports runtime power management, the ``->prepare`` callback
method must not update its state in case it is necessary to resume it
from runtime suspend later on.
For devices supporting runtime power management, the return value of the
prepare callback can be used to indicate to the PM core that it may
...
...
@@ -356,6 +359,16 @@ the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``.
the appropriate low-power state, depending on the bus type the device is
on, and they may enable wakeup events.
However, for devices supporting runtime power management, the
``->suspend`` methods provided by subsystems (bus types and PM domains
in particular) must follow an additional rule regarding what can be done
to the devices before their drivers' ``->suspend`` methods are called.
Namely, they can only resume the devices from runtime suspend by
calling :c:func:`pm_runtime_resume` for them, if that is necessary, and
they must not update the state of the devices in any other way at that
time (in case the drivers need to resume the devices from runtime
suspend in their ``->suspend`` methods).
3. For a number of devices it is convenient to split suspend into the
"quiesce device" and "save device state" phases, in which cases
``suspend_late`` is meant to do the latter. It is always executed after
...
...
@@ -729,6 +742,16 @@ state temporarily, for example so that its system wakeup capability can be
disabled. This all depends on the hardware and the design of the subsystem and
device driver in question.
If it is necessary to resume a device from runtime suspend during a system-wide
transition into a sleep state, that can be done by calling
:c:func:`pm_runtime_resume` for it from the ``->suspend`` callback (or its
couterpart for transitions related to hibernation) of either the device's driver
or a subsystem responsible for it (for example, a bus type or a PM domain).
That is guaranteed to work by the requirement that subsystems must not change
the state of devices (possibly except for resuming them from runtime suspend)
from their ``->prepare`` and ``->suspend`` callbacks (or equivalent) *before*
invoking device drivers' ``->suspend`` callbacks (or equivalent).
During system-wide resume from a sleep state it's easiest to put devices into
the full-power state, as explained in :file:`Documentation/power/runtime_pm.txt`.
Refer to that document for more information regarding this particular issue as
...
...
arch/arm/common/locomo.c
View file @
a5950f26
...
...
@@ -826,28 +826,6 @@ static int locomo_match(struct device *_dev, struct device_driver *_drv)
return
dev
->
devid
==
drv
->
devid
;
}
static
int
locomo_bus_suspend
(
struct
device
*
dev
,
pm_message_t
state
)
{
struct
locomo_dev
*
ldev
=
LOCOMO_DEV
(
dev
);
struct
locomo_driver
*
drv
=
LOCOMO_DRV
(
dev
->
driver
);
int
ret
=
0
;
if
(
drv
&&
drv
->
suspend
)
ret
=
drv
->
suspend
(
ldev
,
state
);
return
ret
;
}
static
int
locomo_bus_resume
(
struct
device
*
dev
)
{
struct
locomo_dev
*
ldev
=
LOCOMO_DEV
(
dev
);
struct
locomo_driver
*
drv
=
LOCOMO_DRV
(
dev
->
driver
);
int
ret
=
0
;
if
(
drv
&&
drv
->
resume
)
ret
=
drv
->
resume
(
ldev
);
return
ret
;
}
static
int
locomo_bus_probe
(
struct
device
*
dev
)
{
struct
locomo_dev
*
ldev
=
LOCOMO_DEV
(
dev
);
...
...
@@ -875,8 +853,6 @@ struct bus_type locomo_bus_type = {
.
match
=
locomo_match
,
.
probe
=
locomo_bus_probe
,
.
remove
=
locomo_bus_remove
,
.
suspend
=
locomo_bus_suspend
,
.
resume
=
locomo_bus_resume
,
};
int
locomo_driver_register
(
struct
locomo_driver
*
driver
)
...
...
arch/arm/include/asm/hardware/locomo.h
View file @
a5950f26
...
...
@@ -189,8 +189,6 @@ struct locomo_driver {
unsigned
int
devid
;
int
(
*
probe
)(
struct
locomo_dev
*
);
int
(
*
remove
)(
struct
locomo_dev
*
);
int
(
*
suspend
)(
struct
locomo_dev
*
,
pm_message_t
);
int
(
*
resume
)(
struct
locomo_dev
*
);
};
#define LOCOMO_DRV(_d) container_of((_d), struct locomo_driver, drv)
...
...
kernel/power/qos.c
View file @
a5950f26
...
...
@@ -701,8 +701,8 @@ static int __init pm_qos_power_init(void)
for
(
i
=
PM_QOS_CPU_DMA_LATENCY
;
i
<
PM_QOS_NUM_CLASSES
;
i
++
)
{
ret
=
register_pm_qos_misc
(
pm_qos_array
[
i
],
d
);
if
(
ret
<
0
)
{
pr
intk
(
KERN_ERR
"pm_qos_param
: %s setup failed
\n
"
,
pm_qos_array
[
i
]
->
name
);
pr
_err
(
"%s
: %s setup failed
\n
"
,
__func__
,
pm_qos_array
[
i
]
->
name
);
return
ret
;
}
}
...
...
kernel/power/snapshot.c
View file @
a5950f26
...
...
@@ -10,6 +10,8 @@
*
*/
#define pr_fmt(fmt) "PM: " fmt
#include <linux/version.h>
#include <linux/module.h>
#include <linux/mm.h>
...
...
@@ -967,7 +969,7 @@ void __init __register_nosave_region(unsigned long start_pfn,
region
->
end_pfn
=
end_pfn
;
list_add_tail
(
&
region
->
list
,
&
nosave_regions
);
Report:
pr
intk
(
KERN_INFO
"PM:
Registered nosave memory: [mem %#010llx-%#010llx]
\n
"
,
pr
_info
(
"
Registered nosave memory: [mem %#010llx-%#010llx]
\n
"
,
(
unsigned
long
long
)
start_pfn
<<
PAGE_SHIFT
,
((
unsigned
long
long
)
end_pfn
<<
PAGE_SHIFT
)
-
1
);
}
...
...
@@ -1039,7 +1041,7 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
list_for_each_entry
(
region
,
&
nosave_regions
,
list
)
{
unsigned
long
pfn
;
pr_debug
(
"
PM:
Marking nosave pages: [mem %#010llx-%#010llx]
\n
"
,
pr_debug
(
"Marking nosave pages: [mem %#010llx-%#010llx]
\n
"
,
(
unsigned
long
long
)
region
->
start_pfn
<<
PAGE_SHIFT
,
((
unsigned
long
long
)
region
->
end_pfn
<<
PAGE_SHIFT
)
-
1
);
...
...
@@ -1095,7 +1097,7 @@ int create_basic_memory_bitmaps(void)
free_pages_map
=
bm2
;
mark_nosave_pages
(
forbidden_pages_map
);
pr_debug
(
"
PM:
Basic memory bitmaps created
\n
"
);
pr_debug
(
"Basic memory bitmaps created
\n
"
);
return
0
;
...
...
@@ -1131,7 +1133,7 @@ void free_basic_memory_bitmaps(void)
memory_bm_free
(
bm2
,
PG_UNSAFE_CLEAR
);
kfree
(
bm2
);
pr_debug
(
"
PM:
Basic memory bitmaps freed
\n
"
);
pr_debug
(
"Basic memory bitmaps freed
\n
"
);
}
void
clear_free_pages
(
void
)
...
...
@@ -1152,7 +1154,7 @@ void clear_free_pages(void)
pfn
=
memory_bm_next_pfn
(
bm
);
}
memory_bm_position_reset
(
bm
);
pr_info
(
"
PM:
free pages cleared after restore
\n
"
);
pr_info
(
"free pages cleared after restore
\n
"
);
#endif
/* PAGE_POISONING_ZERO */
}
...
...
@@ -1690,7 +1692,7 @@ int hibernate_preallocate_memory(void)
ktime_t
start
,
stop
;
int
error
;
pr
intk
(
KERN_INFO
"PM:
Preallocating image memory... "
);
pr
_info
(
"
Preallocating image memory... "
);
start
=
ktime_get
();
error
=
memory_bm_create
(
&
orig_bm
,
GFP_IMAGE
,
PG_ANY
);
...
...
@@ -1821,13 +1823,13 @@ int hibernate_preallocate_memory(void)
out:
stop
=
ktime_get
();
pr
intk
(
KERN_CONT
"done (allocated %lu pages)
\n
"
,
pages
);
pr
_cont
(
"done (allocated %lu pages)
\n
"
,
pages
);
swsusp_show_speed
(
start
,
stop
,
pages
,
"Allocated"
);
return
0
;
err_out:
pr
intk
(
KERN_CONT
"
\n
"
);
pr
_cont
(
"
\n
"
);
swsusp_free
();
return
-
ENOMEM
;
}
...
...
@@ -1867,8 +1869,8 @@ static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
free
+=
zone_page_state
(
zone
,
NR_FREE_PAGES
);
nr_pages
+=
count_pages_for_highmem
(
nr_highmem
);
pr_debug
(
"
PM:
Normal pages needed: %u + %u, available pages: %u
\n
"
,
nr_pages
,
PAGES_FOR_IO
,
free
);
pr_debug
(
"Normal pages needed: %u + %u, available pages: %u
\n
"
,
nr_pages
,
PAGES_FOR_IO
,
free
);
return
free
>
nr_pages
+
PAGES_FOR_IO
;
}
...
...
@@ -1961,20 +1963,20 @@ asmlinkage __visible int swsusp_save(void)
{
unsigned
int
nr_pages
,
nr_highmem
;
pr
intk
(
KERN_INFO
"PM:
Creating hibernation image:
\n
"
);
pr
_info
(
"
Creating hibernation image:
\n
"
);
drain_local_pages
(
NULL
);
nr_pages
=
count_data_pages
();
nr_highmem
=
count_highmem_pages
();
pr
intk
(
KERN_INFO
"PM:
Need to copy %u pages
\n
"
,
nr_pages
+
nr_highmem
);
pr
_info
(
"
Need to copy %u pages
\n
"
,
nr_pages
+
nr_highmem
);
if
(
!
enough_free_mem
(
nr_pages
,
nr_highmem
))
{
pr
intk
(
KERN_ERR
"PM:
Not enough free memory
\n
"
);
pr
_err
(
"
Not enough free memory
\n
"
);
return
-
ENOMEM
;
}
if
(
swsusp_alloc
(
&
copy_bm
,
nr_pages
,
nr_highmem
))
{
pr
intk
(
KERN_ERR
"PM:
Memory allocation failed
\n
"
);
pr
_err
(
"
Memory allocation failed
\n
"
);
return
-
ENOMEM
;
}
...
...
@@ -1995,8 +1997,7 @@ asmlinkage __visible int swsusp_save(void)
nr_copy_pages
=
nr_pages
;
nr_meta_pages
=
DIV_ROUND_UP
(
nr_pages
*
sizeof
(
long
),
PAGE_SIZE
);
printk
(
KERN_INFO
"PM: Hibernation image created (%d pages copied)
\n
"
,
nr_pages
);
pr_info
(
"Hibernation image created (%d pages copied)
\n
"
,
nr_pages
);
return
0
;
}
...
...
@@ -2170,7 +2171,7 @@ static int check_header(struct swsusp_info *info)
if
(
!
reason
&&
info
->
num_physpages
!=
get_num_physpages
())
reason
=
"memory size"
;
if
(
reason
)
{
pr
intk
(
KERN_ERR
"PM:
Image mismatch: %s
\n
"
,
reason
);
pr
_err
(
"
Image mismatch: %s
\n
"
,
reason
);
return
-
EPERM
;
}
return
0
;
...
...
kernel/power/swap.c
View file @
a5950f26
This diff is collapsed.
Click to expand it.
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