]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
arm64/amu: Use capacity_ref_freq() to set AMU ratio
authorVincent Guittot <vincent.guittot@linaro.org>
Mon, 11 Dec 2023 10:48:55 +0000 (11:48 +0100)
committerIngo Molnar <mingo@kernel.org>
Sat, 23 Dec 2023 14:52:36 +0000 (15:52 +0100)
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
arch/arm64/kernel/topology.c
drivers/base/arch_topology.c
include/linux/arch_topology.h

index 817d788cd86669439cf4b55af45214f016cc5efb..1a2c72f3e7f80ed298b1a4a9b6c395febd1d626d 100644 (file)
@@ -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(int cpu)
        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 cpu, u64 max_rate, u64 ref_rate)
        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 cpumask *cpus)
                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;
        }
 
index 1aa76b5c96c2433d3c3f4085af79beea72492169..5aaa0865625d0d10fd02d79b6721c2f6b2863dfe 100644 (file)
@@ -344,6 +344,10 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
        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(void)
        }
 
        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 notifier_block *nb,
 
        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();
index 32c24ff4f2a80736c9616aa181215d97ac5f1c78..a63d61ca55afc82ec865de9de60d8fe667964fef 100644 (file)
@@ -99,6 +99,7 @@ void update_siblings_masks(unsigned int cpu);
 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_ */