Skip to content

Commit 9c7d901

Browse files
rafaeljwPeter Zijlstra
authored andcommitted
x86: PM: Register syscore_ops for scale invariance
On x86 scale invariace tends to be disabled during resume from suspend-to-RAM, because the MPERF or APERF MSR values are not as expected then due to updates taking place after the platform firmware has been invoked to complete the suspend transition. That, of course, is not desirable, especially if the schedutil scaling governor is in use, because the lack of scale invariance causes it to be less reliable. To counter that effect, modify init_freq_invariance() to register a syscore_ops object for scale invariance with the ->resume callback pointing to init_counter_refs() which will run on the CPU starting the resume transition (the other CPUs will be taken care of the "online" operations taking place later). Fixes: e2b0d61 ("x86, sched: check for counters overflow in frequency invariant accounting") Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Giovanni Gherdovich <ggherdovich@suse.cz> Link: https://lkml.kernel.org/r/1803209.Mvru99baaF@kreacher
1 parent 7c53f6b commit 9c7d901

1 file changed

Lines changed: 19 additions & 0 deletions

File tree

arch/x86/kernel/smpboot.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include <linux/numa.h>
5757
#include <linux/pgtable.h>
5858
#include <linux/overflow.h>
59+
#include <linux/syscore_ops.h>
5960

6061
#include <asm/acpi.h>
6162
#include <asm/desc.h>
@@ -2083,6 +2084,23 @@ static void init_counter_refs(void)
20832084
this_cpu_write(arch_prev_mperf, mperf);
20842085
}
20852086

2087+
#ifdef CONFIG_PM_SLEEP
2088+
static struct syscore_ops freq_invariance_syscore_ops = {
2089+
.resume = init_counter_refs,
2090+
};
2091+
2092+
static void register_freq_invariance_syscore_ops(void)
2093+
{
2094+
/* Bail out if registered already. */
2095+
if (freq_invariance_syscore_ops.node.prev)
2096+
return;
2097+
2098+
register_syscore_ops(&freq_invariance_syscore_ops);
2099+
}
2100+
#else
2101+
static inline void register_freq_invariance_syscore_ops(void) {}
2102+
#endif
2103+
20862104
static void init_freq_invariance(bool secondary, bool cppc_ready)
20872105
{
20882106
bool ret = false;
@@ -2109,6 +2127,7 @@ static void init_freq_invariance(bool secondary, bool cppc_ready)
21092127
if (ret) {
21102128
init_counter_refs();
21112129
static_branch_enable(&arch_scale_freq_key);
2130+
register_freq_invariance_syscore_ops();
21122131
pr_info("Estimated ratio of average max frequency by base frequency (times 1024): %llu\n", arch_max_freq_ratio);
21132132
} else {
21142133
pr_debug("Couldn't determine max cpu frequency, necessary for scale-invariant accounting.\n");

0 commit comments

Comments
 (0)