Message ID | 20230901130312.247719-3-vincent.guittot@linaro.org |
---|---|
State | New |
Headers | show |
Series | consolidate and cleanup CPU capacity | expand |
Hi Vincent, On 9/1/23 14:03, Vincent Guittot wrote: > Create a new method to get a unique and fixed max frequency. Currently > cpuinfo.max_freq or last item 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 betwen cpufreq and energy model. > > We need to save the max 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. I do like this 'kHz' change. We also use kHz in the EM, so better aligned now. > > Signed-off-by: Vincent Guittot <vincent.guittot@linaro.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 | 9 +++------ > include/linux/arch_topology.h | 7 +++++++ > 5 files changed, 13 insertions(+), 6 deletions(-) > > diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h > index c7d2510e5a78..853c4f81ba4a 100644 > --- 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 */ > diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h > index 9fab663dd2de..a323b109b9c4 100644 > --- 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 > diff --git a/arch/riscv/include/asm/topology.h b/arch/riscv/include/asm/topology.h > index e316ab3b77f3..61183688bdd5 100644 > --- 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 > diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c > index b741b5ba82bd..75fa67477a9d 100644 > --- a/drivers/base/arch_topology.c > +++ b/drivers/base/arch_topology.c > @@ -26,7 +26,7 @@ > 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, freq_factor) = 1; Why it's not static now? > > static bool supports_scale_freq_counters(const struct cpumask *cpus) > { > @@ -183,10 +183,7 @@ void topology_update_thermal_pressure(const struct cpumask *cpus, > > 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 > @@ -411,7 +408,7 @@ 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) > - per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000; > + per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq; > > if (cpumask_empty(cpus_to_visit)) { > topology_normalize_cpu_scale(); > diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h > index a07b510e7dc5..7a2dba9c3dc0 100644 > --- a/include/linux/arch_topology.h > +++ b/include/linux/arch_topology.h > @@ -27,6 +27,13 @@ static inline unsigned long topology_get_cpu_scale(int cpu) > > void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity); > > +DECLARE_PER_CPU(unsigned long, freq_factor); > + > +static inline unsigned long topology_get_freq_ref(int cpu) > +{ > + return per_cpu(freq_factor, cpu); > +} > + > DECLARE_PER_CPU(unsigned long, arch_freq_scale); > > static inline unsigned long topology_get_freq_scale(int cpu) Apart from that 'static' missing, that looks good. Regards, Lukasz
On 01/09/2023 15:03, Vincent Guittot wrote: > Create a new method to get a unique and fixed max frequency. Currently > cpuinfo.max_freq or last item of performance domain are used as the max ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ IMHO better `highest (or last) performance state` (struct em_perf_state) ... maybe easier to grasp? [...]
On Mon, 4 Sept 2023 at 14:34, Lukasz Luba <lukasz.luba@arm.com> wrote: > > Hi Vincent, > > > On 9/1/23 14:03, Vincent Guittot wrote: > > Create a new method to get a unique and fixed max frequency. Currently > > cpuinfo.max_freq or last item 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 betwen cpufreq and energy model. > > > > We need to save the max 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. > > I do like this 'kHz' change. We also use kHz in the EM, so better > aligned now. > > > > > Signed-off-by: Vincent Guittot <vincent.guittot@linaro.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 | 9 +++------ > > include/linux/arch_topology.h | 7 +++++++ > > 5 files changed, 13 insertions(+), 6 deletions(-) > > > > diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h > > index c7d2510e5a78..853c4f81ba4a 100644 > > --- 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 */ > > diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h > > index 9fab663dd2de..a323b109b9c4 100644 > > --- 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 > > diff --git a/arch/riscv/include/asm/topology.h b/arch/riscv/include/asm/topology.h > > index e316ab3b77f3..61183688bdd5 100644 > > --- 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 > > diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c > > index b741b5ba82bd..75fa67477a9d 100644 > > --- a/drivers/base/arch_topology.c > > +++ b/drivers/base/arch_topology.c > > @@ -26,7 +26,7 @@ > > 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, freq_factor) = 1; > > Why it's not static now? it can be accessed outside with inline function like cpu_scale and arch_freq_scale > > > > > static bool supports_scale_freq_counters(const struct cpumask *cpus) > > { > > @@ -183,10 +183,7 @@ void topology_update_thermal_pressure(const struct cpumask *cpus, > > > > 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 > > @@ -411,7 +408,7 @@ 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) > > - per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000; > > + per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq; > > > > if (cpumask_empty(cpus_to_visit)) { > > topology_normalize_cpu_scale(); > > diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h > > index a07b510e7dc5..7a2dba9c3dc0 100644 > > --- a/include/linux/arch_topology.h > > +++ b/include/linux/arch_topology.h > > @@ -27,6 +27,13 @@ static inline unsigned long topology_get_cpu_scale(int cpu) > > > > void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity); > > > > +DECLARE_PER_CPU(unsigned long, freq_factor); > > + > > +static inline unsigned long topology_get_freq_ref(int cpu) > > +{ > > + return per_cpu(freq_factor, cpu); > > +} > > + > > DECLARE_PER_CPU(unsigned long, arch_freq_scale); > > > > static inline unsigned long topology_get_freq_scale(int cpu) > > Apart from that 'static' missing, that looks good. > > Regards, > Lukasz
Hi Vincent, On Friday 01 Sep 2023 at 15:03:10 (+0200), Vincent Guittot wrote: > Create a new method to get a unique and fixed max frequency. Currently > cpuinfo.max_freq or last item 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 betwen cpufreq and energy model. > > We need to save the max 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. > > Signed-off-by: Vincent Guittot <vincent.guittot@linaro.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 | 9 +++------ > include/linux/arch_topology.h | 7 +++++++ > 5 files changed, 13 insertions(+), 6 deletions(-) > > diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h > index c7d2510e5a78..853c4f81ba4a 100644 > --- 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 The "reference" frequency or performance of a CPU has a specific meaning in the ACPI specification as a fixed frequency of a constant clock and its associated performance level, usually used for performance to frequency conversions. This is not guaranteed to be the maximum performance/frequency and it's definitely not the case for arm systems where this is tied to the system timer - 1-50Mhz. So I believe it might create some confusion to call this "reference" frequency. Any reason for not calling it arch_scale_freq_max? I know not all max frequencies are equal :) but it would still drive the point that this is intended to act as a chosen maximum for the scheduler's use, especially if there's a well place comment. > #endif > > /* Replace task scheduler's default cpu-invariant accounting */ > diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h > index 9fab663dd2de..a323b109b9c4 100644 > --- 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 > diff --git a/arch/riscv/include/asm/topology.h b/arch/riscv/include/asm/topology.h > index e316ab3b77f3..61183688bdd5 100644 > --- 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 > diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c > index b741b5ba82bd..75fa67477a9d 100644 > --- a/drivers/base/arch_topology.c > +++ b/drivers/base/arch_topology.c > @@ -26,7 +26,7 @@ > 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, freq_factor) = 1; Given its new wider use, it might be good for this to get a more relevant name as well. Previously freq_factor made sense for its role in using the dmips/mhz values to obtain CPU capacities. But if this is now returned from arch_scale_freq_ref() it would be more difficult still to easily understand what this value is supposed to reflect, when reading the function name or the per-cpu variable name alone. Thanks, Ionela. > > static bool supports_scale_freq_counters(const struct cpumask *cpus) > { > @@ -183,10 +183,7 @@ void topology_update_thermal_pressure(const struct cpumask *cpus, > > 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 > @@ -411,7 +408,7 @@ 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) > - per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000; > + per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq; > > if (cpumask_empty(cpus_to_visit)) { > topology_normalize_cpu_scale(); > diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h > index a07b510e7dc5..7a2dba9c3dc0 100644 > --- a/include/linux/arch_topology.h > +++ b/include/linux/arch_topology.h > @@ -27,6 +27,13 @@ static inline unsigned long topology_get_cpu_scale(int cpu) > > void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity); > > +DECLARE_PER_CPU(unsigned long, freq_factor); > + > +static inline unsigned long topology_get_freq_ref(int cpu) > +{ > + return per_cpu(freq_factor, cpu); > +} > + > DECLARE_PER_CPU(unsigned long, arch_freq_scale); > > static inline unsigned long topology_get_freq_scale(int cpu) > -- > 2.34.1 > >
On Thu, 21 Sept 2023 at 11:00, Ionela Voinescu <ionela.voinescu@arm.com> wrote: > > Hi Vincent, > > On Friday 01 Sep 2023 at 15:03:10 (+0200), Vincent Guittot wrote: > > Create a new method to get a unique and fixed max frequency. Currently > > cpuinfo.max_freq or last item 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 betwen cpufreq and energy model. > > > > We need to save the max 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. > > > > Signed-off-by: Vincent Guittot <vincent.guittot@linaro.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 | 9 +++------ > > include/linux/arch_topology.h | 7 +++++++ > > 5 files changed, 13 insertions(+), 6 deletions(-) > > > > diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h > > index c7d2510e5a78..853c4f81ba4a 100644 > > --- 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 > > The "reference" frequency or performance of a CPU has a specific meaning > in the ACPI specification as a fixed frequency of a constant clock and its > associated performance level, usually used for performance to frequency > conversions. This is not guaranteed to be the maximum > performance/frequency and it's definitely not the case for arm systems > where this is tied to the system timer - 1-50Mhz. > > So I believe it might create some confusion to call this "reference" > frequency. > > Any reason for not calling it arch_scale_freq_max? I know not all max > frequencies are equal :) but it would still drive the point that this is > intended to act as a chosen maximum for the scheduler's use, especially > if there's a well place comment. I don't like max_freq because most will assume this is the cpufreq max value whereas this value is the actual frequency that has been used as a reference for computing the cpu capacity and should be used as the reference for any further computation > > > #endif > > > > /* Replace task scheduler's default cpu-invariant accounting */ > > diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h > > index 9fab663dd2de..a323b109b9c4 100644 > > --- 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 > > diff --git a/arch/riscv/include/asm/topology.h b/arch/riscv/include/asm/topology.h > > index e316ab3b77f3..61183688bdd5 100644 > > --- 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 > > diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c > > index b741b5ba82bd..75fa67477a9d 100644 > > --- a/drivers/base/arch_topology.c > > +++ b/drivers/base/arch_topology.c > > @@ -26,7 +26,7 @@ > > 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, freq_factor) = 1; > > Given its new wider use, it might be good for this to get a more > relevant name as well. Previously freq_factor made sense for its role > in using the dmips/mhz values to obtain CPU capacities. But if this is > now returned from arch_scale_freq_ref() it would be more difficult still > to easily understand what this value is supposed to reflect, when > reading the function name or the per-cpu variable name alone. As long as it was used internally behind a function i didn't see a problem but I will probably have cppc_cpufreq to set it while registering its Energy model so I will change it > > Thanks, > Ionela. > > > > > static bool supports_scale_freq_counters(const struct cpumask *cpus) > > { > > @@ -183,10 +183,7 @@ void topology_update_thermal_pressure(const struct cpumask *cpus, > > > > 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 > > @@ -411,7 +408,7 @@ 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) > > - per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000; > > + per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq; > > > > if (cpumask_empty(cpus_to_visit)) { > > topology_normalize_cpu_scale(); > > diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h > > index a07b510e7dc5..7a2dba9c3dc0 100644 > > --- a/include/linux/arch_topology.h > > +++ b/include/linux/arch_topology.h > > @@ -27,6 +27,13 @@ static inline unsigned long topology_get_cpu_scale(int cpu) > > > > void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity); > > > > +DECLARE_PER_CPU(unsigned long, freq_factor); > > + > > +static inline unsigned long topology_get_freq_ref(int cpu) > > +{ > > + return per_cpu(freq_factor, cpu); > > +} > > + > > DECLARE_PER_CPU(unsigned long, arch_freq_scale); > > > > static inline unsigned long topology_get_freq_scale(int cpu) > > -- > > 2.34.1 > > > >
diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index c7d2510e5a78..853c4f81ba4a 100644 --- 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 */ diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h index 9fab663dd2de..a323b109b9c4 100644 --- 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 diff --git a/arch/riscv/include/asm/topology.h b/arch/riscv/include/asm/topology.h index e316ab3b77f3..61183688bdd5 100644 --- 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 diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index b741b5ba82bd..75fa67477a9d 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -26,7 +26,7 @@ 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, freq_factor) = 1; static bool supports_scale_freq_counters(const struct cpumask *cpus) { @@ -183,10 +183,7 @@ void topology_update_thermal_pressure(const struct cpumask *cpus, 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 @@ -411,7 +408,7 @@ 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) - per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq / 1000; + per_cpu(freq_factor, cpu) = policy->cpuinfo.max_freq; if (cpumask_empty(cpus_to_visit)) { topology_normalize_cpu_scale(); diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index a07b510e7dc5..7a2dba9c3dc0 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -27,6 +27,13 @@ static inline unsigned long topology_get_cpu_scale(int cpu) void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity); +DECLARE_PER_CPU(unsigned long, freq_factor); + +static inline unsigned long topology_get_freq_ref(int cpu) +{ + return per_cpu(freq_factor, cpu); +} + DECLARE_PER_CPU(unsigned long, arch_freq_scale); static inline unsigned long topology_get_freq_scale(int cpu)
Create a new method to get a unique and fixed max frequency. Currently cpuinfo.max_freq or last item 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 betwen cpufreq and energy model. We need to save the max 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. Signed-off-by: Vincent Guittot <vincent.guittot@linaro.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 | 9 +++------ include/linux/arch_topology.h | 7 +++++++ 5 files changed, 13 insertions(+), 6 deletions(-)