With the Frequency Invariance Engine (FIE) being already wired up with sched tick and making use of relevant (core counter and constant counter) AMU counters, getting the current frequency for a given CPU on supported platforms, can be achieved by utilizing the frequency scale factor which reflects an average CPU frequency for the last tick period length. Suggested-by: Ionela Voinescu <ionela.voinescu@xxxxxxx> Signed-off-by: Beata Michalska <beata.michalska@xxxxxxx> Reviewed-by: Sudeep Holla <sudeep.holla@xxxxxxx> --- Notes: Due to [1], if merged, there might be a need to modify the patch to accommodate changes [1] introduces: freq = cpufreq_get_hw_max_freq(cpu) >> SCHED_CAPACITY_SHIFT to freq = per_cpu(capacity_freq_ref, cpu); >> SCHED_CAPACITY_SHIFT [1] https://lore.kernel.org/linux-arm-kernel/20231121154349.GA1938@willie-the-truck/T/#mcb018d076dbce6f60ed2779634a9b6ffe622641e arch/arm64/kernel/topology.c | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 615c1a20129f..ae2445f6e7da 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -17,6 +17,7 @@ #include <linux/cpufreq.h> #include <linux/init.h> #include <linux/percpu.h> +#include <linux/sched/isolation.h> #include <asm/cpu.h> #include <asm/cputype.h> @@ -186,6 +187,44 @@ static void amu_scale_freq_tick(void) this_cpu_write(arch_freq_scale, (unsigned long)scale); } +unsigned int arch_freq_get_on_cpu(int cpu) +{ + unsigned int freq; + u64 scale; + + if (!cpumask_test_cpu(cpu, amu_fie_cpus)) + return 0; + + /* + * For those CPUs that are in full dynticks mode, try an alternative + * source for the counters (and thus freq scale), + * if available for given policy + */ + if (!housekeeping_cpu(cpu, HK_TYPE_TICK)) { + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + int ref_cpu = nr_cpu_ids; + + if (cpumask_intersects(housekeeping_cpumask(HK_TYPE_TICK), + policy->cpus)) + ref_cpu = cpumask_nth_and(cpu, policy->cpus, + housekeeping_cpumask(HK_TYPE_TICK)); + cpufreq_cpu_put(policy); + if (ref_cpu >= nr_cpu_ids) + return 0; + cpu = ref_cpu; + } + + /* + * Reversed computation to the one used to determine + * the arch_freq_scale value + * (see amu_scale_freq_tick for details) + */ + scale = per_cpu(arch_freq_scale, cpu); + freq = cpufreq_get_hw_max_freq(cpu) >> SCHED_CAPACITY_SHIFT; + freq *= scale; + return freq; +} + static struct scale_freq_data amu_sfd = { .source = SCALE_FREQ_SOURCE_ARCH, .set_freq_scale = amu_scale_freq_tick, -- 2.25.1