From 5b22419ef4d7c39b40fac6a8e0ad40d1e03cbb2a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 9 Feb 2018 14:28:03 +0530 Subject: ARM: dts: mt7623: Remove "cooling-{min|max}-level" for CPU nodes The "cooling-min-level" and "cooling-max-level" properties are not parsed by any part of the kernel currently and the max cooling state of a CPU cooling device is found by referring to the cpufreq table instead. Remove the unused properties from the CPU nodes. Signed-off-by: Viresh Kumar Reviewed-by: Rob Herring Signed-off-by: Rafael J. Wysocki --- Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt index f6403089edcf..d36f07e0a2bb 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt @@ -21,8 +21,6 @@ Optional properties: flow is handled by hardware, hence no software "voltage tracking" is needed. - #cooling-cells: -- cooling-min-level: -- cooling-max-level: Please refer to Documentation/devicetree/bindings/thermal/thermal.txt for detail. @@ -67,8 +65,6 @@ Example 1 (MT7623 SoC): clock-names = "cpu", "intermediate"; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; - cooling-min-level = <0>; - cooling-max-level = <7>; }; cpu@1 { device_type = "cpu"; -- cgit v1.3-14-g43fede From 319ce21acca613eac051ace5437cf02a6020d81e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 9 Feb 2018 14:28:09 +0530 Subject: dt-bindings: cpufreq-dt: Remove "cooling-{min|max}-level" properties The "cooling-min-level" and "cooling-max-level" properties are not parsed by any part of kernel currently and the max cooling state of a CPU cooling device is found by referring to the cpufreq table instead. Remove the unused bindings. Signed-off-by: Viresh Kumar Reviewed-by: Rob Herring Signed-off-by: Rafael J. Wysocki --- Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt index dd3929e85dec..332aed8f4597 100644 --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt @@ -18,8 +18,6 @@ Optional properties: in unit of nanoseconds. - voltage-tolerance: Specify the CPU voltage tolerance in percentage. - #cooling-cells: -- cooling-min-level: -- cooling-max-level: Please refer to Documentation/devicetree/bindings/thermal/thermal.txt. Examples: @@ -40,8 +38,6 @@ cpus { >; clock-latency = <61036>; /* two CLK32 periods */ #cooling-cells = <2>; - cooling-min-level = <0>; - cooling-max-level = <2>; }; cpu@1 { -- cgit v1.3-14-g43fede From 64bdff698092aa6be28c3b248f887022eec77902 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 14 Mar 2018 12:27:21 +0100 Subject: PM: cpuidle/suspend: Add s2idle usage and time state attributes Add a new attribute group called "s2idle" under the sysfs directory of each cpuidle state that supports the ->enter_s2idle callback and put two new attributes, "usage" and "time", into that group to represent the number of times the given state was requested for suspend-to-idle and the total time spent in suspend-to-idle after requesting that state, respectively. That will allow diagnostic information related to suspend-to-idle to be collected without enabling advanced debug features and analyzing dmesg output. Signed-off-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-devices-system-cpu | 25 ++++++++++ drivers/cpuidle/cpuidle.c | 9 ++++ drivers/cpuidle/sysfs.c | 54 ++++++++++++++++++++++ include/linux/cpuidle.h | 4 ++ 4 files changed, 92 insertions(+) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index 4ed63b6cfb15..025b7cf3768d 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -198,6 +198,31 @@ Description: time (in microseconds) this cpu should spend in this idle state to make the transition worth the effort. +What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/ +Date: March 2018 +KernelVersion: v4.17 +Contact: Linux power management list +Description: + Idle state usage statistics related to suspend-to-idle. + + This attribute group is only present for states that can be + used in suspend-to-idle with suspended timekeeping. + +What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/time +Date: March 2018 +KernelVersion: v4.17 +Contact: Linux power management list +Description: + Total time spent by the CPU in suspend-to-idle (with scheduler + tick suspended) after requesting this state. + +What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/usage +Date: March 2018 +KernelVersion: v4.17 +Contact: Linux power management list +Description: + Total number of times this state has been requested by the CPU + while entering suspend-to-idle. What: /sys/devices/system/cpu/cpu#/cpufreq/* Date: pre-git history diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 68a16827f45f..0003e9a02637 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -131,6 +131,10 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv, static void enter_s2idle_proper(struct cpuidle_driver *drv, struct cpuidle_device *dev, int index) { + ktime_t time_start, time_end; + + time_start = ns_to_ktime(local_clock()); + /* * trace_suspend_resume() called by tick_freeze() for the last CPU * executing it contains RCU usage regarded as invalid in the idle @@ -152,6 +156,11 @@ static void enter_s2idle_proper(struct cpuidle_driver *drv, */ RCU_NONIDLE(tick_unfreeze()); start_critical_timings(); + + time_end = ns_to_ktime(local_clock()); + + dev->states_usage[index].s2idle_time += ktime_us_delta(time_end, time_start); + dev->states_usage[index].s2idle_usage++; } /** diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index ae948b1da93a..e754c7aae7f7 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -330,6 +330,58 @@ struct cpuidle_state_kobj { struct kobject kobj; }; +#ifdef CONFIG_SUSPEND +#define define_show_state_s2idle_ull_function(_name) \ +static ssize_t show_state_s2idle_##_name(struct cpuidle_state *state, \ + struct cpuidle_state_usage *state_usage, \ + char *buf) \ +{ \ + return sprintf(buf, "%llu\n", state_usage->s2idle_##_name);\ +} + +define_show_state_s2idle_ull_function(usage); +define_show_state_s2idle_ull_function(time); + +#define define_one_state_s2idle_ro(_name, show) \ +static struct cpuidle_state_attr attr_s2idle_##_name = \ + __ATTR(_name, 0444, show, NULL) + +define_one_state_s2idle_ro(usage, show_state_s2idle_usage); +define_one_state_s2idle_ro(time, show_state_s2idle_time); + +static struct attribute *cpuidle_state_s2idle_attrs[] = { + &attr_s2idle_usage.attr, + &attr_s2idle_time.attr, + NULL +}; + +static const struct attribute_group cpuidle_state_s2idle_group = { + .name = "s2idle", + .attrs = cpuidle_state_s2idle_attrs, +}; + +static void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj) +{ + int ret; + + if (!kobj->state->enter_s2idle) + return; + + ret = sysfs_create_group(&kobj->kobj, &cpuidle_state_s2idle_group); + if (ret) + pr_debug("%s: sysfs attribute group not created\n", __func__); +} + +static void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *kobj) +{ + if (kobj->state->enter_s2idle) + sysfs_remove_group(&kobj->kobj, &cpuidle_state_s2idle_group); +} +#else +static inline void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { } +static inline void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { } +#endif /* CONFIG_SUSPEND */ + #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj) #define kobj_to_state(k) (kobj_to_state_obj(k)->state) #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage) @@ -383,6 +435,7 @@ static struct kobj_type ktype_state_cpuidle = { static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i) { + cpuidle_remove_s2idle_attr_group(device->kobjs[i]); kobject_put(&device->kobjs[i]->kobj); wait_for_completion(&device->kobjs[i]->kobj_unregister); kfree(device->kobjs[i]); @@ -417,6 +470,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) kfree(kobj); goto error_state; } + cpuidle_add_s2idle_attr_group(kobj); kobject_uevent(&kobj->kobj, KOBJ_ADD); device->kobjs[i] = kobj; } diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 0b3fc229086c..a806e94c482f 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -33,6 +33,10 @@ struct cpuidle_state_usage { unsigned long long disable; unsigned long long usage; unsigned long long time; /* in US */ +#ifdef CONFIG_SUSPEND + unsigned long long s2idle_usage; + unsigned long long s2idle_time; /* in US */ +#endif }; struct cpuidle_state { -- cgit v1.3-14-g43fede From 355064675f1c997cea017ea64c8f2c216e5425d9 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 28 Mar 2018 12:01:09 -0500 Subject: PM / hibernate: Make passing hibernate offsets more friendly Currently the only way to specify a hibernate offset for a swap file is on the kernel command line. Add a new /sys/power/resume_offset that lets userspace specify the offset and disk to use when initiating a hibernate cycle. Signed-off-by: Mario Limonciello Signed-off-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-power | 14 ++++++++++++++ Documentation/power/swsusp.txt | 10 +++++++++- kernel/power/hibernate.c | 24 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power index 1e0d1dac706b..2f813d644c69 100644 --- a/Documentation/ABI/testing/sysfs-power +++ b/Documentation/ABI/testing/sysfs-power @@ -287,3 +287,17 @@ Description: 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. + +What: /sys/power/resume_offset +Date: April 2018 +Contact: Mario Limonciello +Description: + This file is used for telling the kernel an offset into a disk + to use when hibernating the system such as with a swap file. + + Reads from this file will display the current offset + the kernel will be using on the next hibernation + attempt. + + Using this sysfs file will override any values that were + set using the kernel command line for disk offset. \ No newline at end of file diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index 9f2f942a01cf..cc87adf44c0a 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt @@ -24,8 +24,16 @@ Some warnings, first. * see the FAQ below for details. (This is not true for more traditional * power states like "standby", which normally don't turn USB off.) +Swap partition: You need to append resume=/dev/your_swap_partition to kernel command -line. Then you suspend by +line or specify it using /sys/power/resume. + +Swap file: +If using a swapfile you can also specify a resume offset using +resume_offset= on the kernel command line or specify it +in /sys/power/resume_offset. + +After preparing then you suspend by echo shutdown > /sys/power/disk; echo disk > /sys/power/state diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index a5c36e9c56a6..d58fad3db22d 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -1061,6 +1061,29 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, power_attr(resume); +static ssize_t resume_offset_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%llu\n", (unsigned long long)swsusp_resume_block); +} + +static ssize_t resume_offset_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, + size_t n) +{ + unsigned long long offset; + int rc; + + rc = kstrtoull(buf, 0, &offset); + if (rc) + return rc; + swsusp_resume_block = offset; + + return n; +} + +power_attr(resume_offset); + static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -1106,6 +1129,7 @@ power_attr(reserved_size); static struct attribute * g[] = { &disk_attr.attr, + &resume_offset_attr.attr, &resume_attr.attr, &image_size_attr.attr, &reserved_size_attr.attr, -- cgit v1.3-14-g43fede