On 15/10/2021 16:45, Lukasz Luba wrote: > The thermal pressure is a mechanism which is used for providing > information about reduced CPU performance to the scheduler. Usually code > has to convert the value from frequency units into capacity units, > which are understandable by the scheduler. Create a common conversion code > which can be just used via a handy API. > > Signed-off-by: Lukasz Luba <lukasz.luba@xxxxxxx> > --- > arch/arm/include/asm/topology.h | 1 + > arch/arm64/include/asm/topology.h | 1 + > drivers/base/arch_topology.c | 36 ++++++++++++++++++++++++++++++- > include/linux/arch_topology.h | 3 +++ > include/linux/sched/topology.h | 7 ++++++ > 5 files changed, 47 insertions(+), 1 deletion(-) > > diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h > index 470299ee2fba..aee6c456c085 100644 > --- a/arch/arm/include/asm/topology.h > +++ b/arch/arm/include/asm/topology.h > @@ -24,6 +24,7 @@ > /* Replace task scheduler's default thermal pressure API */ > #define arch_scale_thermal_pressure topology_get_thermal_pressure > #define arch_set_thermal_pressure topology_set_thermal_pressure > +#define arch_thermal_pressure_update topology_thermal_pressure_update > > #else > > diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h > index ec2db3419c41..c997015402bc 100644 > --- a/arch/arm64/include/asm/topology.h > +++ b/arch/arm64/include/asm/topology.h > @@ -33,6 +33,7 @@ void update_freq_counters_refs(void); > /* Replace task scheduler's default thermal pressure API */ > #define arch_scale_thermal_pressure topology_get_thermal_pressure > #define arch_set_thermal_pressure topology_set_thermal_pressure > +#define arch_thermal_pressure_update topology_thermal_pressure_update s/thermal_pressure_update/update_thermal_pressure ? The scheme seems to be {arch|topology}_*foo*_thermal_pressure But ... > > #include <asm-generic/topology.h> > > diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c > index 43407665918f..1fa28b5afdb2 100644 > --- a/drivers/base/arch_topology.c > +++ b/drivers/base/arch_topology.c > @@ -25,6 +25,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; > > static bool supports_scale_freq_counters(const struct cpumask *cpus) > { > @@ -168,6 +169,40 @@ void topology_set_thermal_pressure(const struct cpumask *cpus, > } > EXPORT_SYMBOL_GPL(topology_set_thermal_pressure); > > +/** > + * topology_thermal_pressure_update() - Update thermal pressure for CPUs > + * @cpus : The related CPUs for which capacity has been reduced > + * @capped_freq : The maximum allowed frequency that CPUs can run at > + * > + * Update the value of thermal pressure for all @cpus in the mask. The > + * cpumask should include all (online+offline) affected CPUs, to avoid > + * operating on stale data when hot-plug is used for some CPUs. The > + * @capped_freq must be less or equal to the max possible frequency and > + * reflects the currently allowed max CPUs frequency due to thermal capping. > + * The @capped_freq must be provided in kHz. > + */ > +void topology_thermal_pressure_update(const struct cpumask *cpus, > + unsigned long capped_freq) > +{ ... why not just s/unsigned long th_pressure/unsigned long capped_freq in existing topology_set_thermal_pressure() and move code the frequency/capacity conversion in there? The patch set will become considerably smaller. void topology_set_thermal_pressure(const struct cpumask *cpus, - unsigned long th_pressure) + unsigned long capped_freq) { + unsigned long max_capacity, capacity; int cpu; - for_each_cpu(cpu, cpus) - WRITE_ONCE(per_cpu(thermal_pressure, cpu), th_pressure); + if (!cpus) + return; + + cpu = cpumask_first(cpus); + max_capacity = arch_scale_cpu_capacity(cpu); + + /* Convert to MHz scale which is used in 'freq_factor' */ + capped_freq /= 1000; + + capacity = mult_frac(capped_freq, max_capacity, + per_cpu(freq_factor, cpu)); + + for_each_cpu(cpu, cpus) { + WRITE_ONCE(per_cpu(thermal_pressure, cpu), + max_capacity - capacity); + } } EXPORT_SYMBOL_GPL(topology_set_thermal_pressure); And a user like [drivers/thermal/cpufreq_cooling.c] can call arch_set_thermal_pressure(cpus, frequency). [...]