--- /dev/null
+From 1f023007f5e782bda19ad9104830c404fd622c5d Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Mon, 11 Dec 2023 11:48:55 +0100
+Subject: arm64/amu: Use capacity_ref_freq() to set AMU ratio
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+commit 1f023007f5e782bda19ad9104830c404fd622c5d upstream.
+
+Use the new capacity_ref_freq() method to set the ratio that is used by AMU for
+computing the arch_scale_freq_capacity().
+This helps to keep everything aligned using the same reference for
+computing CPUs capacity.
+
+The default value of the ratio (stored in per_cpu(arch_max_freq_scale))
+ensures that arch_scale_freq_capacity() returns max capacity until it is
+set to its correct value with the cpu capacity and capacity_ref_freq().
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Sudeep Holla <sudeep.holla@arm.com>
+Acked-by: Will Deacon <will@kernel.org>
+Link: https://lore.kernel.org/r/20231211104855.558096-8-vincent.guittot@linaro.org
+Stable-dep-of: e37617c8e53a ("sched/fair: Fix frequency selection for non-invariant case")
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/topology.c | 26 +++++++++++++-------------
+ drivers/base/arch_topology.c | 12 +++++++++++-
+ include/linux/arch_topology.h | 1 +
+ 3 files changed, 25 insertions(+), 14 deletions(-)
+
+--- a/arch/arm64/kernel/topology.c
++++ b/arch/arm64/kernel/topology.c
+@@ -82,7 +82,12 @@ int __init parse_acpi_topology(void)
+ #undef pr_fmt
+ #define pr_fmt(fmt) "AMU: " fmt
+
+-static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, arch_max_freq_scale);
++/*
++ * Ensure that amu_scale_freq_tick() will return SCHED_CAPACITY_SCALE until
++ * the CPU capacity and its associated frequency have been correctly
++ * initialized.
++ */
++static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, arch_max_freq_scale) = 1UL << (2 * SCHED_CAPACITY_SHIFT);
+ static DEFINE_PER_CPU(u64, arch_const_cycles_prev);
+ static DEFINE_PER_CPU(u64, arch_core_cycles_prev);
+ static cpumask_var_t amu_fie_cpus;
+@@ -112,14 +117,14 @@ static inline bool freq_counters_valid(i
+ return true;
+ }
+
+-static int freq_inv_set_max_ratio(int cpu, u64 max_rate, u64 ref_rate)
++void freq_inv_set_max_ratio(int cpu, u64 max_rate)
+ {
+- u64 ratio;
++ u64 ratio, ref_rate = arch_timer_get_rate();
+
+ if (unlikely(!max_rate || !ref_rate)) {
+- pr_debug("CPU%d: invalid maximum or reference frequency.\n",
++ WARN_ONCE(1, "CPU%d: invalid maximum or reference frequency.\n",
+ cpu);
+- return -EINVAL;
++ return;
+ }
+
+ /*
+@@ -139,12 +144,10 @@ static int freq_inv_set_max_ratio(int cp
+ ratio = div64_u64(ratio, max_rate);
+ if (!ratio) {
+ WARN_ONCE(1, "Reference frequency too low.\n");
+- return -EINVAL;
++ return;
+ }
+
+- per_cpu(arch_max_freq_scale, cpu) = (unsigned long)ratio;
+-
+- return 0;
++ WRITE_ONCE(per_cpu(arch_max_freq_scale, cpu), (unsigned long)ratio);
+ }
+
+ static void amu_scale_freq_tick(void)
+@@ -195,10 +198,7 @@ static void amu_fie_setup(const struct c
+ return;
+
+ for_each_cpu(cpu, cpus) {
+- if (!freq_counters_valid(cpu) ||
+- freq_inv_set_max_ratio(cpu,
+- cpufreq_get_hw_max_freq(cpu) * 1000ULL,
+- arch_timer_get_rate()))
++ if (!freq_counters_valid(cpu))
+ return;
+ }
+
+--- a/drivers/base/arch_topology.c
++++ b/drivers/base/arch_topology.c
+@@ -344,6 +344,10 @@ bool __init topology_parse_cpu_capacity(
+ return !ret;
+ }
+
++void __weak freq_inv_set_max_ratio(int cpu, u64 max_rate)
++{
++}
++
+ #ifdef CONFIG_ACPI_CPPC_LIB
+ #include <acpi/cppc_acpi.h>
+
+@@ -381,6 +385,9 @@ void topology_init_cpu_capacity_cppc(voi
+ }
+
+ for_each_possible_cpu(cpu) {
++ freq_inv_set_max_ratio(cpu,
++ per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ);
++
+ capacity = raw_capacity[cpu];
+ capacity = div64_u64(capacity << SCHED_CAPACITY_SHIFT,
+ capacity_scale);
+@@ -422,8 +429,11 @@ init_cpu_capacity_callback(struct notifi
+
+ cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus);
+
+- for_each_cpu(cpu, policy->related_cpus)
++ for_each_cpu(cpu, policy->related_cpus) {
+ per_cpu(capacity_freq_ref, cpu) = policy->cpuinfo.max_freq;
++ freq_inv_set_max_ratio(cpu,
++ per_cpu(capacity_freq_ref, cpu) * HZ_PER_KHZ);
++ }
+
+ if (cpumask_empty(cpus_to_visit)) {
+ topology_normalize_cpu_scale();
+--- a/include/linux/arch_topology.h
++++ b/include/linux/arch_topology.h
+@@ -99,6 +99,7 @@ void update_siblings_masks(unsigned int
+ void remove_cpu_topology(unsigned int cpuid);
+ void reset_cpu_topology(void);
+ int parse_acpi_topology(void);
++void freq_inv_set_max_ratio(int cpu, u64 max_rate);
+ #endif
+
+ #endif /* _LINUX_ARCH_TOPOLOGY_H_ */
--- /dev/null
+From 5477fa249b56c59c3baa1b237bf083cffa64c84a Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Mon, 11 Dec 2023 11:48:54 +0100
+Subject: cpufreq/cppc: Set the frequency used for computing the capacity
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+commit 5477fa249b56c59c3baa1b237bf083cffa64c84a upstream.
+
+Save the frequency associated to the performance that has been used when
+initializing the capacity of CPUs.
+
+Also, cppc cpufreq driver can register an artificial energy model. In such
+case, it needs the frequency for this compute capacity.
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Pierre Gondois <pierre.gondois@arm.com>
+Acked-by: Sudeep Holla <sudeep.holla@arm.com>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Link: https://lore.kernel.org/r/20231211104855.558096-7-vincent.guittot@linaro.org
+Stable-dep-of: e37617c8e53a ("sched/fair: Fix frequency selection for non-invariant case")
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/arch_topology.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/base/arch_topology.c
++++ b/drivers/base/arch_topology.c
+@@ -349,6 +349,7 @@ bool __init topology_parse_cpu_capacity(
+
+ void topology_init_cpu_capacity_cppc(void)
+ {
++ u64 capacity, capacity_scale = 0;
+ struct cppc_perf_caps perf_caps;
+ int cpu;
+
+@@ -365,6 +366,10 @@ void topology_init_cpu_capacity_cppc(voi
+ (perf_caps.highest_perf >= perf_caps.nominal_perf) &&
+ (perf_caps.highest_perf >= perf_caps.lowest_perf)) {
+ raw_capacity[cpu] = perf_caps.highest_perf;
++ capacity_scale = max_t(u64, capacity_scale, raw_capacity[cpu]);
++
++ per_cpu(capacity_freq_ref, cpu) = cppc_perf_to_khz(&perf_caps, raw_capacity[cpu]);
++
+ pr_debug("cpu_capacity: CPU%d cpu_capacity=%u (raw).\n",
+ cpu, raw_capacity[cpu]);
+ continue;
+@@ -375,7 +380,15 @@ void topology_init_cpu_capacity_cppc(voi
+ goto exit;
+ }
+
+- topology_normalize_cpu_scale();
++ for_each_possible_cpu(cpu) {
++ capacity = raw_capacity[cpu];
++ capacity = div64_u64(capacity << SCHED_CAPACITY_SHIFT,
++ capacity_scale);
++ topology_set_cpu_scale(cpu, capacity);
++ pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n",
++ cpu, topology_get_cpu_scale(cpu));
++ }
++
+ schedule_work(&update_topology_flags_work);
+ pr_debug("cpu_capacity: cpu_capacity initialization done\n");
+
--- /dev/null
+From b3edde44e5d4504c23a176819865cd603fd16d6c Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Mon, 11 Dec 2023 11:48:51 +0100
+Subject: cpufreq/schedutil: Use a fixed reference frequency
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+commit b3edde44e5d4504c23a176819865cd603fd16d6c upstream.
+
+cpuinfo.max_freq can change at runtime because of boost as an example. This
+implies that the value could be different than the one that has been
+used when computing the capacity of a CPU.
+
+The new arch_scale_freq_ref() returns a fixed and coherent reference
+frequency that can be used when computing a frequency based on utilization.
+
+Use this arch_scale_freq_ref() when available and fallback to
+policy otherwise.
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Lukasz Luba <lukasz.luba@arm.com>
+Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
+Reviewed-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Acked-by: Rafael J. Wysocki <rafael@kernel.org>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Link: https://lore.kernel.org/r/20231211104855.558096-4-vincent.guittot@linaro.org
+Stable-dep-of: e37617c8e53a ("sched/fair: Fix frequency selection for non-invariant case")
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/cpufreq_schedutil.c | 26 ++++++++++++++++++++++++--
+ 1 file changed, 24 insertions(+), 2 deletions(-)
+
+--- a/kernel/sched/cpufreq_schedutil.c
++++ b/kernel/sched/cpufreq_schedutil.c
+@@ -138,6 +138,28 @@ static void sugov_deferred_update(struct
+ }
+
+ /**
++ * get_capacity_ref_freq - get the reference frequency that has been used to
++ * correlate frequency and compute capacity for a given cpufreq policy. We use
++ * the CPU managing it for the arch_scale_freq_ref() call in the function.
++ * @policy: the cpufreq policy of the CPU in question.
++ *
++ * Return: the reference CPU frequency to compute a capacity.
++ */
++static __always_inline
++unsigned long get_capacity_ref_freq(struct cpufreq_policy *policy)
++{
++ unsigned int freq = arch_scale_freq_ref(policy->cpu);
++
++ if (freq)
++ return freq;
++
++ if (arch_scale_freq_invariant())
++ return policy->cpuinfo.max_freq;
++
++ return policy->cur;
++}
++
++/**
+ * get_next_freq - Compute a new frequency for a given cpufreq policy.
+ * @sg_policy: schedutil policy object to compute the new frequency for.
+ * @util: Current CPU utilization.
+@@ -163,9 +185,9 @@ static unsigned int get_next_freq(struct
+ unsigned long util, unsigned long max)
+ {
+ struct cpufreq_policy *policy = sg_policy->policy;
+- unsigned int freq = arch_scale_freq_invariant() ?
+- policy->cpuinfo.max_freq : policy->cur;
++ unsigned int freq;
+
++ freq = get_capacity_ref_freq(policy);
+ freq = map_util_freq(util, freq, max);
+
+ if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
--- /dev/null
+From 599457ba15403037b489fe536266a3d5f9efaed7 Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Mon, 11 Dec 2023 11:48:50 +0100
+Subject: cpufreq: Use the fixed and coherent frequency for scaling capacity
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+commit 599457ba15403037b489fe536266a3d5f9efaed7 upstream.
+
+cpuinfo.max_freq can change at runtime because of boost as an example. This
+implies that the value could be different from the frequency that has been
+used to compute the capacity of a CPU.
+
+The new arch_scale_freq_ref() returns a fixed and coherent frequency
+that can be used to compute the capacity for a given frequency.
+
+[ Also fix a arch_set_freq_scale() newline style wart in <linux/cpufreq.h>. ]
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Lukasz Luba <lukasz.luba@arm.com>
+Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
+Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
+Acked-by: Rafael J. Wysocki <rafael@kernel.org>
+Link: https://lore.kernel.org/r/20231211104855.558096-3-vincent.guittot@linaro.org
+Stable-dep-of: e37617c8e53a ("sched/fair: Fix frequency selection for non-invariant case")
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/cpufreq.c | 4 ++--
+ include/linux/cpufreq.h | 1 +
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -454,7 +454,7 @@ void cpufreq_freq_transition_end(struct
+
+ arch_set_freq_scale(policy->related_cpus,
+ policy->cur,
+- policy->cpuinfo.max_freq);
++ arch_scale_freq_ref(policy->cpu));
+
+ spin_lock(&policy->transition_lock);
+ policy->transition_ongoing = false;
+@@ -2205,7 +2205,7 @@ unsigned int cpufreq_driver_fast_switch(
+
+ policy->cur = freq;
+ arch_set_freq_scale(policy->related_cpus, freq,
+- policy->cpuinfo.max_freq);
++ arch_scale_freq_ref(policy->cpu));
+ cpufreq_stats_record_transition(policy, freq);
+
+ if (trace_cpu_frequency_enabled()) {
+--- a/include/linux/cpufreq.h
++++ b/include/linux/cpufreq.h
+@@ -1245,6 +1245,7 @@ void arch_set_freq_scale(const struct cp
+ {
+ }
+ #endif
++
+ /* the following are really really optional */
+ extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+ extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs;
--- /dev/null
+From 15cbbd1d317e07b4e5c6aca5d4c5579539a82784 Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Mon, 11 Dec 2023 11:48:52 +0100
+Subject: energy_model: Use a fixed reference frequency
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+commit 15cbbd1d317e07b4e5c6aca5d4c5579539a82784 upstream.
+
+The last item of a performance domain is not always the performance point
+that has been used to compute CPU's capacity. This can lead to different
+target frequency compared with other part of the system like schedutil and
+would result in wrong energy estimation.
+
+A new arch_scale_freq_ref() is available to return a fixed and coherent
+frequency reference that can be used when computing the CPU's frequency
+for an level of utilization. Use this function to get this reference
+frequency.
+
+Energy model is never used without defining arch_scale_freq_ref() but
+can be compiled. Define a default arch_scale_freq_ref() returning 0
+in such case.
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Lukasz Luba <lukasz.luba@arm.com>
+Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
+Link: https://lore.kernel.org/r/20231211104855.558096-5-vincent.guittot@linaro.org
+Stable-dep-of: e37617c8e53a ("sched/fair: Fix frequency selection for non-invariant case")
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/energy_model.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/include/linux/energy_model.h
++++ b/include/linux/energy_model.h
+@@ -224,7 +224,7 @@ static inline unsigned long em_cpu_energ
+ unsigned long max_util, unsigned long sum_util,
+ unsigned long allowed_cpu_cap)
+ {
+- unsigned long freq, scale_cpu;
++ unsigned long freq, ref_freq, scale_cpu;
+ struct em_perf_state *ps;
+ int cpu;
+
+@@ -241,10 +241,10 @@ static inline unsigned long em_cpu_energ
+ */
+ cpu = cpumask_first(to_cpumask(pd->cpus));
+ scale_cpu = arch_scale_cpu_capacity(cpu);
+- ps = &pd->table[pd->nr_perf_states - 1];
++ ref_freq = arch_scale_freq_ref(cpu);
+
+ max_util = min(max_util, allowed_cpu_cap);
+- freq = map_util_freq(max_util, ps->frequency, scale_cpu);
++ freq = map_util_freq(max_util, ref_freq, scale_cpu);
+
+ /*
+ * Find the lowest performance state of the Energy Model above the
--- /dev/null
+From e37617c8e53a1f7fcba6d5e1041f4fd8a2425c27 Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Sun, 14 Jan 2024 19:36:00 +0100
+Subject: sched/fair: Fix frequency selection for non-invariant case
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+commit e37617c8e53a1f7fcba6d5e1041f4fd8a2425c27 upstream.
+
+Linus reported a ~50% performance regression on single-threaded
+workloads on his AMD Ryzen system, and bisected it to:
+
+ 9c0b4bb7f630 ("sched/cpufreq: Rework schedutil governor performance estimation")
+
+When frequency invariance is not enabled, get_capacity_ref_freq(policy)
+is supposed to return the current frequency and the performance margin
+applied by map_util_perf(), enabling the utilization to go above the
+maximum compute capacity and to select a higher frequency than the current one.
+
+After the changes in 9c0b4bb7f630, the performance margin was applied
+earlier in the path to take into account utilization clampings and
+we couldn't get a utilization higher than the maximum compute capacity,
+and the CPU remained 'stuck' at lower frequencies.
+
+To fix this, we must use a frequency above the current frequency to
+get a chance to select a higher OPP when the current one becomes fully used.
+Apply the same margin and return a frequency 25% higher than the current
+one in order to switch to the next OPP before we fully use the CPU
+at the current one.
+
+[ mingo: Clarified the changelog. ]
+
+Fixes: 9c0b4bb7f630 ("sched/cpufreq: Rework schedutil governor performance estimation")
+Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
+Bisected-by: Linus Torvalds <torvalds@linux-foundation.org>
+Reported-by: Wyes Karny <wkarny@gmail.com>
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Wyes Karny <wkarny@gmail.com>
+Link: https://lore.kernel.org/r/20240114183600.135316-1-vincent.guittot@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/cpufreq_schedutil.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/kernel/sched/cpufreq_schedutil.c
++++ b/kernel/sched/cpufreq_schedutil.c
+@@ -156,7 +156,11 @@ unsigned long get_capacity_ref_freq(stru
+ if (arch_scale_freq_invariant())
+ return policy->cpuinfo.max_freq;
+
+- return policy->cur;
++ /*
++ * Apply a 25% margin so that we select a higher frequency than
++ * the current one before the CPU is fully busy:
++ */
++ return policy->cur + (policy->cur >> 2);
+ }
+
+ /**
--- /dev/null
+From 9942cb22ea458c34fa17b73d143ea32d4df1caca Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Mon, 11 Dec 2023 11:48:49 +0100
+Subject: sched/topology: Add a new arch_scale_freq_ref() method
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+commit 9942cb22ea458c34fa17b73d143ea32d4df1caca upstream.
+
+Create a new method to get a unique and fixed max frequency. Currently
+cpuinfo.max_freq or the highest (or last) state of performance domain are
+used as the max frequency when computing the frequency for a level of
+utilization, but:
+
+ - cpuinfo_max_freq can change at runtime. boost is one example of
+ such change.
+
+ - cpuinfo.max_freq and last item of the PD can be different leading to
+ different results between cpufreq and energy model.
+
+We need to save the reference frequency that has been used when computing
+the CPUs capacity and use this fixed and coherent value to convert between
+frequency and CPU's capacity.
+
+In fact, we already save the frequency that has been used when computing
+the capacity of each CPU. We extend the precision to save kHz instead of
+MHz currently and we modify the type to be aligned with other variables
+used when converting frequency to capacity and the other way.
+
+[ mingo: Minor edits. ]
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Lukasz Luba <lukasz.luba@arm.com>
+Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
+Acked-by: Sudeep Holla <sudeep.holla@arm.com>
+Link: https://lore.kernel.org/r/20231211104855.558096-2-vincent.guittot@linaro.org
+Stable-dep-of: e37617c8e53a ("sched/fair: Fix frequency selection for non-invariant case")
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/include/asm/topology.h | 1 +
+ arch/arm64/include/asm/topology.h | 1 +
+ arch/riscv/include/asm/topology.h | 1 +
+ drivers/base/arch_topology.c | 29 ++++++++++++++---------------
+ include/linux/arch_topology.h | 7 +++++++
+ include/linux/sched/topology.h | 8 ++++++++
+ 6 files changed, 32 insertions(+), 15 deletions(-)
+
+--- a/arch/arm/include/asm/topology.h
++++ b/arch/arm/include/asm/topology.h
+@@ -13,6 +13,7 @@
+ #define arch_set_freq_scale topology_set_freq_scale
+ #define arch_scale_freq_capacity topology_get_freq_scale
+ #define arch_scale_freq_invariant topology_scale_freq_invariant
++#define arch_scale_freq_ref topology_get_freq_ref
+ #endif
+
+ /* Replace task scheduler's default cpu-invariant accounting */
+--- a/arch/arm64/include/asm/topology.h
++++ b/arch/arm64/include/asm/topology.h
+@@ -23,6 +23,7 @@ void update_freq_counters_refs(void);
+ #define arch_set_freq_scale topology_set_freq_scale
+ #define arch_scale_freq_capacity topology_get_freq_scale
+ #define arch_scale_freq_invariant topology_scale_freq_invariant
++#define arch_scale_freq_ref topology_get_freq_ref
+
+ #ifdef CONFIG_ACPI_CPPC_LIB
+ #define arch_init_invariance_cppc topology_init_cpu_capacity_cppc
+--- a/arch/riscv/include/asm/topology.h
++++ b/arch/riscv/include/asm/topology.h
+@@ -9,6 +9,7 @@
+ #define arch_set_freq_scale topology_set_freq_scale
+ #define arch_scale_freq_capacity topology_get_freq_scale
+ #define arch_scale_freq_invariant topology_scale_freq_invariant
++#define arch_scale_freq_ref topology_get_freq_ref
+
+ /* Replace task scheduler's default cpu-invariant accounting */
+ #define arch_scale_cpu_capacity topology_get_cpu_scale
+--- a/drivers/base/arch_topology.c
++++ b/drivers/base/arch_topology.c
+@@ -19,6 +19,7 @@
+ #include <linux/init.h>
+ #include <linux/rcupdate.h>
+ #include <linux/sched.h>
++#include <linux/units.h>
+
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/thermal_pressure.h>
+@@ -26,7 +27,8 @@
+ static DEFINE_PER_CPU(struct scale_freq_data __rcu *, sft_data);
+ static struct cpumask scale_freq_counters_mask;
+ static bool scale_freq_invariant;
+-static DEFINE_PER_CPU(u32, freq_factor) = 1;
++DEFINE_PER_CPU(unsigned long, capacity_freq_ref) = 1;
++EXPORT_PER_CPU_SYMBOL_GPL(capacity_freq_ref);
+
+ static bool supports_scale_freq_counters(const struct cpumask *cpus)
+ {
+@@ -170,9 +172,9 @@ DEFINE_PER_CPU(unsigned long, thermal_pr
+ * operating on stale data when hot-plug is used for some CPUs. The
+ * @capped_freq reflects the currently allowed max CPUs frequency due to
+ * thermal capping. It might be also a boost frequency value, which is bigger
+- * than the internal 'freq_factor' max frequency. In such case the pressure
+- * value should simply be removed, since this is an indication that there is
+- * no thermal throttling. The @capped_freq must be provided in kHz.
++ * than the internal 'capacity_freq_ref' max frequency. In such case the
++ * pressure value should simply be removed, since this is an indication that
++ * there is no thermal throttling. The @capped_freq must be provided in kHz.
+ */
+ void topology_update_thermal_pressure(const struct cpumask *cpus,
+ unsigned long capped_freq)
+@@ -183,10 +185,7 @@ void topology_update_thermal_pressure(co
+
+ cpu = cpumask_first(cpus);
+ max_capacity = arch_scale_cpu_capacity(cpu);
+- max_freq = per_cpu(freq_factor, cpu);
+-
+- /* Convert to MHz scale which is used in 'freq_factor' */
+- capped_freq /= 1000;
++ max_freq = arch_scale_freq_ref(cpu);
+
+ /*
+ * Handle properly the boost frequencies, which should simply clean
+@@ -279,13 +278,13 @@ void topology_normalize_cpu_scale(void)
+
+ capacity_scale = 1;
+ for_each_possible_cpu(cpu) {
+- capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu);
++ capacity = raw_capacity[cpu] * per_cpu(capacity_freq_ref, cpu);
+ capacity_scale = max(capacity, capacity_scale);
+ }
+
+ pr_debug("cpu_capacity: capacity_scale=%llu\n", capacity_scale);
+ for_each_possible_cpu(cpu) {
+- capacity = raw_capacity[cpu] * per_cpu(freq_factor, cpu);
++ capacity = raw_capacity[cpu] * per_cpu(capacity_freq_ref, cpu);
+ capacity = div64_u64(capacity << SCHED_CAPACITY_SHIFT,
+ capacity_scale);
+ topology_set_cpu_scale(cpu, capacity);
+@@ -321,15 +320,15 @@ bool __init topology_parse_cpu_capacity(
+ cpu_node, raw_capacity[cpu]);
+
+ /*
+- * Update freq_factor for calculating early boot cpu capacities.
++ * Update capacity_freq_ref for calculating early boot CPU capacities.
+ * For non-clk CPU DVFS mechanism, there's no way to get the
+ * frequency value now, assuming they are running at the same
+- * frequency (by keeping the initial freq_factor value).
++ * frequency (by keeping the initial capacity_freq_ref value).
+ */
+ cpu_clk = of_clk_get(cpu_node, 0);
+ if (!PTR_ERR_OR_ZERO(cpu_clk)) {
+- per_cpu(freq_factor, cpu) =
+- clk_get_rate(cpu_clk) / 1000;
++ per_cpu(capacity_freq_ref, cpu) =
++ clk_get_rate(cpu_clk) / HZ_PER_KHZ;
+ clk_put(cpu_clk);
+ }
+ } else {
+@@ -411,7 +410,7 @@ init_cpu_capacity_callback(struct notifi
+ cpumask_andnot(cpus_to_visit, cpus_to_visit, policy->related_cpus);
+
+ for_each_cpu(cpu, policy->related_cpus)
+- per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000;
++ per_cpu(capacity_freq_ref, cpu) = policy->cpuinfo.max_freq;
+
+ if (cpumask_empty(cpus_to_visit)) {
+ topology_normalize_cpu_scale();
+--- a/include/linux/arch_topology.h
++++ b/include/linux/arch_topology.h
+@@ -27,6 +27,13 @@ static inline unsigned long topology_get
+
+ void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity);
+
++DECLARE_PER_CPU(unsigned long, capacity_freq_ref);
++
++static inline unsigned long topology_get_freq_ref(int cpu)
++{
++ return per_cpu(capacity_freq_ref, cpu);
++}
++
+ DECLARE_PER_CPU(unsigned long, arch_freq_scale);
+
+ static inline unsigned long topology_get_freq_scale(int cpu)
+--- a/include/linux/sched/topology.h
++++ b/include/linux/sched/topology.h
+@@ -275,6 +275,14 @@ void arch_update_thermal_pressure(const
+ { }
+ #endif
+
++#ifndef arch_scale_freq_ref
++static __always_inline
++unsigned int arch_scale_freq_ref(int cpu)
++{
++ return 0;
++}
++#endif
++
+ static inline int task_node(const struct task_struct *p)
+ {
+ return cpu_to_node(task_cpu(p));
pm-runtime-take-active-children-into-account-in-pm_runtime_get_if_in_use.patch
ata-libata-scsi-return-aborted-command-when-missing-sense-and-result-tf.patch
kbuild-userprogs-use-correct-linker-when-mixing-clang-and-gnu-ld.patch
+sched-topology-add-a-new-arch_scale_freq_ref-method.patch
+cpufreq-use-the-fixed-and-coherent-frequency-for-scaling-capacity.patch
+cpufreq-schedutil-use-a-fixed-reference-frequency.patch
+energy_model-use-a-fixed-reference-frequency.patch
+cpufreq-cppc-set-the-frequency-used-for-computing-the-capacity.patch
+arm64-amu-use-capacity_ref_freq-to-set-amu-ratio.patch
+topology-set-capacity_freq_ref-in-all-cases.patch
+sched-fair-fix-frequency-selection-for-non-invariant-case.patch
--- /dev/null
+From 98323e9d70172f1b46d1cadb20d6c54abf62870d Mon Sep 17 00:00:00 2001
+From: Vincent Guittot <vincent.guittot@linaro.org>
+Date: Wed, 17 Jan 2024 20:05:45 +0100
+Subject: topology: Set capacity_freq_ref in all cases
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+commit 98323e9d70172f1b46d1cadb20d6c54abf62870d upstream.
+
+If "capacity-dmips-mhz" is not set, raw_capacity is null and we skip the
+normalization step which includes setting per_cpu capacity_freq_ref.
+Always register the notifier but skip the capacity normalization if
+raw_capacity is null.
+
+Fixes: 9942cb22ea45 ("sched/topology: Add a new arch_scale_freq_ref() method")
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Acked-by: Sudeep Holla <sudeep.holla@arm.com>
+Tested-by: Pierre Gondois <pierre.gondois@arm.com>
+Tested-by: Mark Brown <broonie@kernel.org>
+Tested-by: Paul Barker <paul.barker.ct@bp.renesas.com>
+Reviewed-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Tested-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Link: https://lore.kernel.org/r/20240117190545.596057-1-vincent.guittot@linaro.org
+Stable-dep-of: e37617c8e53a ("sched/fair: Fix frequency selection for non-invariant case")
+Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/arch_topology.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+--- a/drivers/base/arch_topology.c
++++ b/drivers/base/arch_topology.c
+@@ -417,9 +417,6 @@ init_cpu_capacity_callback(struct notifi
+ struct cpufreq_policy *policy = data;
+ int cpu;
+
+- if (!raw_capacity)
+- return 0;
+-
+ if (val != CPUFREQ_CREATE_POLICY)
+ return 0;
+
+@@ -436,9 +433,11 @@ init_cpu_capacity_callback(struct notifi
+ }
+
+ if (cpumask_empty(cpus_to_visit)) {
+- topology_normalize_cpu_scale();
+- schedule_work(&update_topology_flags_work);
+- free_raw_capacity();
++ if (raw_capacity) {
++ topology_normalize_cpu_scale();
++ schedule_work(&update_topology_flags_work);
++ free_raw_capacity();
++ }
+ pr_debug("cpu_capacity: parsing done\n");
+ schedule_work(&parsing_done_work);
+ }
+@@ -458,7 +457,7 @@ static int __init register_cpufreq_notif
+ * On ACPI-based systems skip registering cpufreq notifier as cpufreq
+ * information is not needed for cpu capacity initialization.
+ */
+- if (!acpi_disabled || !raw_capacity)
++ if (!acpi_disabled)
+ return -EINVAL;
+
+ if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL))