From: Greg Kroah-Hartman Date: Fri, 22 Aug 2025 09:04:33 +0000 (+0200) Subject: 6.6-stable patches X-Git-Tag: v6.16.3~54 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=15c2c1beef90d5ec7d601e993e9123d2d4891a18;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: arm64-amu-use-capacity_ref_freq-to-set-amu-ratio.patch cpufreq-cppc-set-the-frequency-used-for-computing-the-capacity.patch cpufreq-schedutil-use-a-fixed-reference-frequency.patch cpufreq-use-the-fixed-and-coherent-frequency-for-scaling-capacity.patch energy_model-use-a-fixed-reference-frequency.patch sched-fair-fix-frequency-selection-for-non-invariant-case.patch sched-topology-add-a-new-arch_scale_freq_ref-method.patch topology-set-capacity_freq_ref-in-all-cases.patch --- diff --git a/queue-6.6/arm64-amu-use-capacity_ref_freq-to-set-amu-ratio.patch b/queue-6.6/arm64-amu-use-capacity_ref_freq-to-set-amu-ratio.patch new file mode 100644 index 0000000000..1c4b155ffc --- /dev/null +++ b/queue-6.6/arm64-amu-use-capacity_ref_freq-to-set-amu-ratio.patch @@ -0,0 +1,140 @@ +From 1f023007f5e782bda19ad9104830c404fd622c5d Mon Sep 17 00:00:00 2001 +From: Vincent Guittot +Date: Mon, 11 Dec 2023 11:48:55 +0100 +Subject: arm64/amu: Use capacity_ref_freq() to set AMU ratio + +From: Vincent Guittot + +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 +Signed-off-by: Ingo Molnar +Acked-by: Sudeep Holla +Acked-by: Will Deacon +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 + +@@ -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_ */ diff --git a/queue-6.6/cpufreq-cppc-set-the-frequency-used-for-computing-the-capacity.patch b/queue-6.6/cpufreq-cppc-set-the-frequency-used-for-computing-the-capacity.patch new file mode 100644 index 0000000000..8adbd33614 --- /dev/null +++ b/queue-6.6/cpufreq-cppc-set-the-frequency-used-for-computing-the-capacity.patch @@ -0,0 +1,66 @@ +From 5477fa249b56c59c3baa1b237bf083cffa64c84a Mon Sep 17 00:00:00 2001 +From: Vincent Guittot +Date: Mon, 11 Dec 2023 11:48:54 +0100 +Subject: cpufreq/cppc: Set the frequency used for computing the capacity + +From: Vincent Guittot + +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 +Signed-off-by: Ingo Molnar +Tested-by: Pierre Gondois +Acked-by: Sudeep Holla +Acked-by: Viresh Kumar +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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"); + diff --git a/queue-6.6/cpufreq-schedutil-use-a-fixed-reference-frequency.patch b/queue-6.6/cpufreq-schedutil-use-a-fixed-reference-frequency.patch new file mode 100644 index 0000000000..5a2096b90f --- /dev/null +++ b/queue-6.6/cpufreq-schedutil-use-a-fixed-reference-frequency.patch @@ -0,0 +1,77 @@ +From b3edde44e5d4504c23a176819865cd603fd16d6c Mon Sep 17 00:00:00 2001 +From: Vincent Guittot +Date: Mon, 11 Dec 2023 11:48:51 +0100 +Subject: cpufreq/schedutil: Use a fixed reference frequency + +From: Vincent Guittot + +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 +Signed-off-by: Ingo Molnar +Tested-by: Lukasz Luba +Reviewed-by: Lukasz Luba +Reviewed-by: Dietmar Eggemann +Acked-by: Rafael J. Wysocki +Acked-by: Viresh Kumar +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-6.6/cpufreq-use-the-fixed-and-coherent-frequency-for-scaling-capacity.patch b/queue-6.6/cpufreq-use-the-fixed-and-coherent-frequency-for-scaling-capacity.patch new file mode 100644 index 0000000000..da4e0cf263 --- /dev/null +++ b/queue-6.6/cpufreq-use-the-fixed-and-coherent-frequency-for-scaling-capacity.patch @@ -0,0 +1,63 @@ +From 599457ba15403037b489fe536266a3d5f9efaed7 Mon Sep 17 00:00:00 2001 +From: Vincent Guittot +Date: Mon, 11 Dec 2023 11:48:50 +0100 +Subject: cpufreq: Use the fixed and coherent frequency for scaling capacity + +From: Vincent Guittot + +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 . ] + +Signed-off-by: Vincent Guittot +Signed-off-by: Ingo Molnar +Tested-by: Lukasz Luba +Reviewed-by: Lukasz Luba +Acked-by: Viresh Kumar +Acked-by: Rafael J. Wysocki +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-6.6/energy_model-use-a-fixed-reference-frequency.patch b/queue-6.6/energy_model-use-a-fixed-reference-frequency.patch new file mode 100644 index 0000000000..b1342f4267 --- /dev/null +++ b/queue-6.6/energy_model-use-a-fixed-reference-frequency.patch @@ -0,0 +1,59 @@ +From 15cbbd1d317e07b4e5c6aca5d4c5579539a82784 Mon Sep 17 00:00:00 2001 +From: Vincent Guittot +Date: Mon, 11 Dec 2023 11:48:52 +0100 +Subject: energy_model: Use a fixed reference frequency + +From: Vincent Guittot + +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 +Signed-off-by: Ingo Molnar +Tested-by: Lukasz Luba +Reviewed-by: Lukasz Luba +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-6.6/sched-fair-fix-frequency-selection-for-non-invariant-case.patch b/queue-6.6/sched-fair-fix-frequency-selection-for-non-invariant-case.patch new file mode 100644 index 0000000000..9499821619 --- /dev/null +++ b/queue-6.6/sched-fair-fix-frequency-selection-for-non-invariant-case.patch @@ -0,0 +1,60 @@ +From e37617c8e53a1f7fcba6d5e1041f4fd8a2425c27 Mon Sep 17 00:00:00 2001 +From: Vincent Guittot +Date: Sun, 14 Jan 2024 19:36:00 +0100 +Subject: sched/fair: Fix frequency selection for non-invariant case + +From: Vincent Guittot + +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 +Bisected-by: Linus Torvalds +Reported-by: Wyes Karny +Signed-off-by: Vincent Guittot +Signed-off-by: Ingo Molnar +Tested-by: Wyes Karny +Link: https://lore.kernel.org/r/20240114183600.135316-1-vincent.guittot@linaro.org +Signed-off-by: Greg Kroah-Hartman +--- + 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); + } + + /** diff --git a/queue-6.6/sched-topology-add-a-new-arch_scale_freq_ref-method.patch b/queue-6.6/sched-topology-add-a-new-arch_scale_freq_ref-method.patch new file mode 100644 index 0000000000..b46b8f8482 --- /dev/null +++ b/queue-6.6/sched-topology-add-a-new-arch_scale_freq_ref-method.patch @@ -0,0 +1,202 @@ +From 9942cb22ea458c34fa17b73d143ea32d4df1caca Mon Sep 17 00:00:00 2001 +From: Vincent Guittot +Date: Mon, 11 Dec 2023 11:48:49 +0100 +Subject: sched/topology: Add a new arch_scale_freq_ref() method + +From: Vincent Guittot + +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 +Signed-off-by: Ingo Molnar +Tested-by: Lukasz Luba +Reviewed-by: Lukasz Luba +Acked-by: Sudeep Holla +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + + #define CREATE_TRACE_POINTS + #include +@@ -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)); diff --git a/queue-6.6/series b/queue-6.6/series index 470342081e..0b982c5690 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -468,3 +468,11 @@ pm-runtime-simplify-pm_runtime_get_if_active-usage.patch 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 diff --git a/queue-6.6/topology-set-capacity_freq_ref-in-all-cases.patch b/queue-6.6/topology-set-capacity_freq_ref-in-all-cases.patch new file mode 100644 index 0000000000..69ac963efc --- /dev/null +++ b/queue-6.6/topology-set-capacity_freq_ref-in-all-cases.patch @@ -0,0 +1,66 @@ +From 98323e9d70172f1b46d1cadb20d6c54abf62870d Mon Sep 17 00:00:00 2001 +From: Vincent Guittot +Date: Wed, 17 Jan 2024 20:05:45 +0100 +Subject: topology: Set capacity_freq_ref in all cases + +From: Vincent Guittot + +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 +Acked-by: Sudeep Holla +Tested-by: Pierre Gondois +Tested-by: Mark Brown +Tested-by: Paul Barker +Reviewed-by: Dietmar Eggemann +Tested-by: Dietmar Eggemann +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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))