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
cba630b6
Commit
cba630b6
authored
Aug 29, 2017
by
Rafael J. Wysocki
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'pm-sleep' into pm-docs
parents
0c0b6b7b
726fb6b4
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
622 additions
and
291 deletions
+622
-291
Documentation/ABI/testing/sysfs-power
Documentation/ABI/testing/sysfs-power
+12
-0
Documentation/power/states.txt
Documentation/power/states.txt
+3
-1
arch/arm/mach-tegra/cpuidle-tegra114.c
arch/arm/mach-tegra/cpuidle-tegra114.c
+2
-2
drivers/acpi/processor_idle.c
drivers/acpi/processor_idle.c
+3
-3
drivers/acpi/sleep.c
drivers/acpi/sleep.c
+188
-14
drivers/base/power/main.c
drivers/base/power/main.c
+64
-39
drivers/base/power/wakeup.c
drivers/base/power/wakeup.c
+1
-1
drivers/cpuidle/cpuidle.c
drivers/cpuidle/cpuidle.c
+9
-9
drivers/cpuidle/dt_idle_states.c
drivers/cpuidle/dt_idle_states.c
+2
-2
drivers/idle/intel_idle.c
drivers/idle/intel_idle.c
+90
-90
drivers/platform/x86/intel-hid.c
drivers/platform/x86/intel-hid.c
+14
-3
drivers/regulator/of_regulator.c
drivers/regulator/of_regulator.c
+1
-1
include/linux/cpuidle.h
include/linux/cpuidle.h
+4
-4
include/linux/pm.h
include/linux/pm.h
+4
-0
include/linux/suspend.h
include/linux/suspend.h
+33
-15
kernel/power/hibernate.c
kernel/power/hibernate.c
+17
-12
kernel/power/main.c
kernel/power/main.c
+59
-5
kernel/power/power.h
kernel/power/power.h
+4
-1
kernel/power/suspend.c
kernel/power/suspend.c
+103
-81
kernel/power/suspend_test.c
kernel/power/suspend_test.c
+2
-2
kernel/sched/idle.c
kernel/sched/idle.c
+4
-4
kernel/time/timekeeping_debug.c
kernel/time/timekeeping_debug.c
+3
-2
No files found.
Documentation/ABI/testing/sysfs-power
View file @
cba630b6
...
...
@@ -273,3 +273,15 @@ Description:
This output is useful for system wakeup diagnostics of spurious
wakeup interrupts.
What: /sys/power/pm_debug_messages
Date: July 2017
Contact: Rafael J. Wysocki <rjw@rjwysocki.net>
Description:
The /sys/power/pm_debug_messages file controls the printing
of debug messages from the system suspend/hiberbation
infrastructure to the kernel log.
Writing a "1" to this file enables the debug messages and
writing a "0" (default) to it disables them. Reads from
this file return the current value.
Documentation/power/states.txt
View file @
cba630b6
...
...
@@ -35,7 +35,9 @@ only one way to cause the system to go into the Suspend-To-RAM state (write
The default suspend mode (ie. the one to be used without writing anything into
/sys/power/mem_sleep) is either "deep" (if Suspend-To-RAM is supported) or
"s2idle", but it can be overridden by the value of the "mem_sleep_default"
parameter in the kernel command line.
parameter in the kernel command line. On some ACPI-based systems, depending on
the information in the FADT, the default may be "s2idle" even if Suspend-To-RAM
is supported.
The properties of all of the sleep states are described below.
...
...
arch/arm/mach-tegra/cpuidle-tegra114.c
View file @
cba630b6
...
...
@@ -60,7 +60,7 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
return
index
;
}
static
void
tegra114_idle_enter_
freez
e
(
struct
cpuidle_device
*
dev
,
static
void
tegra114_idle_enter_
s2idl
e
(
struct
cpuidle_device
*
dev
,
struct
cpuidle_driver
*
drv
,
int
index
)
{
...
...
@@ -77,7 +77,7 @@ static struct cpuidle_driver tegra_idle_driver = {
#ifdef CONFIG_PM_SLEEP
[
1
]
=
{
.
enter
=
tegra114_idle_power_down
,
.
enter_
freeze
=
tegra114_idle_enter_freez
e
,
.
enter_
s2idle
=
tegra114_idle_enter_s2idl
e
,
.
exit_latency
=
500
,
.
target_residency
=
1000
,
.
flags
=
CPUIDLE_FLAG_TIMER_STOP
,
...
...
drivers/acpi/processor_idle.c
View file @
cba630b6
...
...
@@ -789,7 +789,7 @@ static int acpi_idle_enter(struct cpuidle_device *dev,
return
index
;
}
static
void
acpi_idle_enter_
freez
e
(
struct
cpuidle_device
*
dev
,
static
void
acpi_idle_enter_
s2idl
e
(
struct
cpuidle_device
*
dev
,
struct
cpuidle_driver
*
drv
,
int
index
)
{
struct
acpi_processor_cx
*
cx
=
per_cpu
(
acpi_cstate
[
index
],
dev
->
cpu
);
...
...
@@ -867,14 +867,14 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
drv
->
safe_state_index
=
count
;
}
/*
* Halt-induced C1 is not good for ->enter_
freez
e, because it
* Halt-induced C1 is not good for ->enter_
s2idl
e, because it
* re-enables interrupts on exit. Moreover, C1 is generally not
* particularly interesting from the suspend-to-idle angle, so
* avoid C1 and the situations in which we may need to fall back
* to it altogether.
*/
if
(
cx
->
type
!=
ACPI_STATE_C1
&&
!
acpi_idle_fallback_to_c1
(
pr
))
state
->
enter_
freeze
=
acpi_idle_enter_freez
e
;
state
->
enter_
s2idle
=
acpi_idle_enter_s2idl
e
;
count
++
;
if
(
count
==
CPUIDLE_STATE_MAX
)
...
...
drivers/acpi/sleep.c
View file @
cba630b6
...
...
@@ -669,6 +669,7 @@ static const struct acpi_device_id lps0_device_ids[] = {
#define ACPI_LPS0_DSM_UUID "c4eb40a0-6cd2-11e2-bcfd-0800200c9a66"
#define ACPI_LPS0_GET_DEVICE_CONSTRAINTS 1
#define ACPI_LPS0_SCREEN_OFF 3
#define ACPI_LPS0_SCREEN_ON 4
#define ACPI_LPS0_ENTRY 5
...
...
@@ -680,6 +681,166 @@ static acpi_handle lps0_device_handle;
static
guid_t
lps0_dsm_guid
;
static
char
lps0_dsm_func_mask
;
/* Device constraint entry structure */
struct
lpi_device_info
{
char
*
name
;
int
enabled
;
union
acpi_object
*
package
;
};
/* Constraint package structure */
struct
lpi_device_constraint
{
int
uid
;
int
min_dstate
;
int
function_states
;
};
struct
lpi_constraints
{
acpi_handle
handle
;
int
min_dstate
;
};
static
struct
lpi_constraints
*
lpi_constraints_table
;
static
int
lpi_constraints_table_size
;
static
void
lpi_device_get_constraints
(
void
)
{
union
acpi_object
*
out_obj
;
int
i
;
out_obj
=
acpi_evaluate_dsm_typed
(
lps0_device_handle
,
&
lps0_dsm_guid
,
1
,
ACPI_LPS0_GET_DEVICE_CONSTRAINTS
,
NULL
,
ACPI_TYPE_PACKAGE
);
acpi_handle_debug
(
lps0_device_handle
,
"_DSM function 1 eval %s
\n
"
,
out_obj
?
"successful"
:
"failed"
);
if
(
!
out_obj
)
return
;
lpi_constraints_table
=
kcalloc
(
out_obj
->
package
.
count
,
sizeof
(
*
lpi_constraints_table
),
GFP_KERNEL
);
if
(
!
lpi_constraints_table
)
goto
free_acpi_buffer
;
acpi_handle_debug
(
lps0_device_handle
,
"LPI: constraints list begin:
\n
"
);
for
(
i
=
0
;
i
<
out_obj
->
package
.
count
;
i
++
)
{
struct
lpi_constraints
*
constraint
;
acpi_status
status
;
union
acpi_object
*
package
=
&
out_obj
->
package
.
elements
[
i
];
struct
lpi_device_info
info
=
{
};
int
package_count
=
0
,
j
;
if
(
!
package
)
continue
;
for
(
j
=
0
;
j
<
package
->
package
.
count
;
++
j
)
{
union
acpi_object
*
element
=
&
(
package
->
package
.
elements
[
j
]);
switch
(
element
->
type
)
{
case
ACPI_TYPE_INTEGER
:
info
.
enabled
=
element
->
integer
.
value
;
break
;
case
ACPI_TYPE_STRING
:
info
.
name
=
element
->
string
.
pointer
;
break
;
case
ACPI_TYPE_PACKAGE
:
package_count
=
element
->
package
.
count
;
info
.
package
=
element
->
package
.
elements
;
break
;
}
}
if
(
!
info
.
enabled
||
!
info
.
package
||
!
info
.
name
)
continue
;
constraint
=
&
lpi_constraints_table
[
lpi_constraints_table_size
];
status
=
acpi_get_handle
(
NULL
,
info
.
name
,
&
constraint
->
handle
);
if
(
ACPI_FAILURE
(
status
))
continue
;
acpi_handle_debug
(
lps0_device_handle
,
"index:%d Name:%s
\n
"
,
i
,
info
.
name
);
constraint
->
min_dstate
=
-
1
;
for
(
j
=
0
;
j
<
package_count
;
++
j
)
{
union
acpi_object
*
info_obj
=
&
info
.
package
[
j
];
union
acpi_object
*
cnstr_pkg
;
union
acpi_object
*
obj
;
struct
lpi_device_constraint
dev_info
;
switch
(
info_obj
->
type
)
{
case
ACPI_TYPE_INTEGER
:
/* version */
break
;
case
ACPI_TYPE_PACKAGE
:
if
(
info_obj
->
package
.
count
<
2
)
break
;
cnstr_pkg
=
info_obj
->
package
.
elements
;
obj
=
&
cnstr_pkg
[
0
];
dev_info
.
uid
=
obj
->
integer
.
value
;
obj
=
&
cnstr_pkg
[
1
];
dev_info
.
min_dstate
=
obj
->
integer
.
value
;
acpi_handle_debug
(
lps0_device_handle
,
"uid:%d min_dstate:%s
\n
"
,
dev_info
.
uid
,
acpi_power_state_string
(
dev_info
.
min_dstate
));
constraint
->
min_dstate
=
dev_info
.
min_dstate
;
break
;
}
}
if
(
constraint
->
min_dstate
<
0
)
{
acpi_handle_debug
(
lps0_device_handle
,
"Incomplete constraint defined
\n
"
);
continue
;
}
lpi_constraints_table_size
++
;
}
acpi_handle_debug
(
lps0_device_handle
,
"LPI: constraints list end
\n
"
);
free_acpi_buffer:
ACPI_FREE
(
out_obj
);
}
static
void
lpi_check_constraints
(
void
)
{
int
i
;
for
(
i
=
0
;
i
<
lpi_constraints_table_size
;
++
i
)
{
struct
acpi_device
*
adev
;
if
(
acpi_bus_get_device
(
lpi_constraints_table
[
i
].
handle
,
&
adev
))
continue
;
acpi_handle_debug
(
adev
->
handle
,
"LPI: required min power state:%s current power state:%s
\n
"
,
acpi_power_state_string
(
lpi_constraints_table
[
i
].
min_dstate
),
acpi_power_state_string
(
adev
->
power
.
state
));
if
(
!
adev
->
flags
.
power_manageable
)
{
acpi_handle_info
(
adev
->
handle
,
"LPI: Device not power manageble
\n
"
);
continue
;
}
if
(
adev
->
power
.
state
<
lpi_constraints_table
[
i
].
min_dstate
)
acpi_handle_info
(
adev
->
handle
,
"LPI: Constraint not met; min power state:%s current power state:%s
\n
"
,
acpi_power_state_string
(
lpi_constraints_table
[
i
].
min_dstate
),
acpi_power_state_string
(
adev
->
power
.
state
));
}
}
static
void
acpi_sleep_run_lps0_dsm
(
unsigned
int
func
)
{
union
acpi_object
*
out_obj
;
...
...
@@ -714,6 +875,12 @@ static int lps0_device_attach(struct acpi_device *adev,
if
((
bitmask
&
ACPI_S2IDLE_FUNC_MASK
)
==
ACPI_S2IDLE_FUNC_MASK
)
{
lps0_dsm_func_mask
=
bitmask
;
lps0_device_handle
=
adev
->
handle
;
/*
* Use suspend-to-idle by default if the default
* suspend mode was not set from the command line.
*/
if
(
mem_sleep_default
>
PM_SUSPEND_MEM
)
mem_sleep_current
=
PM_SUSPEND_TO_IDLE
;
}
acpi_handle_debug
(
adev
->
handle
,
"_DSM function mask: 0x%x
\n
"
,
...
...
@@ -723,6 +890,9 @@ static int lps0_device_attach(struct acpi_device *adev,
"_DSM function 0 evaluation failed
\n
"
);
}
ACPI_FREE
(
out_obj
);
lpi_device_get_constraints
();
return
0
;
}
...
...
@@ -731,14 +901,14 @@ static struct acpi_scan_handler lps0_handler = {
.
attach
=
lps0_device_attach
,
};
static
int
acpi_
freez
e_begin
(
void
)
static
int
acpi_
s2idl
e_begin
(
void
)
{
acpi_scan_lock_acquire
();
s2idle_in_progress
=
true
;
return
0
;
}
static
int
acpi_
freez
e_prepare
(
void
)
static
int
acpi_
s2idl
e_prepare
(
void
)
{
if
(
lps0_device_handle
)
{
acpi_sleep_run_lps0_dsm
(
ACPI_LPS0_SCREEN_OFF
);
...
...
@@ -758,8 +928,12 @@ static int acpi_freeze_prepare(void)
return
0
;
}
static
void
acpi_
freez
e_wake
(
void
)
static
void
acpi_
s2idl
e_wake
(
void
)
{
if
(
pm_debug_messages_on
)
lpi_check_constraints
();
/*
* If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means
* that the SCI has triggered while suspended, so cancel the wakeup in
...
...
@@ -772,7 +946,7 @@ static void acpi_freeze_wake(void)
}
}
static
void
acpi_
freez
e_sync
(
void
)
static
void
acpi_
s2idl
e_sync
(
void
)
{
/*
* Process all pending events in case there are any wakeup ones.
...
...
@@ -785,7 +959,7 @@ static void acpi_freeze_sync(void)
s2idle_wakeup
=
false
;
}
static
void
acpi_
freez
e_restore
(
void
)
static
void
acpi_
s2idl
e_restore
(
void
)
{
if
(
acpi_sci_irq_valid
())
disable_irq_wake
(
acpi_sci_irq
);
...
...
@@ -798,19 +972,19 @@ static void acpi_freeze_restore(void)
}
}
static
void
acpi_
freez
e_end
(
void
)
static
void
acpi_
s2idl
e_end
(
void
)
{
s2idle_in_progress
=
false
;
acpi_scan_lock_release
();
}
static
const
struct
platform_
freeze_ops
acpi_freez
e_ops
=
{
.
begin
=
acpi_
freez
e_begin
,
.
prepare
=
acpi_
freez
e_prepare
,
.
wake
=
acpi_
freez
e_wake
,
.
sync
=
acpi_
freez
e_sync
,
.
restore
=
acpi_
freez
e_restore
,
.
end
=
acpi_
freez
e_end
,
static
const
struct
platform_
s2idle_ops
acpi_s2idl
e_ops
=
{
.
begin
=
acpi_
s2idl
e_begin
,
.
prepare
=
acpi_
s2idl
e_prepare
,
.
wake
=
acpi_
s2idl
e_wake
,
.
sync
=
acpi_
s2idl
e_sync
,
.
restore
=
acpi_
s2idl
e_restore
,
.
end
=
acpi_
s2idl
e_end
,
};
static
void
acpi_sleep_suspend_setup
(
void
)
...
...
@@ -825,7 +999,7 @@ static void acpi_sleep_suspend_setup(void)
&
acpi_suspend_ops_old
:
&
acpi_suspend_ops
);
acpi_scan_add_handler
(
&
lps0_handler
);
freeze_set_ops
(
&
acpi_freez
e_ops
);
s2idle_set_ops
(
&
acpi_s2idl
e_ops
);
}
#else
/* !CONFIG_SUSPEND */
...
...
drivers/base/power/main.c
View file @
cba630b6
...
...
@@ -418,8 +418,7 @@ static void pm_dev_err(struct device *dev, pm_message_t state, const char *info,
dev_name
(
dev
),
pm_verb
(
state
.
event
),
info
,
error
);
}
#ifdef CONFIG_PM_DEBUG
static
void
dpm_show_time
(
ktime_t
starttime
,
pm_message_t
state
,
static
void
dpm_show_time
(
ktime_t
starttime
,
pm_message_t
state
,
int
error
,
const
char
*
info
)
{
ktime_t
calltime
;
...
...
@@ -432,14 +431,12 @@ static void dpm_show_time(ktime_t starttime, pm_message_t state,
usecs
=
usecs64
;
if
(
usecs
==
0
)
usecs
=
1
;
pr_info
(
"PM: %s%s%s of devices complete after %ld.%03ld msecs
\n
"
,
info
?:
""
,
info
?
" "
:
""
,
pm_verb
(
state
.
event
),
usecs
/
USEC_PER_MSEC
,
usecs
%
USEC_PER_MSEC
);
pm_pr_dbg
(
"%s%s%s of devices %s after %ld.%03ld msecs
\n
"
,
info
?:
""
,
info
?
" "
:
""
,
pm_verb
(
state
.
event
),
error
?
"aborted"
:
"complete"
,
usecs
/
USEC_PER_MSEC
,
usecs
%
USEC_PER_MSEC
);
}
#else
static
inline
void
dpm_show_time
(
ktime_t
starttime
,
pm_message_t
state
,
const
char
*
info
)
{}
#endif
/* CONFIG_PM_DEBUG */
static
int
dpm_run_callback
(
pm_callback_t
cb
,
struct
device
*
dev
,
pm_message_t
state
,
const
char
*
info
)
...
...
@@ -602,14 +599,7 @@ static void async_resume_noirq(void *data, async_cookie_t cookie)
put_device
(
dev
);
}
/**
* dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
* @state: PM transition of the system being carried out.
*
* Call the "noirq" resume handlers for all devices in dpm_noirq_list and
* enable device drivers to receive interrupts.
*/
void
dpm_resume_noirq
(
pm_message_t
state
)
void
dpm_noirq_resume_devices
(
pm_message_t
state
)
{
struct
device
*
dev
;
ktime_t
starttime
=
ktime_get
();
...
...
@@ -654,11 +644,28 @@ void dpm_resume_noirq(pm_message_t state)
}
mutex_unlock
(
&
dpm_list_mtx
);
async_synchronize_full
();
dpm_show_time
(
starttime
,
state
,
"noirq"
);
dpm_show_time
(
starttime
,
state
,
0
,
"noirq"
);
trace_suspend_resume
(
TPS
(
"dpm_resume_noirq"
),
state
.
event
,
false
);
}
void
dpm_noirq_end
(
void
)
{
resume_device_irqs
();
device_wakeup_disarm_wake_irqs
();
cpuidle_resume
();
trace_suspend_resume
(
TPS
(
"dpm_resume_noirq"
),
state
.
event
,
false
);
}
/**
* dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
* @state: PM transition of the system being carried out.
*
* Invoke the "noirq" resume callbacks for all devices in dpm_noirq_list and
* allow device drivers' interrupt handlers to be called.
*/
void
dpm_resume_noirq
(
pm_message_t
state
)
{
dpm_noirq_resume_devices
(
state
);
dpm_noirq_end
();
}
/**
...
...
@@ -776,7 +783,7 @@ void dpm_resume_early(pm_message_t state)
}
mutex_unlock
(
&
dpm_list_mtx
);
async_synchronize_full
();
dpm_show_time
(
starttime
,
state
,
"early"
);
dpm_show_time
(
starttime
,
state
,
0
,
"early"
);
trace_suspend_resume
(
TPS
(
"dpm_resume_early"
),
state
.
event
,
false
);
}
...
...
@@ -948,7 +955,7 @@ void dpm_resume(pm_message_t state)
}
mutex_unlock
(
&
dpm_list_mtx
);
async_synchronize_full
();
dpm_show_time
(
starttime
,
state
,
NULL
);
dpm_show_time
(
starttime
,
state
,
0
,
NULL
);
cpufreq_resume
();
trace_suspend_resume
(
TPS
(
"dpm_resume"
),
state
.
event
,
false
);
...
...
@@ -1098,6 +1105,11 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
if
(
async_error
)
goto
Complete
;
if
(
pm_wakeup_pending
())
{
async_error
=
-
EBUSY
;
goto
Complete
;
}
if
(
dev
->
power
.
syscore
||
dev
->
power
.
direct_complete
)
goto
Complete
;
...
...
@@ -1158,22 +1170,19 @@ static int device_suspend_noirq(struct device *dev)
return
__device_suspend_noirq
(
dev
,
pm_transition
,
false
);
}
/**
* dpm_suspend_noirq - Execute "noirq suspend" callbacks for all devices.
* @state: PM transition of the system being carried out.
*
* Prevent device drivers from receiving interrupts and call the "noirq" suspend
* handlers for all non-sysdev devices.
*/
int
dpm_
suspend_noirq
(
pm_message_t
state
)
void
dpm_noirq_begin
(
void
)
{
cpuidle_pause
();
device_wakeup_arm_wake_irqs
();
suspend_device_irqs
();
}
int
dpm_
noirq_suspend_devices
(
pm_message_t
state
)
{
ktime_t
starttime
=
ktime_get
();
int
error
=
0
;
trace_suspend_resume
(
TPS
(
"dpm_suspend_noirq"
),
state
.
event
,
true
);
cpuidle_pause
();
device_wakeup_arm_wake_irqs
();
suspend_device_irqs
();
mutex_lock
(
&
dpm_list_mtx
);
pm_transition
=
state
;
async_error
=
0
;
...
...
@@ -1208,14 +1217,31 @@ int dpm_suspend_noirq(pm_message_t state)
if
(
error
)
{
suspend_stats
.
failed_suspend_noirq
++
;
dpm_save_failed_step
(
SUSPEND_SUSPEND_NOIRQ
);
dpm_resume_noirq
(
resume_event
(
state
));
}
else
{
dpm_show_time
(
starttime
,
state
,
"noirq"
);
}
dpm_show_time
(
starttime
,
state
,
error
,
"noirq"
);
trace_suspend_resume
(
TPS
(
"dpm_suspend_noirq"
),
state
.
event
,
false
);
return
error
;
}
/**
* dpm_suspend_noirq - Execute "noirq suspend" callbacks for all devices.
* @state: PM transition of the system being carried out.
*
* Prevent device drivers' interrupt handlers from being called and invoke
* "noirq" suspend callbacks for all non-sysdev devices.
*/
int
dpm_suspend_noirq
(
pm_message_t
state
)
{
int
ret
;
dpm_noirq_begin
();
ret
=
dpm_noirq_suspend_devices
(
state
);
if
(
ret
)
dpm_resume_noirq
(
resume_event
(
state
));
return
ret
;
}
/**
* device_suspend_late - Execute a "late suspend" callback for given device.
* @dev: Device to handle.
...
...
@@ -1350,9 +1376,8 @@ int dpm_suspend_late(pm_message_t state)
suspend_stats
.
failed_suspend_late
++
;
dpm_save_failed_step
(
SUSPEND_SUSPEND_LATE
);
dpm_resume_early
(
resume_event
(
state
));
}
else
{
dpm_show_time
(
starttime
,
state
,
"late"
);
}
dpm_show_time
(
starttime
,
state
,
error
,
"late"
);
trace_suspend_resume
(
TPS
(
"dpm_suspend_late"
),
state
.
event
,
false
);
return
error
;
}
...
...
@@ -1618,8 +1643,8 @@ int dpm_suspend(pm_message_t state)
if
(
error
)
{
suspend_stats
.
failed_suspend
++
;
dpm_save_failed_step
(
SUSPEND_SUSPEND
);
}
else
dpm_show_time
(
starttime
,
state
,
NULL
);
}
dpm_show_time
(
starttime
,
state
,
error
,
NULL
);
trace_suspend_resume
(
TPS
(
"dpm_suspend"
),
state
.
event
,
false
);
return
error
;
}
...
...
drivers/base/power/wakeup.c
View file @
cba630b6
...
...
@@ -863,7 +863,7 @@ bool pm_wakeup_pending(void)
void
pm_system_wakeup
(
void
)
{
atomic_inc
(
&
pm_abort_suspend
);
freez
e_wake
();
s2idl
e_wake
();
}
EXPORT_SYMBOL_GPL
(
pm_system_wakeup
);
...
...
drivers/cpuidle/cpuidle.c
View file @
cba630b6
...
...
@@ -77,7 +77,7 @@ static int find_deepest_state(struct cpuidle_driver *drv,
struct
cpuidle_device
*
dev
,
unsigned
int
max_latency
,
unsigned
int
forbidden_flags
,
bool
freez
e
)
bool
s2idl
e
)
{
unsigned
int
latency_req
=
0
;
int
i
,
ret
=
0
;
...
...
@@ -89,7 +89,7 @@ static int find_deepest_state(struct cpuidle_driver *drv,
if
(
s
->
disabled
||
su
->
disable
||
s
->
exit_latency
<=
latency_req
||
s
->
exit_latency
>
max_latency
||
(
s
->
flags
&
forbidden_flags
)
||
(
freeze
&&
!
s
->
enter_freez
e
))
||
(
s2idle
&&
!
s
->
enter_s2idl
e
))
continue
;
latency_req
=
s
->
exit_latency
;
...
...
@@ -128,7 +128,7 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
}
#ifdef CONFIG_SUSPEND
static
void
enter_
freez
e_proper
(
struct
cpuidle_driver
*
drv
,
static
void
enter_
s2idl
e_proper
(
struct
cpuidle_driver
*
drv
,
struct
cpuidle_device
*
dev
,
int
index
)
{
/*
...
...
@@ -143,7 +143,7 @@ static void enter_freeze_proper(struct cpuidle_driver *drv,
* suspended is generally unsafe.
*/
stop_critical_timings
();
drv
->
states
[
index
].
enter_
freez
e
(
dev
,
drv
,
index
);
drv
->
states
[
index
].
enter_
s2idl
e
(
dev
,
drv
,
index
);
WARN_ON
(
!
irqs_disabled
());
/*
* timekeeping_resume() that will be called by tick_unfreeze() for the
...
...
@@ -155,25 +155,25 @@ static void enter_freeze_proper(struct cpuidle_driver *drv,
}
/**
* cpuidle_enter_
freez
e - Enter an idle state suitable for suspend-to-idle.
* cpuidle_enter_
s2idl
e - Enter an idle state suitable for suspend-to-idle.
* @drv: cpuidle driver for the given CPU.
* @dev: cpuidle device for the given CPU.
*
* If there are states with the ->enter_
freez
e callback, find the deepest of
* If there are states with the ->enter_
s2idl
e callback, find the deepest of
* them and enter it with frozen tick.
*/
int
cpuidle_enter_
freez
e
(
struct
cpuidle_driver
*
drv
,
struct
cpuidle_device
*
dev
)
int
cpuidle_enter_
s2idl
e
(
struct
cpuidle_driver
*
drv
,
struct
cpuidle_device
*
dev
)
{
int
index
;
/*
* Find the deepest state with ->enter_
freez
e present, which guarantees
* Find the deepest state with ->enter_
s2idl
e present, which guarantees
* that interrupts won't be enabled when it exits and allows the tick to
* be frozen safely.
*/
index
=
find_deepest_state
(
drv
,
dev
,
UINT_MAX
,
0
,
true
);
if
(
index
>
0
)
enter_
freez
e_proper
(
drv
,
dev
,
index
);
enter_
s2idl
e_proper
(
drv
,
dev
,
index
);
return
index
;
}
...
...
drivers/cpuidle/dt_idle_states.c
View file @
cba630b6
...
...
@@ -41,9 +41,9 @@ static int init_state_node(struct cpuidle_state *idle_state,
/*
* Since this is not a "coupled" state, it's safe to assume interrupts
* won't be enabled when it exits allowing the tick to be frozen
* safely. So enter() can be also enter_
freez
e() callback.
* safely. So enter() can be also enter_
s2idl
e() callback.
*/
idle_state
->
enter_
freez
e
=
match_id
->
data
;
idle_state
->
enter_
s2idl
e
=
match_id
->
data
;
err
=
of_property_read_u32
(
state_node
,
"wakeup-latency-us"
,
&
idle_state
->
exit_latency
);
...
...
drivers/idle/intel_idle.c
View file @
cba630b6
...
...
@@ -97,7 +97,7 @@ static const struct idle_cpu *icpu;
static
struct
cpuidle_device
__percpu
*
intel_idle_cpuidle_devices
;
static
int
intel_idle
(
struct
cpuidle_device
*
dev
,
struct
cpuidle_driver
*
drv
,
int
index
);
static
void
intel_idle_
freez
e
(
struct
cpuidle_device
*
dev
,
static
void
intel_idle_
s2idl
e
(
struct
cpuidle_device
*
dev
,
struct
cpuidle_driver
*
drv
,
int
index
);
static
struct
cpuidle_state
*
cpuidle_state_table
;
...
...
@@ -132,7 +132,7 @@ static struct cpuidle_state nehalem_cstates[] = {
.
exit_latency
=
3
,
.
target_residency
=
6
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -140,7 +140,7 @@ static struct cpuidle_state nehalem_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -148,7 +148,7 @@ static struct cpuidle_state nehalem_cstates[] = {
.
exit_latency
=
20
,
.
target_residency
=
80
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[] = {
.
exit_latency
=
200
,
.
target_residency
=
800
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -169,7 +169,7 @@ static struct cpuidle_state snb_cstates[] = {
.
exit_latency
=
2
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -177,7 +177,7 @@ static struct cpuidle_state snb_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -185,7 +185,7 @@ static struct cpuidle_state snb_cstates[] = {
.
exit_latency
=
80
,
.
target_residency
=
211
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -193,7 +193,7 @@ static struct cpuidle_state snb_cstates[] = {
.
exit_latency
=
104
,
.
target_residency
=
345
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7"
,
.
desc
=
"MWAIT 0x30"
,
...
...
@@ -201,7 +201,7 @@ static struct cpuidle_state snb_cstates[] = {
.
exit_latency
=
109
,
.
target_residency
=
345
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -214,7 +214,7 @@ static struct cpuidle_state byt_cstates[] = {
.
exit_latency
=
1
,
.
target_residency
=
1
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6N"
,
.
desc
=
"MWAIT 0x58"
,
...
...
@@ -222,7 +222,7 @@ static struct cpuidle_state byt_cstates[] = {
.
exit_latency
=
300
,
.
target_residency
=
275
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6S"
,
.
desc
=
"MWAIT 0x52"
,
...
...
@@ -230,7 +230,7 @@ static struct cpuidle_state byt_cstates[] = {
.
exit_latency
=
500
,
.
target_residency
=
560
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7"
,
.
desc
=
"MWAIT 0x60"
,
...
...
@@ -238,7 +238,7 @@ static struct cpuidle_state byt_cstates[] = {
.
exit_latency
=
1200
,
.
target_residency
=
4000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7S"
,
.
desc
=
"MWAIT 0x64"
,
...
...
@@ -246,7 +246,7 @@ static struct cpuidle_state byt_cstates[] = {
.
exit_latency
=
10000
,
.
target_residency
=
20000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -259,7 +259,7 @@ static struct cpuidle_state cht_cstates[] = {
.
exit_latency
=
1
,
.
target_residency
=
1
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6N"
,
.
desc
=
"MWAIT 0x58"
,
...
...
@@ -267,7 +267,7 @@ static struct cpuidle_state cht_cstates[] = {
.
exit_latency
=
80
,
.
target_residency
=
275
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6S"
,
.
desc
=
"MWAIT 0x52"
,
...
...
@@ -275,7 +275,7 @@ static struct cpuidle_state cht_cstates[] = {
.
exit_latency
=
200
,
.
target_residency
=
560
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7"
,
.
desc
=
"MWAIT 0x60"
,
...
...
@@ -283,7 +283,7 @@ static struct cpuidle_state cht_cstates[] = {
.
exit_latency
=
1200
,
.
target_residency
=
4000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7S"
,
.
desc
=
"MWAIT 0x64"
,
...
...
@@ -291,7 +291,7 @@ static struct cpuidle_state cht_cstates[] = {
.
exit_latency
=
10000
,
.
target_residency
=
20000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -304,7 +304,7 @@ static struct cpuidle_state ivb_cstates[] = {
.
exit_latency
=
1
,
.
target_residency
=
1
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -312,7 +312,7 @@ static struct cpuidle_state ivb_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -320,7 +320,7 @@ static struct cpuidle_state ivb_cstates[] = {
.
exit_latency
=
59
,
.
target_residency
=
156
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -328,7 +328,7 @@ static struct cpuidle_state ivb_cstates[] = {
.
exit_latency
=
80
,
.
target_residency
=
300
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7"
,
.
desc
=
"MWAIT 0x30"
,
...
...
@@ -336,7 +336,7 @@ static struct cpuidle_state ivb_cstates[] = {
.
exit_latency
=
87
,
.
target_residency
=
300
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -349,7 +349,7 @@ static struct cpuidle_state ivt_cstates[] = {
.
exit_latency
=
1
,
.
target_residency
=
1
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -357,7 +357,7 @@ static struct cpuidle_state ivt_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
80
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -365,7 +365,7 @@ static struct cpuidle_state ivt_cstates[] = {
.
exit_latency
=
59
,
.
target_residency
=
156
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -373,7 +373,7 @@ static struct cpuidle_state ivt_cstates[] = {
.
exit_latency
=
82
,
.
target_residency
=
300
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -386,7 +386,7 @@ static struct cpuidle_state ivt_cstates_4s[] = {
.
exit_latency
=
1
,
.
target_residency
=
1
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -394,7 +394,7 @@ static struct cpuidle_state ivt_cstates_4s[] = {
.
exit_latency
=
10
,
.
target_residency
=
250
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -402,7 +402,7 @@ static struct cpuidle_state ivt_cstates_4s[] = {
.
exit_latency
=
59
,
.
target_residency
=
300
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -410,7 +410,7 @@ static struct cpuidle_state ivt_cstates_4s[] = {
.
exit_latency
=
84
,
.
target_residency
=
400
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -423,7 +423,7 @@ static struct cpuidle_state ivt_cstates_8s[] = {
.
exit_latency
=
1
,
.
target_residency
=
1
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -431,7 +431,7 @@ static struct cpuidle_state ivt_cstates_8s[] = {
.
exit_latency
=
10
,
.
target_residency
=
500
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -439,7 +439,7 @@ static struct cpuidle_state ivt_cstates_8s[] = {
.
exit_latency
=
59
,
.
target_residency
=
600
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -447,7 +447,7 @@ static struct cpuidle_state ivt_cstates_8s[] = {
.
exit_latency
=
88
,
.
target_residency
=
700
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -460,7 +460,7 @@ static struct cpuidle_state hsw_cstates[] = {
.
exit_latency
=
2
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -468,7 +468,7 @@ static struct cpuidle_state hsw_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -476,7 +476,7 @@ static struct cpuidle_state hsw_cstates[] = {
.
exit_latency
=
33
,
.
target_residency
=
100
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -484,7 +484,7 @@ static struct cpuidle_state hsw_cstates[] = {
.
exit_latency
=
133
,
.
target_residency
=
400
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7s"
,
.
desc
=
"MWAIT 0x32"
,
...
...
@@ -492,7 +492,7 @@ static struct cpuidle_state hsw_cstates[] = {
.
exit_latency
=
166
,
.
target_residency
=
500
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C8"
,
.
desc
=
"MWAIT 0x40"
,
...
...
@@ -500,7 +500,7 @@ static struct cpuidle_state hsw_cstates[] = {
.
exit_latency
=
300
,
.
target_residency
=
900
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C9"
,
.
desc
=
"MWAIT 0x50"
,
...
...
@@ -508,7 +508,7 @@ static struct cpuidle_state hsw_cstates[] = {
.
exit_latency
=
600
,
.
target_residency
=
1800
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C10"
,
.
desc
=
"MWAIT 0x60"
,
...
...
@@ -516,7 +516,7 @@ static struct cpuidle_state hsw_cstates[] = {
.
exit_latency
=
2600
,
.
target_residency
=
7700
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -528,7 +528,7 @@ static struct cpuidle_state bdw_cstates[] = {
.
exit_latency
=
2
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -536,7 +536,7 @@ static struct cpuidle_state bdw_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -544,7 +544,7 @@ static struct cpuidle_state bdw_cstates[] = {
.
exit_latency
=
40
,
.
target_residency
=
100
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -552,7 +552,7 @@ static struct cpuidle_state bdw_cstates[] = {
.
exit_latency
=
133
,
.
target_residency
=
400
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7s"
,
.
desc
=
"MWAIT 0x32"
,
...
...
@@ -560,7 +560,7 @@ static struct cpuidle_state bdw_cstates[] = {
.
exit_latency
=
166
,
.
target_residency
=
500
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C8"
,
.
desc
=
"MWAIT 0x40"
,
...
...
@@ -568,7 +568,7 @@ static struct cpuidle_state bdw_cstates[] = {
.
exit_latency
=
300
,
.
target_residency
=
900
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C9"
,
.
desc
=
"MWAIT 0x50"
,
...
...
@@ -576,7 +576,7 @@ static struct cpuidle_state bdw_cstates[] = {
.
exit_latency
=
600
,
.
target_residency
=
1800
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C10"
,
.
desc
=
"MWAIT 0x60"
,
...
...
@@ -584,7 +584,7 @@ static struct cpuidle_state bdw_cstates[] = {
.
exit_latency
=
2600
,
.
target_residency
=
7700
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -597,7 +597,7 @@ static struct cpuidle_state skl_cstates[] = {
.
exit_latency
=
2
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -605,7 +605,7 @@ static struct cpuidle_state skl_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C3"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -613,7 +613,7 @@ static struct cpuidle_state skl_cstates[] = {
.
exit_latency
=
70
,
.
target_residency
=
100
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -621,7 +621,7 @@ static struct cpuidle_state skl_cstates[] = {
.
exit_latency
=
85
,
.
target_residency
=
200
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7s"
,
.
desc
=
"MWAIT 0x33"
,
...
...
@@ -629,7 +629,7 @@ static struct cpuidle_state skl_cstates[] = {
.
exit_latency
=
124
,
.
target_residency
=
800
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C8"
,
.
desc
=
"MWAIT 0x40"
,
...
...
@@ -637,7 +637,7 @@ static struct cpuidle_state skl_cstates[] = {
.
exit_latency
=
200
,
.
target_residency
=
800
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C9"
,
.
desc
=
"MWAIT 0x50"
,
...
...
@@ -645,7 +645,7 @@ static struct cpuidle_state skl_cstates[] = {
.
exit_latency
=
480
,
.
target_residency
=
5000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C10"
,
.
desc
=
"MWAIT 0x60"
,
...
...
@@ -653,7 +653,7 @@ static struct cpuidle_state skl_cstates[] = {
.
exit_latency
=
890
,
.
target_residency
=
5000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -666,7 +666,7 @@ static struct cpuidle_state skx_cstates[] = {
.
exit_latency
=
2
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -674,7 +674,7 @@ static struct cpuidle_state skx_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -682,7 +682,7 @@ static struct cpuidle_state skx_cstates[] = {
.
exit_latency
=
133
,
.
target_residency
=
600
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -695,7 +695,7 @@ static struct cpuidle_state atom_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C2"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -703,7 +703,7 @@ static struct cpuidle_state atom_cstates[] = {
.
exit_latency
=
20
,
.
target_residency
=
80
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C4"
,
.
desc
=
"MWAIT 0x30"
,
...
...
@@ -711,7 +711,7 @@ static struct cpuidle_state atom_cstates[] = {
.
exit_latency
=
100
,
.
target_residency
=
400
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x52"
,
...
...
@@ -719,7 +719,7 @@ static struct cpuidle_state atom_cstates[] = {
.
exit_latency
=
140
,
.
target_residency
=
560
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -731,7 +731,7 @@ static struct cpuidle_state tangier_cstates[] = {
.
exit_latency
=
1
,
.
target_residency
=
4
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C4"
,
.
desc
=
"MWAIT 0x30"
,
...
...
@@ -739,7 +739,7 @@ static struct cpuidle_state tangier_cstates[] = {
.
exit_latency
=
100
,
.
target_residency
=
400
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x52"
,
...
...
@@ -747,7 +747,7 @@ static struct cpuidle_state tangier_cstates[] = {
.
exit_latency
=
140
,
.
target_residency
=
560
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7"
,
.
desc
=
"MWAIT 0x60"
,
...
...
@@ -755,7 +755,7 @@ static struct cpuidle_state tangier_cstates[] = {
.
exit_latency
=
1200
,
.
target_residency
=
4000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C9"
,
.
desc
=
"MWAIT 0x64"
,
...
...
@@ -763,7 +763,7 @@ static struct cpuidle_state tangier_cstates[] = {
.
exit_latency
=
10000
,
.
target_residency
=
20000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -775,7 +775,7 @@ static struct cpuidle_state avn_cstates[] = {
.
exit_latency
=
2
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x51"
,
...
...
@@ -783,7 +783,7 @@ static struct cpuidle_state avn_cstates[] = {
.
exit_latency
=
15
,
.
target_residency
=
45
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -795,7 +795,7 @@ static struct cpuidle_state knl_cstates[] = {
.
exit_latency
=
1
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
},
.
enter_
s2idle
=
intel_idle_s2idl
e
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x10"
,
...
...
@@ -803,7 +803,7 @@ static struct cpuidle_state knl_cstates[] = {
.
exit_latency
=
120
,
.
target_residency
=
500
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
},
.
enter_
s2idle
=
intel_idle_s2idl
e
},
{
.
enter
=
NULL
}
};
...
...
@@ -816,7 +816,7 @@ static struct cpuidle_state bxt_cstates[] = {
.
exit_latency
=
2
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -824,7 +824,7 @@ static struct cpuidle_state bxt_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -832,7 +832,7 @@ static struct cpuidle_state bxt_cstates[] = {
.
exit_latency
=
133
,
.
target_residency
=
133
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C7s"
,
.
desc
=
"MWAIT 0x31"
,
...
...
@@ -840,7 +840,7 @@ static struct cpuidle_state bxt_cstates[] = {
.
exit_latency
=
155
,
.
target_residency
=
155
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C8"
,
.
desc
=
"MWAIT 0x40"
,
...
...
@@ -848,7 +848,7 @@ static struct cpuidle_state bxt_cstates[] = {
.
exit_latency
=
1000
,
.
target_residency
=
1000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C9"
,
.
desc
=
"MWAIT 0x50"
,
...
...
@@ -856,7 +856,7 @@ static struct cpuidle_state bxt_cstates[] = {
.
exit_latency
=
2000
,
.
target_residency
=
2000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C10"
,
.
desc
=
"MWAIT 0x60"
,
...
...
@@ -864,7 +864,7 @@ static struct cpuidle_state bxt_cstates[] = {
.
exit_latency
=
10000
,
.
target_residency
=
10000
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -877,7 +877,7 @@ static struct cpuidle_state dnv_cstates[] = {
.
exit_latency
=
2
,
.
target_residency
=
2
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C1E"
,
.
desc
=
"MWAIT 0x01"
,
...
...
@@ -885,7 +885,7 @@ static struct cpuidle_state dnv_cstates[] = {
.
exit_latency
=
10
,
.
target_residency
=
20
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
name
=
"C6"
,
.
desc
=
"MWAIT 0x20"
,
...
...
@@ -893,7 +893,7 @@ static struct cpuidle_state dnv_cstates[] = {
.
exit_latency
=
50
,
.
target_residency
=
500
,
.
enter
=
&
intel_idle
,
.
enter_
freeze
=
intel_idle_freez
e
,
},
.
enter_
s2idle
=
intel_idle_s2idl
e
,
},
{
.
enter
=
NULL
}
};
...
...
@@ -936,12 +936,12 @@ static __cpuidle int intel_idle(struct cpuidle_device *dev,
}
/**
* intel_idle_
freez
e - simplified "enter" callback routine for suspend-to-idle
* intel_idle_
s2idl
e - simplified "enter" callback routine for suspend-to-idle
* @dev: cpuidle_device
* @drv: cpuidle driver
* @index: state index
*/
static
void
intel_idle_
freez
e
(
struct
cpuidle_device
*
dev
,
static
void
intel_idle_
s2idl
e
(
struct
cpuidle_device
*
dev
,
struct
cpuidle_driver
*
drv
,
int
index
)
{
unsigned
long
ecx
=
1
;
/* break on interrupt flag */
...
...
@@ -1337,7 +1337,7 @@ static void __init intel_idle_cpuidle_driver_init(void)
int
num_substates
,
mwait_hint
,
mwait_cstate
;
if
((
cpuidle_state_table
[
cstate
].
enter
==
NULL
)
&&
(
cpuidle_state_table
[
cstate
].
enter_
freez
e
==
NULL
))
(
cpuidle_state_table
[
cstate
].
enter_
s2idl
e
==
NULL
))
break
;
if
(
cstate
+
1
>
max_cstate
)
{
...
...
drivers/platform/x86/intel-hid.c
View file @
cba630b6
...
...
@@ -203,15 +203,26 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
acpi_status
status
;
if
(
priv
->
wakeup_mode
)
{
/*
* Needed for wakeup from suspend-to-idle to work on some
* platforms that don't expose the 5-button array, but still
* send notifies with the power button event code to this
* device object on power button actions while suspended.
*/
if
(
event
==
0xce
)
goto
wakeup
;
/* Wake up on 5-button array events only. */
if
(
event
==
0xc0
||
!
priv
->
array
)
return
;
if
(
sparse_keymap_entry_from_scancode
(
priv
->
array
,
event
))
pm_wakeup_hard_event
(
&
device
->
dev
);
else
if
(
!
sparse_keymap_entry_from_scancode
(
priv
->
array
,
event
))
{
dev_info
(
&
device
->
dev
,
"unknown event 0x%x
\n
"
,
event
);
return
;
}
wakeup:
pm_wakeup_hard_event
(
&
device
->
dev
);
return
;
}
...
...
drivers/regulator/of_regulator.c
View file @
cba630b6
...
...
@@ -150,7 +150,7 @@ static void of_get_regulation_constraints(struct device_node *np,
suspend_state
=
&
constraints
->
state_disk
;
break
;
case
PM_SUSPEND_ON
:
case
PM_SUSPEND_
FREEZ
E
:
case
PM_SUSPEND_
TO_IDL
E
:
case
PM_SUSPEND_STANDBY
:
default:
continue
;
...
...
include/linux/cpuidle.h
View file @
cba630b6
...
...
@@ -52,11 +52,11 @@ struct cpuidle_state {
int
(
*
enter_dead
)
(
struct
cpuidle_device
*
dev
,
int
index
);
/*
* CPUs execute ->enter_
freez
e with the local tick or entire timekeeping
* CPUs execute ->enter_
s2idl
e with the local tick or entire timekeeping
* suspended, so it must not re-enable interrupts at any point (even
* temporarily) or attempt to change states of clock event devices.
*/
void
(
*
enter_
freez
e
)
(
struct
cpuidle_device
*
dev
,
void
(
*
enter_
s2idl
e
)
(
struct
cpuidle_device
*
dev
,
struct
cpuidle_driver
*
drv
,
int
index
);
};
...
...
@@ -197,14 +197,14 @@ static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL; }
#ifdef CONFIG_CPU_IDLE
extern
int
cpuidle_find_deepest_state
(
struct
cpuidle_driver
*
drv
,
struct
cpuidle_device
*
dev
);
extern
int
cpuidle_enter_
freez
e
(
struct
cpuidle_driver
*
drv
,
extern
int
cpuidle_enter_
s2idl
e
(
struct
cpuidle_driver
*
drv
,
struct
cpuidle_device
*
dev
);
extern
void
cpuidle_use_deepest_state
(
bool
enable
);
#else
static
inline
int
cpuidle_find_deepest_state
(
struct
cpuidle_driver
*
drv
,
struct
cpuidle_device
*
dev
)
{
return
-
ENODEV
;
}
static
inline
int
cpuidle_enter_
freez
e
(
struct
cpuidle_driver
*
drv
,
static
inline
int
cpuidle_enter_
s2idl
e
(
struct
cpuidle_driver
*
drv
,
struct
cpuidle_device
*
dev
)
{
return
-
ENODEV
;
}
static
inline
void
cpuidle_use_deepest_state
(
bool
enable
)
...
...
include/linux/pm.h
View file @
cba630b6
...
...
@@ -689,6 +689,8 @@ struct dev_pm_domain {
extern
void
device_pm_lock
(
void
);
extern
void
dpm_resume_start
(
pm_message_t
state
);
extern
void
dpm_resume_end
(
pm_message_t
state
);
extern
void
dpm_noirq_resume_devices
(
pm_message_t
state
);
extern
void
dpm_noirq_end
(
void
);
extern
void
dpm_resume_noirq
(
pm_message_t
state
);
extern
void
dpm_resume_early
(
pm_message_t
state
);
extern
void
dpm_resume
(
pm_message_t
state
);
...
...
@@ -697,6 +699,8 @@ extern void dpm_complete(pm_message_t state);
extern
void
device_pm_unlock
(
void
);
extern
int
dpm_suspend_end
(
pm_message_t
state
);
extern
int
dpm_suspend_start
(
pm_message_t
state
);
extern
void
dpm_noirq_begin
(
void
);
extern
int
dpm_noirq_suspend_devices
(
pm_message_t
state
);
extern
int
dpm_suspend_noirq
(
pm_message_t
state
);
extern
int
dpm_suspend_late
(
pm_message_t
state
);
extern
int
dpm_suspend
(
pm_message_t
state
);
...
...
include/linux/suspend.h
View file @
cba630b6
...
...
@@ -33,10 +33,10 @@ static inline void pm_restore_console(void)
typedef
int
__bitwise
suspend_state_t
;
#define PM_SUSPEND_ON ((__force suspend_state_t) 0)
#define PM_SUSPEND_
FREEZ
E ((__force suspend_state_t) 1)
#define PM_SUSPEND_
TO_IDL
E ((__force suspend_state_t) 1)
#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 2)
#define PM_SUSPEND_MEM ((__force suspend_state_t) 3)
#define PM_SUSPEND_MIN PM_SUSPEND_
FREEZ
E
#define PM_SUSPEND_MIN PM_SUSPEND_
TO_IDL
E
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)
enum
suspend_stat_step
{
...
...
@@ -186,7 +186,7 @@ struct platform_suspend_ops {
void
(
*
recover
)(
void
);
};
struct
platform_
freez
e_ops
{
struct
platform_
s2idl
e_ops
{
int
(
*
begin
)(
void
);
int
(
*
prepare
)(
void
);
void
(
*
wake
)(
void
);
...
...
@@ -196,6 +196,9 @@ struct platform_freeze_ops {
};
#ifdef CONFIG_SUSPEND
extern
suspend_state_t
mem_sleep_current
;
extern
suspend_state_t
mem_sleep_default
;
/**
* suspend_set_ops - set platform dependent suspend operations
* @ops: The new suspend operations to set.
...
...
@@ -234,22 +237,22 @@ static inline bool pm_resume_via_firmware(void)
}
/* Suspend-to-idle state machnine. */
enum
freeze_state
{
FREEZ
E_STATE_NONE
,
/* Not suspended/suspending. */
FREEZ
E_STATE_ENTER
,
/* Enter suspend-to-idle. */
FREEZ
E_STATE_WAKE
,
/* Wake up from suspend-to-idle. */
enum
s2idle_states
{
S2IDL
E_STATE_NONE
,
/* Not suspended/suspending. */
S2IDL
E_STATE_ENTER
,
/* Enter suspend-to-idle. */
S2IDL
E_STATE_WAKE
,
/* Wake up from suspend-to-idle. */
};
extern
enum
freeze_state
__read_mostly
suspend_freez
e_state
;
extern
enum
s2idle_states
__read_mostly
s2idl
e_state
;
static
inline
bool
idle_should_
freez
e
(
void
)
static
inline
bool
idle_should_
enter_s2idl
e
(
void
)
{
return
unlikely
(
s
uspend_freeze_state
==
FREEZ
E_STATE_ENTER
);
return
unlikely
(
s
2idle_state
==
S2IDL
E_STATE_ENTER
);
}
extern
void
__init
pm_states_init
(
void
);
extern
void
freeze_set_ops
(
const
struct
platform_freez
e_ops
*
ops
);
extern
void
freez
e_wake
(
void
);
extern
void
s2idle_set_ops
(
const
struct
platform_s2idl
e_ops
*
ops
);
extern
void
s2idl
e_wake
(
void
);
/**
* arch_suspend_disable_irqs - disable IRQs for suspend
...
...
@@ -281,10 +284,10 @@ static inline bool pm_resume_via_firmware(void) { return false; }
static
inline
void
suspend_set_ops
(
const
struct
platform_suspend_ops
*
ops
)
{}
static
inline
int
pm_suspend
(
suspend_state_t
state
)
{
return
-
ENOSYS
;
}
static
inline
bool
idle_should_
freez
e
(
void
)
{
return
false
;
}
static
inline
bool
idle_should_
enter_s2idl
e
(
void
)
{
return
false
;
}
static
inline
void
__init
pm_states_init
(
void
)
{}
static
inline
void
freeze_set_ops
(
const
struct
platform_freez
e_ops
*
ops
)
{}
static
inline
void
freez
e_wake
(
void
)
{}
static
inline
void
s2idle_set_ops
(
const
struct
platform_s2idl
e_ops
*
ops
)
{}
static
inline
void
s2idl
e_wake
(
void
)
{}
#endif
/* !CONFIG_SUSPEND */
/* struct pbe is used for creating lists of pages that should be restored
...
...
@@ -427,6 +430,7 @@ extern int unregister_pm_notifier(struct notifier_block *nb);
/* drivers/base/power/wakeup.c */
extern
bool
events_check_enabled
;
extern
unsigned
int
pm_wakeup_irq
;
extern
suspend_state_t
pm_suspend_target_state
;
extern
bool
pm_wakeup_pending
(
void
);
extern
void
pm_system_wakeup
(
void
);
...
...
@@ -491,10 +495,24 @@ static inline void unlock_system_sleep(void) {}
#ifdef CONFIG_PM_SLEEP_DEBUG
extern
bool
pm_print_times_enabled
;
extern
bool
pm_debug_messages_on
;
extern
__printf
(
2
,
3
)
void
__pm_pr_dbg
(
bool
defer
,
const
char
*
fmt
,
...);
#else
#define pm_print_times_enabled (false)
#define pm_debug_messages_on (false)
#include <linux/printk.h>
#define __pm_pr_dbg(defer, fmt, ...) \
no_printk(KERN_DEBUG fmt, ##__VA_ARGS__)
#endif
#define pm_pr_dbg(fmt, ...) \
__pm_pr_dbg(false, fmt, ##__VA_ARGS__)
#define pm_deferred_pr_dbg(fmt, ...) \
__pm_pr_dbg(true, fmt, ##__VA_ARGS__)
#ifdef CONFIG_PM_AUTOSLEEP
/* kernel/power/autosleep.c */
...
...
kernel/power/hibernate.c
View file @
cba630b6
...
...
@@ -651,7 +651,7 @@ static int load_image_and_restore(void)
int
error
;
unsigned
int
flags
;
p
r_debu
g
(
"Loading hibernation image.
\n
"
);
p
m_pr_db
g
(
"Loading hibernation image.
\n
"
);
lock_device_hotplug
();
error
=
create_basic_memory_bitmaps
();
...
...
@@ -681,7 +681,7 @@ int hibernate(void)
bool
snapshot_test
=
false
;
if
(
!
hibernation_available
())
{
p
r_debu
g
(
"Hibernation not available.
\n
"
);
p
m_pr_db
g
(
"Hibernation not available.
\n
"
);
return
-
EPERM
;
}
...
...
@@ -692,6 +692,7 @@ int hibernate(void)
goto
Unlock
;
}
pr_info
(
"hibernation entry
\n
"
);
pm_prepare_console
();
error
=
__pm_notifier_call_chain
(
PM_HIBERNATION_PREPARE
,
-
1
,
&
nr_calls
);
if
(
error
)
{
...
...
@@ -727,7 +728,7 @@ int hibernate(void)
else
flags
|=
SF_CRC32_MODE
;
p
r_debu
g
(
"Writing image.
\n
"
);
p
m_pr_db
g
(
"Writing image.
\n
"
);
error
=
swsusp_write
(
flags
);
swsusp_free
();
if
(
!
error
)
{
...
...
@@ -739,7 +740,7 @@ int hibernate(void)
in_suspend
=
0
;
pm_restore_gfp_mask
();
}
else
{
p
r_debu
g
(
"Image restored successfully.
\n
"
);
p
m_pr_db
g
(
"Image restored successfully.
\n
"
);
}
Free_bitmaps:
...
...
@@ -747,7 +748,7 @@ int hibernate(void)
Thaw:
unlock_device_hotplug
();
if
(
snapshot_test
)
{
p
r_debu
g
(
"Checking hibernation image
\n
"
);
p
m_pr_db
g
(
"Checking hibernation image
\n
"
);
error
=
swsusp_check
();
if
(
!
error
)
error
=
load_image_and_restore
();
...
...
@@ -762,6 +763,8 @@ int hibernate(void)
atomic_inc
(
&
snapshot_device_available
);
Unlock:
unlock_system_sleep
();
pr_info
(
"hibernation exit
\n
"
);
return
error
;
}
...
...
@@ -811,7 +814,7 @@ static int software_resume(void)
goto
Unlock
;
}
p
r_debu
g
(
"Checking hibernation image partition %s
\n
"
,
resume_file
);
p
m_pr_db
g
(
"Checking hibernation image partition %s
\n
"
,
resume_file
);
if
(
resume_delay
)
{
pr_info
(
"Waiting %dsec before reading resume device ...
\n
"
,
...
...
@@ -853,10 +856,10 @@ static int software_resume(void)
}
Check_image:
p
r_debu
g
(
"Hibernation image partition %d:%d present
\n
"
,
p
m_pr_db
g
(
"Hibernation image partition %d:%d present
\n
"
,
MAJOR
(
swsusp_resume_device
),
MINOR
(
swsusp_resume_device
));
p
r_debu
g
(
"Looking for hibernation image.
\n
"
);
p
m_pr_db
g
(
"Looking for hibernation image.
\n
"
);
error
=
swsusp_check
();
if
(
error
)
goto
Unlock
;
...
...
@@ -868,6 +871,7 @@ static int software_resume(void)
goto
Unlock
;
}
pr_info
(
"resume from hibernation
\n
"
);
pm_prepare_console
();
error
=
__pm_notifier_call_chain
(
PM_RESTORE_PREPARE
,
-
1
,
&
nr_calls
);
if
(
error
)
{
...
...
@@ -875,7 +879,7 @@ static int software_resume(void)
goto
Close_Finish
;
}
p
r_debu
g
(
"Preparing processes for restore.
\n
"
);
p
m_pr_db
g
(
"Preparing processes for restore.
\n
"
);
error
=
freeze_processes
();
if
(
error
)
goto
Close_Finish
;
...
...
@@ -884,11 +888,12 @@ static int software_resume(void)
Finish:
__pm_notifier_call_chain
(
PM_POST_RESTORE
,
nr_calls
,
NULL
);
pm_restore_console
();
pr_info
(
"resume from hibernation failed (%d)
\n
"
,
error
);
atomic_inc
(
&
snapshot_device_available
);
/* For success case, the suspend path will release the lock */
Unlock:
mutex_unlock
(
&
pm_mutex
);
p
r_debu
g
(
"Hibernation image not present or could not be loaded.
\n
"
);
p
m_pr_db
g
(
"Hibernation image not present or could not be loaded.
\n
"
);
return
error
;
Close_Finish:
swsusp_close
(
FMODE_READ
);
...
...
@@ -1012,8 +1017,8 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
error
=
-
EINVAL
;
if
(
!
error
)
p
r_debu
g
(
"Hibernation mode set to '%s'
\n
"
,
hibernation_modes
[
mode
]);
p
m_pr_db
g
(
"Hibernation mode set to '%s'
\n
"
,
hibernation_modes
[
mode
]);
unlock_system_sleep
();
return
error
?
error
:
n
;
}
...
...
kernel/power/main.c
View file @
cba630b6
...
...
@@ -150,7 +150,7 @@ static ssize_t mem_sleep_store(struct kobject *kobj, struct kobj_attribute *attr
power_attr
(
mem_sleep
);
#endif
/* CONFIG_SUSPEND */
#ifdef CONFIG_PM_DEBUG
#ifdef CONFIG_PM_
SLEEP_
DEBUG
int
pm_test_level
=
TEST_NONE
;
static
const
char
*
const
pm_tests
[
__TEST_AFTER_LAST
]
=
{
...
...
@@ -211,7 +211,7 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
}
power_attr
(
pm_test
);
#endif
/* CONFIG_PM_DEBUG */
#endif
/* CONFIG_PM_
SLEEP_
DEBUG */
#ifdef CONFIG_DEBUG_FS
static
char
*
suspend_step_name
(
enum
suspend_stat_step
step
)
...
...
@@ -361,6 +361,61 @@ static ssize_t pm_wakeup_irq_show(struct kobject *kobj,
power_attr_ro
(
pm_wakeup_irq
);
bool
pm_debug_messages_on
__read_mostly
;
static
ssize_t
pm_debug_messages_show
(
struct
kobject
*
kobj
,
struct
kobj_attribute
*
attr
,
char
*
buf
)
{
return
sprintf
(
buf
,
"%d
\n
"
,
pm_debug_messages_on
);
}
static
ssize_t
pm_debug_messages_store
(
struct
kobject
*
kobj
,
struct
kobj_attribute
*
attr
,
const
char
*
buf
,
size_t
n
)
{
unsigned
long
val
;
if
(
kstrtoul
(
buf
,
10
,
&
val
))
return
-
EINVAL
;
if
(
val
>
1
)
return
-
EINVAL
;
pm_debug_messages_on
=
!!
val
;
return
n
;
}
power_attr
(
pm_debug_messages
);
/**
* __pm_pr_dbg - Print a suspend debug message to the kernel log.
* @defer: Whether or not to use printk_deferred() to print the message.
* @fmt: Message format.
*
* The message will be emitted if enabled through the pm_debug_messages
* sysfs attribute.
*/
void
__pm_pr_dbg
(
bool
defer
,
const
char
*
fmt
,
...)
{
struct
va_format
vaf
;
va_list
args
;
if
(
!
pm_debug_messages_on
)
return
;
va_start
(
args
,
fmt
);
vaf
.
fmt
=
fmt
;
vaf
.
va
=
&
args
;
if
(
defer
)
printk_deferred
(
KERN_DEBUG
"PM: %pV"
,
&
vaf
);
else
printk
(
KERN_DEBUG
"PM: %pV"
,
&
vaf
);
va_end
(
args
);
}
#else
/* !CONFIG_PM_SLEEP_DEBUG */
static
inline
void
pm_print_times_init
(
void
)
{}
#endif
/* CONFIG_PM_SLEEP_DEBUG */
...
...
@@ -691,12 +746,11 @@ static struct attribute * g[] = {
&
wake_lock_attr
.
attr
,
&
wake_unlock_attr
.
attr
,
#endif
#ifdef CONFIG_PM_DEBUG
&
pm_test_attr
.
attr
,
#endif
#ifdef CONFIG_PM_SLEEP_DEBUG
&
pm_test_attr
.
attr
,
&
pm_print_times_attr
.
attr
,
&
pm_wakeup_irq_attr
.
attr
,
&
pm_debug_messages_attr
.
attr
,
#endif
#endif
#ifdef CONFIG_FREEZER
...
...
kernel/power/power.h
View file @
cba630b6
...
...
@@ -192,7 +192,6 @@ extern void swsusp_show_speed(ktime_t, ktime_t, unsigned int, char *);
extern
const
char
*
const
pm_labels
[];
extern
const
char
*
pm_states
[];
extern
const
char
*
mem_sleep_states
[];
extern
suspend_state_t
mem_sleep_current
;
extern
int
suspend_devices_and_enter
(
suspend_state_t
state
);
#else
/* !CONFIG_SUSPEND */
...
...
@@ -245,7 +244,11 @@ enum {
#define TEST_FIRST TEST_NONE
#define TEST_MAX (__TEST_AFTER_LAST - 1)
#ifdef CONFIG_PM_SLEEP_DEBUG
extern
int
pm_test_level
;
#else
#define pm_test_level (TEST_NONE)
#endif
#ifdef CONFIG_SUSPEND_FREEZER
static
inline
int
suspend_freeze_processes
(
void
)
...
...
kernel/power/suspend.c
View file @
cba630b6
...
...
@@ -8,6 +8,8 @@
* This file is released under the GPLv2.
*/
#define pr_fmt(fmt) "PM: " fmt
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/errno.h>
...
...
@@ -33,53 +35,55 @@
#include "power.h"
const
char
*
const
pm_labels
[]
=
{
[
PM_SUSPEND_
FREEZ
E
]
=
"freeze"
,
[
PM_SUSPEND_
TO_IDL
E
]
=
"freeze"
,
[
PM_SUSPEND_STANDBY
]
=
"standby"
,
[
PM_SUSPEND_MEM
]
=
"mem"
,
};
const
char
*
pm_states
[
PM_SUSPEND_MAX
];
static
const
char
*
const
mem_sleep_labels
[]
=
{
[
PM_SUSPEND_
FREEZ
E
]
=
"s2idle"
,
[
PM_SUSPEND_
TO_IDL
E
]
=
"s2idle"
,
[
PM_SUSPEND_STANDBY
]
=
"shallow"
,
[
PM_SUSPEND_MEM
]
=
"deep"
,
};
const
char
*
mem_sleep_states
[
PM_SUSPEND_MAX
];
suspend_state_t
mem_sleep_current
=
PM_SUSPEND_FREEZE
;
static
suspend_state_t
mem_sleep_default
=
PM_SUSPEND_MEM
;
suspend_state_t
mem_sleep_current
=
PM_SUSPEND_TO_IDLE
;
suspend_state_t
mem_sleep_default
=
PM_SUSPEND_MAX
;
suspend_state_t
pm_suspend_target_state
;
EXPORT_SYMBOL_GPL
(
pm_suspend_target_state
);
unsigned
int
pm_suspend_global_flags
;
EXPORT_SYMBOL_GPL
(
pm_suspend_global_flags
);
static
const
struct
platform_suspend_ops
*
suspend_ops
;
static
const
struct
platform_
freeze_ops
*
freez
e_ops
;
static
DECLARE_WAIT_QUEUE_HEAD
(
s
uspend_freez
e_wait_head
);
static
const
struct
platform_
s2idle_ops
*
s2idl
e_ops
;
static
DECLARE_WAIT_QUEUE_HEAD
(
s
2idl
e_wait_head
);
enum
freeze_state
__read_mostly
suspend_freez
e_state
;
static
DEFINE_SPINLOCK
(
s
uspend_freez
e_lock
);
enum
s2idle_states
__read_mostly
s2idl
e_state
;
static
DEFINE_SPINLOCK
(
s
2idl
e_lock
);
void
freeze_set_ops
(
const
struct
platform_freez
e_ops
*
ops
)
void
s2idle_set_ops
(
const
struct
platform_s2idl
e_ops
*
ops
)
{
lock_system_sleep
();
freez
e_ops
=
ops
;
s2idl
e_ops
=
ops
;
unlock_system_sleep
();
}
static
void
freez
e_begin
(
void
)
static
void
s2idl
e_begin
(
void
)
{
s
uspend_freeze_state
=
FREEZ
E_STATE_NONE
;
s
2idle_state
=
S2IDL
E_STATE_NONE
;
}
static
void
freez
e_enter
(
void
)
static
void
s2idl
e_enter
(
void
)
{
trace_suspend_resume
(
TPS
(
"machine_suspend"
),
PM_SUSPEND_
FREEZ
E
,
true
);
trace_suspend_resume
(
TPS
(
"machine_suspend"
),
PM_SUSPEND_
TO_IDL
E
,
true
);
spin_lock_irq
(
&
s
uspend_freez
e_lock
);
spin_lock_irq
(
&
s
2idl
e_lock
);
if
(
pm_wakeup_pending
())
goto
out
;
s
uspend_freeze_state
=
FREEZ
E_STATE_ENTER
;
spin_unlock_irq
(
&
s
uspend_freez
e_lock
);
s
2idle_state
=
S2IDL
E_STATE_ENTER
;
spin_unlock_irq
(
&
s
2idl
e_lock
);
get_online_cpus
();
cpuidle_resume
();
...
...
@@ -87,56 +91,75 @@ static void freeze_enter(void)
/* Push all the CPUs into the idle loop. */
wake_up_all_idle_cpus
();
/* Make the current CPU wait so it can enter the idle loop too. */
wait_event
(
s
uspend_freez
e_wait_head
,
s
uspend_freeze_state
==
FREEZ
E_STATE_WAKE
);
wait_event
(
s
2idl
e_wait_head
,
s
2idle_state
==
S2IDL
E_STATE_WAKE
);
cpuidle_pause
();
put_online_cpus
();
spin_lock_irq
(
&
s
uspend_freez
e_lock
);
spin_lock_irq
(
&
s
2idl
e_lock
);
out:
s
uspend_freeze_state
=
FREEZ
E_STATE_NONE
;
spin_unlock_irq
(
&
s
uspend_freez
e_lock
);
s
2idle_state
=
S2IDL
E_STATE_NONE
;
spin_unlock_irq
(
&
s
2idl
e_lock
);
trace_suspend_resume
(
TPS
(
"machine_suspend"
),
PM_SUSPEND_
FREEZ
E
,
false
);
trace_suspend_resume
(
TPS
(
"machine_suspend"
),
PM_SUSPEND_
TO_IDL
E
,
false
);
}
static
void
s2idle_loop
(
void
)
{
pr_debug
(
"PM: suspend-to-idle
\n
"
);
pm_pr_dbg
(
"suspend-to-idle
\n
"
);
for
(;;)
{
int
error
;
dpm_noirq_begin
();
/*
* Suspend-to-idle equals
* frozen processes + suspended devices + idle processors.
* Thus s2idle_enter() should be called right after
* all devices have been suspended.
*/
error
=
dpm_noirq_suspend_devices
(
PMSG_SUSPEND
);
if
(
!
error
)
s2idle_enter
();
dpm_noirq_resume_devices
(
PMSG_RESUME
);
if
(
error
&&
(
error
!=
-
EBUSY
||
!
pm_wakeup_pending
()))
{
dpm_noirq_end
();
break
;
}
do
{
freeze_enter
();
if
(
s2idle_ops
&&
s2idle_ops
->
wake
)
s2idle_ops
->
wake
();
if
(
freeze_ops
&&
freeze_ops
->
wake
)
freeze_ops
->
wake
();
dpm_noirq_end
();
dpm_resume_noirq
(
PMSG_RESUME
);
if
(
freeze_ops
&&
freeze_ops
->
sync
)
freeze_ops
->
sync
();
if
(
s2idle_ops
&&
s2idle_ops
->
sync
)
s2idle_ops
->
sync
();
if
(
pm_wakeup_pending
())
break
;
pm_wakeup_clear
(
false
);
}
while
(
!
dpm_suspend_noirq
(
PMSG_SUSPEND
));
}
p
r_debug
(
"PM:
resume from suspend-to-idle
\n
"
);
p
m_pr_dbg
(
"
resume from suspend-to-idle
\n
"
);
}
void
freez
e_wake
(
void
)
void
s2idl
e_wake
(
void
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
s
uspend_freez
e_lock
,
flags
);
if
(
s
uspend_freeze_state
>
FREEZ
E_STATE_NONE
)
{
s
uspend_freeze_state
=
FREEZ
E_STATE_WAKE
;
wake_up
(
&
s
uspend_freez
e_wait_head
);
spin_lock_irqsave
(
&
s
2idl
e_lock
,
flags
);
if
(
s
2idle_state
>
S2IDL
E_STATE_NONE
)
{
s
2idle_state
=
S2IDL
E_STATE_WAKE
;
wake_up
(
&
s
2idl
e_wait_head
);
}
spin_unlock_irqrestore
(
&
s
uspend_freez
e_lock
,
flags
);
spin_unlock_irqrestore
(
&
s
2idl
e_lock
,
flags
);
}
EXPORT_SYMBOL_GPL
(
freez
e_wake
);
EXPORT_SYMBOL_GPL
(
s2idl
e_wake
);
static
bool
valid_state
(
suspend_state_t
state
)
{
...
...
@@ -152,19 +175,19 @@ void __init pm_states_init(void)
{
/* "mem" and "freeze" are always present in /sys/power/state. */
pm_states
[
PM_SUSPEND_MEM
]
=
pm_labels
[
PM_SUSPEND_MEM
];
pm_states
[
PM_SUSPEND_
FREEZE
]
=
pm_labels
[
PM_SUSPEND_FREEZ
E
];
pm_states
[
PM_SUSPEND_
TO_IDLE
]
=
pm_labels
[
PM_SUSPEND_TO_IDL
E
];
/*
* Suspend-to-idle should be supported even without any suspend_ops,
* initialize mem_sleep_states[] accordingly here.
*/
mem_sleep_states
[
PM_SUSPEND_
FREEZE
]
=
mem_sleep_labels
[
PM_SUSPEND_FREEZ
E
];
mem_sleep_states
[
PM_SUSPEND_
TO_IDLE
]
=
mem_sleep_labels
[
PM_SUSPEND_TO_IDL
E
];
}
static
int
__init
mem_sleep_default_setup
(
char
*
str
)
{
suspend_state_t
state
;
for
(
state
=
PM_SUSPEND_
FREEZ
E
;
state
<=
PM_SUSPEND_MEM
;
state
++
)
for
(
state
=
PM_SUSPEND_
TO_IDL
E
;
state
<=
PM_SUSPEND_MEM
;
state
++
)
if
(
mem_sleep_labels
[
state
]
&&
!
strcmp
(
str
,
mem_sleep_labels
[
state
]))
{
mem_sleep_default
=
state
;
...
...
@@ -193,7 +216,7 @@ void suspend_set_ops(const struct platform_suspend_ops *ops)
}
if
(
valid_state
(
PM_SUSPEND_MEM
))
{
mem_sleep_states
[
PM_SUSPEND_MEM
]
=
mem_sleep_labels
[
PM_SUSPEND_MEM
];
if
(
mem_sleep_default
=
=
PM_SUSPEND_MEM
)
if
(
mem_sleep_default
>
=
PM_SUSPEND_MEM
)
mem_sleep_current
=
PM_SUSPEND_MEM
;
}
...
...
@@ -216,49 +239,49 @@ EXPORT_SYMBOL_GPL(suspend_valid_only_mem);
static
bool
sleep_state_supported
(
suspend_state_t
state
)
{
return
state
==
PM_SUSPEND_
FREEZ
E
||
(
suspend_ops
&&
suspend_ops
->
enter
);
return
state
==
PM_SUSPEND_
TO_IDL
E
||
(
suspend_ops
&&
suspend_ops
->
enter
);
}
static
int
platform_suspend_prepare
(
suspend_state_t
state
)
{
return
state
!=
PM_SUSPEND_
FREEZ
E
&&
suspend_ops
->
prepare
?
return
state
!=
PM_SUSPEND_
TO_IDL
E
&&
suspend_ops
->
prepare
?
suspend_ops
->
prepare
()
:
0
;
}
static
int
platform_suspend_prepare_late
(
suspend_state_t
state
)
{
return
state
==
PM_SUSPEND_
FREEZE
&&
freeze_ops
&&
freez
e_ops
->
prepare
?
freez
e_ops
->
prepare
()
:
0
;
return
state
==
PM_SUSPEND_
TO_IDLE
&&
s2idle_ops
&&
s2idl
e_ops
->
prepare
?
s2idl
e_ops
->
prepare
()
:
0
;
}
static
int
platform_suspend_prepare_noirq
(
suspend_state_t
state
)
{
return
state
!=
PM_SUSPEND_
FREEZ
E
&&
suspend_ops
->
prepare_late
?
return
state
!=
PM_SUSPEND_
TO_IDL
E
&&
suspend_ops
->
prepare_late
?
suspend_ops
->
prepare_late
()
:
0
;
}
static
void
platform_resume_noirq
(
suspend_state_t
state
)
{
if
(
state
!=
PM_SUSPEND_
FREEZ
E
&&
suspend_ops
->
wake
)
if
(
state
!=
PM_SUSPEND_
TO_IDL
E
&&
suspend_ops
->
wake
)
suspend_ops
->
wake
();
}
static
void
platform_resume_early
(
suspend_state_t
state
)
{
if
(
state
==
PM_SUSPEND_
FREEZE
&&
freeze_ops
&&
freez
e_ops
->
restore
)
freez
e_ops
->
restore
();
if
(
state
==
PM_SUSPEND_
TO_IDLE
&&
s2idle_ops
&&
s2idl
e_ops
->
restore
)
s2idl
e_ops
->
restore
();
}
static
void
platform_resume_finish
(
suspend_state_t
state
)
{
if
(
state
!=
PM_SUSPEND_
FREEZ
E
&&
suspend_ops
->
finish
)
if
(
state
!=
PM_SUSPEND_
TO_IDL
E
&&
suspend_ops
->
finish
)
suspend_ops
->
finish
();
}
static
int
platform_suspend_begin
(
suspend_state_t
state
)
{
if
(
state
==
PM_SUSPEND_
FREEZE
&&
freeze_ops
&&
freez
e_ops
->
begin
)
return
freez
e_ops
->
begin
();
if
(
state
==
PM_SUSPEND_
TO_IDLE
&&
s2idle_ops
&&
s2idl
e_ops
->
begin
)
return
s2idl
e_ops
->
begin
();
else
if
(
suspend_ops
&&
suspend_ops
->
begin
)
return
suspend_ops
->
begin
(
state
);
else
...
...
@@ -267,21 +290,21 @@ static int platform_suspend_begin(suspend_state_t state)
static
void
platform_resume_end
(
suspend_state_t
state
)
{
if
(
state
==
PM_SUSPEND_
FREEZE
&&
freeze_ops
&&
freez
e_ops
->
end
)
freez
e_ops
->
end
();
if
(
state
==
PM_SUSPEND_
TO_IDLE
&&
s2idle_ops
&&
s2idl
e_ops
->
end
)
s2idl
e_ops
->
end
();
else
if
(
suspend_ops
&&
suspend_ops
->
end
)
suspend_ops
->
end
();
}
static
void
platform_recover
(
suspend_state_t
state
)
{
if
(
state
!=
PM_SUSPEND_
FREEZ
E
&&
suspend_ops
->
recover
)
if
(
state
!=
PM_SUSPEND_
TO_IDL
E
&&
suspend_ops
->
recover
)
suspend_ops
->
recover
();
}
static
bool
platform_suspend_again
(
suspend_state_t
state
)
{
return
state
!=
PM_SUSPEND_
FREEZ
E
&&
suspend_ops
->
suspend_again
?
return
state
!=
PM_SUSPEND_
TO_IDL
E
&&
suspend_ops
->
suspend_again
?
suspend_ops
->
suspend_again
()
:
false
;
}
...
...
@@ -370,16 +393,21 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
error
=
dpm_suspend_late
(
PMSG_SUSPEND
);
if
(
error
)
{
pr_err
(
"
PM:
late suspend of devices failed
\n
"
);
pr_err
(
"late suspend of devices failed
\n
"
);
goto
Platform_finish
;
}
error
=
platform_suspend_prepare_late
(
state
);
if
(
error
)
goto
Devices_early_resume
;
if
(
state
==
PM_SUSPEND_TO_IDLE
&&
pm_test_level
!=
TEST_PLATFORM
)
{
s2idle_loop
();
goto
Platform_early_resume
;
}
error
=
dpm_suspend_noirq
(
PMSG_SUSPEND
);
if
(
error
)
{
pr_err
(
"
PM:
noirq suspend of devices failed
\n
"
);
pr_err
(
"noirq suspend of devices failed
\n
"
);
goto
Platform_early_resume
;
}
error
=
platform_suspend_prepare_noirq
(
state
);
...
...
@@ -389,17 +417,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
if
(
suspend_test
(
TEST_PLATFORM
))
goto
Platform_wake
;
/*
* PM_SUSPEND_FREEZE equals
* frozen processes + suspended devices + idle processors.
* Thus we should invoke freeze_enter() soon after
* all the devices are suspended.
*/
if
(
state
==
PM_SUSPEND_FREEZE
)
{
s2idle_loop
();
goto
Platform_early_resume
;
}
error
=
disable_nonboot_cpus
();
if
(
error
||
suspend_test
(
TEST_CPUS
))
goto
Enable_cpus
;
...
...
@@ -456,6 +473,8 @@ int suspend_devices_and_enter(suspend_state_t state)
if
(
!
sleep_state_supported
(
state
))
return
-
ENOSYS
;
pm_suspend_target_state
=
state
;
error
=
platform_suspend_begin
(
state
);
if
(
error
)
goto
Close
;
...
...
@@ -464,7 +483,7 @@ int suspend_devices_and_enter(suspend_state_t state)
suspend_test_start
();
error
=
dpm_suspend_start
(
PMSG_SUSPEND
);
if
(
error
)
{
pr_err
(
"
PM:
Some devices failed to suspend, or early wake event detected
\n
"
);
pr_err
(
"Some devices failed to suspend, or early wake event detected
\n
"
);
goto
Recover_platform
;
}
suspend_test_finish
(
"suspend devices"
);
...
...
@@ -485,6 +504,7 @@ int suspend_devices_and_enter(suspend_state_t state)
Close:
platform_resume_end
(
state
);
pm_suspend_target_state
=
PM_SUSPEND_ON
;
return
error
;
Recover_platform:
...
...
@@ -518,10 +538,10 @@ static int enter_state(suspend_state_t state)
int
error
;
trace_suspend_resume
(
TPS
(
"suspend_enter"
),
state
,
true
);
if
(
state
==
PM_SUSPEND_
FREEZ
E
)
{
if
(
state
==
PM_SUSPEND_
TO_IDL
E
)
{
#ifdef CONFIG_PM_DEBUG
if
(
pm_test_level
!=
TEST_NONE
&&
pm_test_level
<=
TEST_CPUS
)
{
pr_warn
(
"
PM:
Unsupported test mode for suspend to idle, please choose none/freezer/devices/platform.
\n
"
);
pr_warn
(
"Unsupported test mode for suspend to idle, please choose none/freezer/devices/platform.
\n
"
);
return
-
EAGAIN
;
}
#endif
...
...
@@ -531,18 +551,18 @@ static int enter_state(suspend_state_t state)
if
(
!
mutex_trylock
(
&
pm_mutex
))
return
-
EBUSY
;
if
(
state
==
PM_SUSPEND_
FREEZ
E
)
freez
e_begin
();
if
(
state
==
PM_SUSPEND_
TO_IDL
E
)
s2idl
e_begin
();
#ifndef CONFIG_SUSPEND_SKIP_SYNC
trace_suspend_resume
(
TPS
(
"sync_filesystems"
),
0
,
true
);
pr_info
(
"
PM:
Syncing filesystems ... "
);
pr_info
(
"Syncing filesystems ... "
);
sys_sync
();
pr_cont
(
"done.
\n
"
);
trace_suspend_resume
(
TPS
(
"sync_filesystems"
),
0
,
false
);
#endif
p
r_debug
(
"PM: Preparing system for sleep (%s)
\n
"
,
pm_state
s
[
state
]);
p
m_pr_dbg
(
"Preparing system for sleep (%s)
\n
"
,
mem_sleep_label
s
[
state
]);
pm_suspend_clear_flags
();
error
=
suspend_prepare
(
state
);
if
(
error
)
...
...
@@ -552,13 +572,13 @@ static int enter_state(suspend_state_t state)
goto
Finish
;
trace_suspend_resume
(
TPS
(
"suspend_enter"
),
state
,
false
);
p
r_debug
(
"PM: Suspending system (%s)
\n
"
,
pm_state
s
[
state
]);
p
m_pr_dbg
(
"Suspending system (%s)
\n
"
,
mem_sleep_label
s
[
state
]);
pm_restrict_gfp_mask
();
error
=
suspend_devices_and_enter
(
state
);
pm_restore_gfp_mask
();
Finish:
p
r_debug
(
"PM:
Finishing wakeup.
\n
"
);
p
m_pr_dbg
(
"
Finishing wakeup.
\n
"
);
suspend_finish
();
Unlock:
mutex_unlock
(
&
pm_mutex
);
...
...
@@ -579,6 +599,7 @@ int pm_suspend(suspend_state_t state)
if
(
state
<=
PM_SUSPEND_ON
||
state
>=
PM_SUSPEND_MAX
)
return
-
EINVAL
;
pr_info
(
"suspend entry (%s)
\n
"
,
mem_sleep_labels
[
state
]);
error
=
enter_state
(
state
);
if
(
error
)
{
suspend_stats
.
fail
++
;
...
...
@@ -586,6 +607,7 @@ int pm_suspend(suspend_state_t state)
}
else
{
suspend_stats
.
success
++
;
}
pr_info
(
"suspend exit
\n
"
);
return
error
;
}
EXPORT_SYMBOL
(
pm_suspend
);
kernel/power/suspend_test.c
View file @
cba630b6
...
...
@@ -104,9 +104,9 @@ static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state)
printk
(
info_test
,
pm_states
[
state
]);
status
=
pm_suspend
(
state
);
if
(
status
<
0
)
state
=
PM_SUSPEND_
FREEZ
E
;
state
=
PM_SUSPEND_
TO_IDL
E
;
}
if
(
state
==
PM_SUSPEND_
FREEZ
E
)
{
if
(
state
==
PM_SUSPEND_
TO_IDL
E
)
{
printk
(
info_test
,
pm_states
[
state
]);
status
=
pm_suspend
(
state
);
}
...
...
kernel/sched/idle.c
View file @
cba630b6
...
...
@@ -158,7 +158,7 @@ static void cpuidle_idle_call(void)
}
/*
* Suspend-to-idle ("
freez
e") is a system state in which all user space
* Suspend-to-idle ("
s2idl
e") is a system state in which all user space
* has been frozen, all I/O devices have been suspended and the only
* activity happens here and in iterrupts (if any). In that case bypass
* the cpuidle governor and go stratight for the deepest idle state
...
...
@@ -167,9 +167,9 @@ static void cpuidle_idle_call(void)
* until a proper wakeup interrupt happens.
*/
if
(
idle_should_
freez
e
()
||
dev
->
use_deepest_state
)
{
if
(
idle_should_
freez
e
())
{
entered_state
=
cpuidle_enter_
freez
e
(
drv
,
dev
);
if
(
idle_should_
enter_s2idl
e
()
||
dev
->
use_deepest_state
)
{
if
(
idle_should_
enter_s2idl
e
())
{
entered_state
=
cpuidle_enter_
s2idl
e
(
drv
,
dev
);
if
(
entered_state
>
0
)
{
local_irq_enable
();
goto
exit_idle
;
...
...
kernel/time/timekeeping_debug.c
View file @
cba630b6
...
...
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/seq_file.h>
#include <linux/suspend.h>
#include <linux/time.h>
#include "timekeeping_internal.h"
...
...
@@ -75,7 +76,7 @@ void tk_debug_account_sleep_time(struct timespec64 *t)
int
bin
=
min
(
fls
(
t
->
tv_sec
),
NUM_BINS
-
1
);
sleep_time_bin
[
bin
]
++
;
p
rintk_deferred
(
KERN_INFO
"S
uspended for %lld.%03lu seconds
\n
"
,
(
s64
)
t
->
tv_sec
,
t
->
tv_nsec
/
NSEC_PER_MSEC
);
p
m_deferred_pr_dbg
(
"Timekeeping s
uspended for %lld.%03lu seconds
\n
"
,
(
s64
)
t
->
tv_sec
,
t
->
tv_nsec
/
NSEC_PER_MSEC
);
}
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