Merge branches 'pm-sleep' and 'powercap'
* pm-sleep: PM / sleep: Print active wakeup sources when blocking on wakeup_count reads x86/suspend: fix false positive KASAN warning on suspend/resume PM / sleep / ACPI: Use the ACPI_FADT_LOW_POWER_S0 flag PM / sleep: System sleep state selection interface rework PM / hibernate: Verify the consistent of e820 memory map by md5 digest * powercap: powercap / RAPL: Add Knights Mill CPUID powercap/intel_rapl: fix and tidy up error handling powercap/intel_rapl: Track active CPUs internally powercap/intel_rapl: Cleanup duplicated init code powercap/intel rapl: Convert to hotplug state machine powercap/intel_rapl: Propagate error code when registration fails powercap/intel_rapl: Add missing domain data update on hotplug
This commit is contained in:
@@ -78,6 +78,78 @@ static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
|
||||
power_attr(pm_async);
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
static ssize_t mem_sleep_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
char *s = buf;
|
||||
suspend_state_t i;
|
||||
|
||||
for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
|
||||
if (mem_sleep_states[i]) {
|
||||
const char *label = mem_sleep_states[i];
|
||||
|
||||
if (mem_sleep_current == i)
|
||||
s += sprintf(s, "[%s] ", label);
|
||||
else
|
||||
s += sprintf(s, "%s ", label);
|
||||
}
|
||||
|
||||
/* Convert the last space to a newline if needed. */
|
||||
if (s != buf)
|
||||
*(s-1) = '\n';
|
||||
|
||||
return (s - buf);
|
||||
}
|
||||
|
||||
static suspend_state_t decode_suspend_state(const char *buf, size_t n)
|
||||
{
|
||||
suspend_state_t state;
|
||||
char *p;
|
||||
int len;
|
||||
|
||||
p = memchr(buf, '\n', n);
|
||||
len = p ? p - buf : n;
|
||||
|
||||
for (state = PM_SUSPEND_MIN; state < PM_SUSPEND_MAX; state++) {
|
||||
const char *label = mem_sleep_states[state];
|
||||
|
||||
if (label && len == strlen(label) && !strncmp(buf, label, len))
|
||||
return state;
|
||||
}
|
||||
|
||||
return PM_SUSPEND_ON;
|
||||
}
|
||||
|
||||
static ssize_t mem_sleep_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t n)
|
||||
{
|
||||
suspend_state_t state;
|
||||
int error;
|
||||
|
||||
error = pm_autosleep_lock();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (pm_autosleep_state() > PM_SUSPEND_ON) {
|
||||
error = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
state = decode_suspend_state(buf, n);
|
||||
if (state < PM_SUSPEND_MAX && state > PM_SUSPEND_ON)
|
||||
mem_sleep_current = state;
|
||||
else
|
||||
error = -EINVAL;
|
||||
|
||||
out:
|
||||
pm_autosleep_unlock();
|
||||
return error ? error : n;
|
||||
}
|
||||
|
||||
power_attr(mem_sleep);
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
|
||||
#ifdef CONFIG_PM_DEBUG
|
||||
int pm_test_level = TEST_NONE;
|
||||
|
||||
@@ -368,12 +440,16 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
}
|
||||
|
||||
state = decode_state(buf, n);
|
||||
if (state < PM_SUSPEND_MAX)
|
||||
if (state < PM_SUSPEND_MAX) {
|
||||
if (state == PM_SUSPEND_MEM)
|
||||
state = mem_sleep_current;
|
||||
|
||||
error = pm_suspend(state);
|
||||
else if (state == PM_SUSPEND_MAX)
|
||||
} else if (state == PM_SUSPEND_MAX) {
|
||||
error = hibernate();
|
||||
else
|
||||
} else {
|
||||
error = -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
pm_autosleep_unlock();
|
||||
@@ -485,6 +561,9 @@ static ssize_t autosleep_store(struct kobject *kobj,
|
||||
&& strcmp(buf, "off") && strcmp(buf, "off\n"))
|
||||
return -EINVAL;
|
||||
|
||||
if (state == PM_SUSPEND_MEM)
|
||||
state = mem_sleep_current;
|
||||
|
||||
error = pm_autosleep_set_state(state);
|
||||
return error ? error : n;
|
||||
}
|
||||
@@ -602,6 +681,9 @@ static struct attribute * g[] = {
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
&pm_async_attr.attr,
|
||||
&wakeup_count_attr.attr,
|
||||
#ifdef CONFIG_SUSPEND
|
||||
&mem_sleep_attr.attr,
|
||||
#endif
|
||||
#ifdef CONFIG_PM_AUTOSLEEP
|
||||
&autosleep_attr.attr,
|
||||
#endif
|
||||
|
@@ -189,11 +189,15 @@ extern void swsusp_show_speed(ktime_t, ktime_t, unsigned int, char *);
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
/* kernel/power/suspend.c */
|
||||
extern const char *pm_labels[];
|
||||
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 */
|
||||
#define mem_sleep_current PM_SUSPEND_ON
|
||||
|
||||
static inline int suspend_devices_and_enter(suspend_state_t state)
|
||||
{
|
||||
return -ENOSYS;
|
||||
|
@@ -32,8 +32,21 @@
|
||||
|
||||
#include "power.h"
|
||||
|
||||
const char *pm_labels[] = { "mem", "standby", "freeze", NULL };
|
||||
const char * const pm_labels[] = {
|
||||
[PM_SUSPEND_FREEZE] = "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_FREEZE] = "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;
|
||||
suspend_state_t mem_sleep_default = PM_SUSPEND_MAX;
|
||||
|
||||
unsigned int pm_suspend_global_flags;
|
||||
EXPORT_SYMBOL_GPL(pm_suspend_global_flags);
|
||||
@@ -110,30 +123,32 @@ static bool valid_state(suspend_state_t state)
|
||||
return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is set, the "mem" label always corresponds to the deepest sleep state
|
||||
* available, the "standby" label corresponds to the second deepest sleep state
|
||||
* available (if any), and the "freeze" label corresponds to the remaining
|
||||
* available sleep state (if there is one).
|
||||
*/
|
||||
static bool relative_states;
|
||||
|
||||
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_FREEZE];
|
||||
/*
|
||||
* freeze state should be supported even without any suspend_ops,
|
||||
* initialize pm_states accordingly here
|
||||
* Suspend-to-idle should be supported even without any suspend_ops,
|
||||
* initialize mem_sleep_states[] accordingly here.
|
||||
*/
|
||||
pm_states[PM_SUSPEND_FREEZE] = pm_labels[relative_states ? 0 : 2];
|
||||
mem_sleep_states[PM_SUSPEND_FREEZE] = mem_sleep_labels[PM_SUSPEND_FREEZE];
|
||||
}
|
||||
|
||||
static int __init sleep_states_setup(char *str)
|
||||
static int __init mem_sleep_default_setup(char *str)
|
||||
{
|
||||
relative_states = !strncmp(str, "1", 1);
|
||||
suspend_state_t state;
|
||||
|
||||
for (state = PM_SUSPEND_FREEZE; state <= PM_SUSPEND_MEM; state++)
|
||||
if (mem_sleep_labels[state] &&
|
||||
!strcmp(str, mem_sleep_labels[state])) {
|
||||
mem_sleep_default = state;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("relative_sleep_states=", sleep_states_setup);
|
||||
__setup("mem_sleep_default=", mem_sleep_default_setup);
|
||||
|
||||
/**
|
||||
* suspend_set_ops - Set the global suspend method table.
|
||||
@@ -141,21 +156,21 @@ __setup("relative_sleep_states=", sleep_states_setup);
|
||||
*/
|
||||
void suspend_set_ops(const struct platform_suspend_ops *ops)
|
||||
{
|
||||
suspend_state_t i;
|
||||
int j = 0;
|
||||
|
||||
lock_system_sleep();
|
||||
|
||||
suspend_ops = ops;
|
||||
for (i = PM_SUSPEND_MEM; i >= PM_SUSPEND_STANDBY; i--)
|
||||
if (valid_state(i)) {
|
||||
pm_states[i] = pm_labels[j++];
|
||||
} else if (!relative_states) {
|
||||
pm_states[i] = NULL;
|
||||
j++;
|
||||
}
|
||||
|
||||
pm_states[PM_SUSPEND_FREEZE] = pm_labels[j];
|
||||
if (valid_state(PM_SUSPEND_STANDBY)) {
|
||||
mem_sleep_states[PM_SUSPEND_STANDBY] = mem_sleep_labels[PM_SUSPEND_STANDBY];
|
||||
pm_states[PM_SUSPEND_STANDBY] = pm_labels[PM_SUSPEND_STANDBY];
|
||||
if (mem_sleep_default == PM_SUSPEND_STANDBY)
|
||||
mem_sleep_current = PM_SUSPEND_STANDBY;
|
||||
}
|
||||
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)
|
||||
mem_sleep_current = PM_SUSPEND_MEM;
|
||||
}
|
||||
|
||||
unlock_system_sleep();
|
||||
}
|
||||
|
Reference in New Issue
Block a user