Message ID | 1412749572-29449-3-git-send-email-mturquette@linaro.org |
---|---|
State | New |
Headers | show |
On Wed, Oct 08, 2014 at 07:26:12AM +0100, Mike Turquette wrote: > Move the cpu capacity bits out of arch/arm/ and into the CPUfreq driver. > Not all ARM devices will use CPUfreq and it is unsafe to assume as such > in topology.c. > > Instead, use the new capacity_ops introduced into CFS. If this code is > generic enough then it could be factored and shared via a header to make > it easier for other CPUfreq drivers to take advantage of it. > > Signed-off-by: Mike Turquette <mturquette@linaro.org> > --- > This approach simply builds on top of Morten's series. I am not sure > that the per-cpu method is the best way to go in the future. And if so I > imagine that the CPUfreq core could provide everything except for the > cpu_eff part. > > In general I think that the overlap between CPUfreq drivers and > arch/arm/kernel/topology.c is something that needs to addresssed soon, > as both pieces of code are re-inventing parts of each other. I think it would be easier to deal with the capacity scaling if we split it into two scaling factors (like Vincent proposed by using the existing arch_scale_{cpu,freq}_capacity() functions). Then whatever handles frequency scaling doesn't have to coordinate with uarch scaling. Both would be factors in the range 0..1024. We would just multiply the two scaling factors in fair.c when needed (and shift as necessary). Wouldn't that make it simple enough that we can implement it in a generic way in arch/*/topology.c with a bit of help from the cpufreq framework without involving any drivers directly? Or is that just wishful thinking? :) -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
On Wed, Oct 08, 2014 at 03:37:32PM -0700, Mike Turquette wrote: > It creates a dependency such that any ARM platform that wants to have > frequency-invariant load must use CPUfreq. I don't think we want that > dependency. CPUfreq is a likely back-end for many devices, but not all. > > Consider near-future ARM devices that support ACPI for power management > with no corresponding CPUfreq driver. For example if the CPPC driver is > not hooked up to CPUfreq, platforms using CPPC will not jive with the > ARM arch hook that depends on CPUfreq. Oh crap no, CPPC will not add yet another interface to cpu frequency stuff. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
On Thu, Oct 09, 2014 at 10:25:13AM -0700, Mike Turquette wrote: > Quoting Peter Zijlstra (2014-10-09 02:02:52) > > On Wed, Oct 08, 2014 at 03:37:32PM -0700, Mike Turquette wrote: > > > It creates a dependency such that any ARM platform that wants to have > > > frequency-invariant load must use CPUfreq. I don't think we want that > > > dependency. CPUfreq is a likely back-end for many devices, but not all. > > > > > > Consider near-future ARM devices that support ACPI for power management > > > with no corresponding CPUfreq driver. For example if the CPPC driver is > > > not hooked up to CPUfreq, platforms using CPPC will not jive with the > > > ARM arch hook that depends on CPUfreq. > > > > Oh crap no, CPPC will not add yet another interface to cpu frequency > > stuff. > > Right. > > So let's say the ARM arch hook creates a dependency on CPUfreq to scale > capacity as a function of cpu frequency (as it does in the ARM scale > invariance series). > > Then let's say that a hypothetical ARM platform named "foo" uses CPPC > and not CPUfreq to scale frequency. Foo's implementation of CPPC does > not use any of the full-auto or hw-auto stuff. It allows the OS to > request minimum performance levels and the like. > > In this case, how can foo take advantage of the scale invariant stuff? > > Also, feel free to replace "CPPC" with "anything other than CPUfreq". > The problem is a general one and not specific to CPPC or ACPI. Well answer #1 is that you simply should not ever bypass cpufreq for setting cpu frequencies (be this the existing cpufreq or the future integrated cpufreq). Answer #2 is that if you were allowed to create a second infrastructure and you're not calling the right scheduler hooks right along with it, you're buggy. In short, your problem, not mine. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index 2fe85ff..3951232 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -14,6 +14,8 @@ struct cputopo_arm { }; extern struct cputopo_arm cpu_topology[NR_CPUS]; +extern unsigned long max_raw_capacity; +DECLARE_PER_CPU(unsigned long, cpu_raw_capacity); #define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id) #define topology_core_id(cpu) (cpu_topology[cpu].core_id) diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 5f049ec..a2c9b5f 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -79,8 +79,8 @@ static unsigned long *__cpu_capacity; static unsigned long middle_capacity = 1; -static unsigned long max_raw_capacity = 1; -static DEFINE_PER_CPU(unsigned long, cpu_raw_capacity); +unsigned long max_raw_capacity = 1; +DEFINE_PER_CPU(unsigned long, cpu_raw_capacity); /* * Iterate all CPUs' descriptor in DT and compute the efficiency @@ -175,44 +175,6 @@ static void update_cpu_capacity(unsigned int cpu) cpu, arch_scale_freq_capacity(NULL, cpu)); } -/* - * Scheduler load-tracking scale-invariance - * - * Provides the scheduler with a scale-invariance correction factor that - * compensates for frequency scaling and micro-architecture differences between - * cpus. - */ - -static DEFINE_PER_CPU(atomic_long_t, cpu_curr_freq); -static DEFINE_PER_CPU(atomic_long_t, cpu_max_freq); - -/* cpufreq callback function setting current cpu frequency */ -void arch_scale_set_curr_freq(int cpu, unsigned long freq) -{ - atomic_long_set(&per_cpu(cpu_curr_freq, cpu), freq); -} - -/* cpufreq callback function setting max cpu frequency */ -void arch_scale_set_max_freq(int cpu, unsigned long freq) -{ - atomic_long_set(&per_cpu(cpu_max_freq, cpu), freq); -} - -unsigned long arch_scale_load_capacity(int cpu) -{ - unsigned long curr = atomic_long_read(&per_cpu(cpu_curr_freq, cpu)); - unsigned long max = atomic_long_read(&per_cpu(cpu_max_freq, cpu)); - unsigned long ret; - - if (!max || !per_cpu(cpu_raw_capacity, cpu)) - return SCHED_CAPACITY_SCALE; - - ret = (curr * SCHED_CAPACITY_SCALE) / max; - ret = (ret * per_cpu(cpu_raw_capacity, cpu)) / max_raw_capacity; - - return ret; -} - #else static inline void parse_dt_topology(void) {} static inline void update_cpu_capacity(unsigned int cpuid) {} diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index a46c223..5baffbd 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -31,7 +31,10 @@ #include <linux/slab.h> #include <linux/topology.h> #include <linux/types.h> +#include <linux/sched.h> +#include <linux/rcupdate.h> #include <asm/bL_switcher.h> +#include <asm/topology.h> #include "arm_big_little.h" @@ -533,9 +536,52 @@ static struct notifier_block bL_switcher_notifier = { .notifier_call = bL_cpufreq_switcher_notifier, }; +/* + * Scheduler load-tracking scale-invariance + * + * Provides the scheduler with a scale-invariance correction factor that + * compensates for frequency scaling and micro-architecture differences between + * cpus. + */ + +static DEFINE_PER_CPU(atomic_long_t, cpu_curr_freq); +static DEFINE_PER_CPU(atomic_long_t, cpu_max_freq); + +/* cpufreq callback function setting current cpu frequency */ +void arch_scale_set_curr_freq(int cpu, unsigned long freq) +{ + atomic_long_set(&per_cpu(cpu_curr_freq, cpu), freq); +} + +/* cpufreq callback function setting max cpu frequency */ +void arch_scale_set_max_freq(int cpu, unsigned long freq) +{ + atomic_long_set(&per_cpu(cpu_max_freq, cpu), freq); +} + +/* + * scale_load_capacity returns the current capacity for a given cpu, adjusted + * for micro-architectural differences and taking into accout cpu frequency + */ +unsigned long scale_load_capacity(int cpu) +{ + unsigned long curr = atomic_long_read(&per_cpu(cpu_curr_freq, cpu)); + unsigned long max = atomic_long_read(&per_cpu(cpu_max_freq, cpu)); + unsigned long ret; + + if (!max || !per_cpu(cpu_raw_capacity, cpu)) + return SCHED_CAPACITY_SCALE; + + ret = (curr * SCHED_CAPACITY_SCALE) / max; + ret = (ret * per_cpu(cpu_raw_capacity, cpu)) / max_raw_capacity; + + return ret; +} + int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) { int ret, i; + unsigned long flags; if (arm_bL_ops) { pr_debug("%s: Already registered: %s, exiting\n", __func__, @@ -550,6 +596,11 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) arm_bL_ops = ops; + spin_lock_irqsave(&cfs_capacity_ops.lock, flags); + cfs_capacity_ops.get_capacity = scale_load_capacity; + spin_unlock_irqrestore(&cfs_capacity_ops.lock, flags); + synchronize_rcu(); + ret = bL_switcher_get_enabled(); set_switching_enabled(ret);
Move the cpu capacity bits out of arch/arm/ and into the CPUfreq driver. Not all ARM devices will use CPUfreq and it is unsafe to assume as such in topology.c. Instead, use the new capacity_ops introduced into CFS. If this code is generic enough then it could be factored and shared via a header to make it easier for other CPUfreq drivers to take advantage of it. Signed-off-by: Mike Turquette <mturquette@linaro.org> --- This approach simply builds on top of Morten's series. I am not sure that the per-cpu method is the best way to go in the future. And if so I imagine that the CPUfreq core could provide everything except for the cpu_eff part. In general I think that the overlap between CPUfreq drivers and arch/arm/kernel/topology.c is something that needs to addresssed soon, as both pieces of code are re-inventing parts of each other. arch/arm/include/asm/topology.h | 2 ++ arch/arm/kernel/topology.c | 42 ++------------------------------- drivers/cpufreq/arm_big_little.c | 51 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 40 deletions(-)