aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorten Rasmussen <Morten.Rasmussen@arm.com>2014-09-22 17:24:03 +0100
committerRobin Randhawa <robin.randhawa@arm.com>2015-04-09 12:26:12 +0100
commit2c58b6ac7774436ccbd350109155ffa011253867 (patch)
treeb48624a4bb02668ee41fe3e8f1690e0b85279817
parent2fa7ff2224aab888dda4a215c37d271980d22376 (diff)
downloadkernel-2c58b6ac7774436ccbd350109155ffa011253867.tar.gz
arm: Frequency invariant scheduler load-tracking support
Implements arch-specific function to provide the scheduler with a frequency scaling correction factor for more accurate load-tracking. The factor is: current_freq(cpu) * SCHED_CAPACITY_SCALE / max_freq(cpu) This implementation only provides frequency invariance. No micro-architecture invariance yet. Cc: Russell King <linux@arm.linux.org.uk> Signed-off-by: Morten Rasmussen <morten.rasmussen@arm.com>
-rw-r--r--arch/arm/kernel/topology.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 2310bfb..dcfc484 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -169,6 +169,39 @@ static void update_cpu_capacity(unsigned int cpu)
cpu, arch_scale_cpu_capacity(NULL, cpu));
}
+/*
+ * Scheduler load-tracking scale-invariance
+ *
+ * Provides the scheduler with a scale-invariance correction factor that
+ * compensates for frequency scaling.
+ */
+
+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_freq_capacity(struct sched_domain *sd, 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));
+
+ if (!curr || !max)
+ return SCHED_CAPACITY_SCALE;
+
+ return (curr * SCHED_CAPACITY_SCALE) / max;
+}
+
#else
static inline void parse_dt_topology(void) {}
static inline void update_cpu_capacity(unsigned int cpuid) {}