arm64: Cpu invariant scheduler load-tracking and capacity support
authorJuri Lelli <juri.lelli@arm.com>
Thu, 30 Apr 2015 10:53:48 +0000 (11:53 +0100)
committerAmit Pundir <amit.pundir@linaro.org>
Wed, 14 Sep 2016 09:18:50 +0000 (14:48 +0530)
Provides the scheduler with a cpu scaling correction factor for more
accurate load-tracking and cpu capacity handling.

The Energy Model (EM) (in fact the capacity value of the last element
of the capacity states vector of the core (MC) level sched_group_energy
structure) is used as the source for this cpu scaling factor.

The cpu capacity value depends on the micro-architecture and the
maximum frequency of the cpu.

The maximum frequency part should not be confused with the frequency
invariant scheduler load-tracking support which deals with frequency
related scaling due to DFVS functionality.

Signed-off-by: Juri Lelli <juri.lelli@arm.com>
Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
arch/arm64/include/asm/topology.h
arch/arm64/kernel/topology.c

index 72c47c3fa7b3b882bfaecd2f300e00f94b14a498..9370a336c9341287d00b492556c0f8cd13f46eb1 100644 (file)
@@ -22,11 +22,13 @@ void init_cpu_topology(void);
 void store_cpu_topology(unsigned int cpuid);
 const struct cpumask *cpu_coregroup_mask(int cpu);
 
+struct sched_domain;
 #ifdef CONFIG_CPU_FREQ
 #define arch_scale_freq_capacity cpufreq_scale_freq_capacity
-struct sched_domain;
 extern unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu);
 #endif
+#define arch_scale_cpu_capacity scale_cpu_capacity
+extern unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu);
 
 #include <asm-generic/topology.h>
 
index 694f6deedbab89509c26d9c9d05d8e6911cf0fbd..fb99a6735fd4ebfee2c997aafbc9b930aaa78ada 100644 (file)
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
+static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
+
+unsigned long scale_cpu_capacity(struct sched_domain *sd, int cpu)
+{
+       return per_cpu(cpu_scale, cpu);
+}
+
+static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
+{
+       per_cpu(cpu_scale, cpu) = capacity;
+}
+
 static int __init get_cpu_for_node(struct device_node *node)
 {
        struct device_node *cpu_node;
@@ -211,6 +223,35 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
        return &cpu_topology[cpu].core_sibling;
 }
 
+static inline int cpu_corepower_flags(void)
+{
+       return SD_SHARE_PKG_RESOURCES  | SD_SHARE_POWERDOMAIN | \
+              SD_SHARE_CAP_STATES;
+}
+
+static struct sched_domain_topology_level arm64_topology[] = {
+#ifdef CONFIG_SCHED_MC
+       { cpu_coregroup_mask, cpu_corepower_flags, cpu_core_energy, SD_INIT_NAME(MC) },
+#endif
+       { cpu_cpu_mask, NULL, cpu_cluster_energy, SD_INIT_NAME(DIE) },
+       { NULL, },
+};
+
+static void update_cpu_capacity(unsigned int cpu)
+{
+       unsigned long capacity = SCHED_CAPACITY_SCALE;
+
+       if (cpu_core_energy(cpu)) {
+               int max_cap_idx = cpu_core_energy(cpu)->nr_cap_states - 1;
+               capacity = cpu_core_energy(cpu)->cap_states[max_cap_idx].cap;
+       }
+
+       set_capacity_scale(cpu, capacity);
+
+       pr_info("CPU%d: update cpu_capacity %lu\n",
+               cpu, arch_scale_cpu_capacity(NULL, cpu));
+}
+
 static void update_siblings_masks(unsigned int cpuid)
 {
        struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
@@ -272,6 +313,7 @@ void store_cpu_topology(unsigned int cpuid)
 
 topology_populated:
        update_siblings_masks(cpuid);
+       update_cpu_capacity(cpuid);
 }
 
 static void __init reset_cpu_topology(void)