From c4a6287185179732dfc1e903c195ff90c19f1065 Mon Sep 17 00:00:00 2001 From: Frode Isaksen Date: Tue, 19 Dec 2017 11:15:35 +0000 Subject: This layer provides Energy Aware Scheduling (EAS) patches For the moment only for Renesas R-Car Gen3 SoC's. Can be expanded for other SoC's by setting the machine feature biglittle and provide the relevant EAS patches. Bug-AGL: SPEC-813 Change-Id: I2b5e69c515c33e57be19b30466fe208d7b8ac1a5 Signed-off-by: Frode Isaksen --- ...r-out-energy-model-from-topology-shim-lay.patch | 353 +++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 meta-eas/recipes-kernel/linux/linux-renesas/0070-arm64-Factor-out-energy-model-from-topology-shim-lay.patch (limited to 'meta-eas/recipes-kernel/linux/linux-renesas/0070-arm64-Factor-out-energy-model-from-topology-shim-lay.patch') diff --git a/meta-eas/recipes-kernel/linux/linux-renesas/0070-arm64-Factor-out-energy-model-from-topology-shim-lay.patch b/meta-eas/recipes-kernel/linux/linux-renesas/0070-arm64-Factor-out-energy-model-from-topology-shim-lay.patch new file mode 100644 index 0000000..f6ec5be --- /dev/null +++ b/meta-eas/recipes-kernel/linux/linux-renesas/0070-arm64-Factor-out-energy-model-from-topology-shim-lay.patch @@ -0,0 +1,353 @@ +From 19b9b07f001278198a4d3aae6744213beb1a75bd Mon Sep 17 00:00:00 2001 +From: Dietmar Eggemann +Date: Mon, 15 Aug 2016 22:38:20 +0100 +Subject: [PATCH 70/92] arm64: Factor out energy model from topology shim layer + +To be able to support multiple energy models before we have the +full-fletched dt solution in arm64 (e.g. for platform Arm Juno and +Hisilicon Hikey) factor out the static energy model data and the +appropriate access function into energy_model.h. + +The patch uses of_match_node() to match the compatible string with the +appropriate platform energy model data, i.e. the patch introduces a +dependency to CONFIG_OF_FLATTREE for propagating the energy model data +towards the task scheduler. + +Signed-off-by: Dietmar Eggemann +(cherry picked from commit 6a48e61e481ef4952be07345efb10bc5cd47d22d) +Signed-off-by: Gaku Inami +--- + arch/arm64/kernel/energy_model.h | 177 +++++++++++++++++++++++++++++++++++++++ + arch/arm64/kernel/topology.c | 118 +------------------------- + 2 files changed, 181 insertions(+), 114 deletions(-) + create mode 100644 arch/arm64/kernel/energy_model.h + +diff --git a/arch/arm64/kernel/energy_model.h b/arch/arm64/kernel/energy_model.h +new file mode 100644 +index 0000000..170dd84 +--- /dev/null ++++ b/arch/arm64/kernel/energy_model.h +@@ -0,0 +1,177 @@ ++/* ++ * arch/arm64/kernel/energy_model.h ++ * ++ * Copyright (C) 2016 ARM Ltd. ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ */ ++ ++#include ++ ++/* ++ * Energy cost model data. There are no unit requirements for the data. ++ * Data can be normalized to any reference point, but the normalization ++ * must be consistent. That is, one bogo-joule/watt must be the same ++ * quantity for all data, but we don't care what it is. ++ */ ++ ++/* Juno (r0, r2) */ ++ ++static struct idle_state idle_states_cluster_juno_a53[] = { ++ { .power = 56 }, /* arch_cpu_idle() (active idle) = WFI */ ++ { .power = 56 }, /* WFI */ ++ { .power = 56 }, /* cpu-sleep-0 */ ++ { .power = 17 }, /* cluster-sleep-0 */ ++}; ++ ++static struct idle_state idle_states_cluster_juno_a57[] = { ++ { .power = 65 }, /* arch_cpu_idle() (active idle) = WFI */ ++ { .power = 65 }, /* WFI */ ++ { .power = 65 }, /* cpu-sleep-0 */ ++ { .power = 24 }, /* cluster-sleep-0 */ ++}; ++ ++static struct capacity_state cap_states_cluster_juno_a53[] = { ++ { .cap = 235, .power = 26, }, /* 450 MHz */ ++ { .cap = 303, .power = 30, }, /* 575 MHz */ ++ { .cap = 368, .power = 39, }, /* 700 MHz */ ++ { .cap = 406, .power = 47, }, /* 775 MHz */ ++ { .cap = 447, .power = 57, }, /* 850 Mhz */ ++}; ++ ++static struct capacity_state cap_states_cluster_juno_a57[] = { ++ { .cap = 417, .power = 24, }, /* 450 MHz */ ++ { .cap = 579, .power = 32, }, /* 625 MHz */ ++ { .cap = 744, .power = 43, }, /* 800 MHz */ ++ { .cap = 883, .power = 49, }, /* 950 MHz */ ++ { .cap = 1024, .power = 64, }, /* 1100 MHz */ ++}; ++ ++static struct sched_group_energy energy_cluster_juno_a53 = { ++ .nr_idle_states = ARRAY_SIZE(idle_states_cluster_juno_a53), ++ .idle_states = idle_states_cluster_juno_a53, ++ .nr_cap_states = ARRAY_SIZE(cap_states_cluster_juno_a53), ++ .cap_states = cap_states_cluster_juno_a53, ++}; ++ ++static struct sched_group_energy energy_cluster_juno_a57 = { ++ .nr_idle_states = ARRAY_SIZE(idle_states_cluster_juno_a57), ++ .idle_states = idle_states_cluster_juno_a57, ++ .nr_cap_states = ARRAY_SIZE(cap_states_cluster_juno_a57), ++ .cap_states = cap_states_cluster_juno_a57, ++}; ++ ++static struct idle_state idle_states_core_juno_a53[] = { ++ { .power = 6 }, /* arch_cpu_idle() (active idle) = WFI */ ++ { .power = 6 }, /* WFI */ ++ { .power = 0 }, /* cpu-sleep-0 */ ++ { .power = 0 }, /* cluster-sleep-0 */ ++}; ++ ++static struct idle_state idle_states_core_juno_a57[] = { ++ { .power = 15 }, /* arch_cpu_idle() (active idle) = WFI */ ++ { .power = 15 }, /* WFI */ ++ { .power = 0 }, /* cpu-sleep-0 */ ++ { .power = 0 }, /* cluster-sleep-0 */ ++}; ++ ++static struct capacity_state cap_states_core_juno_a53[] = { ++ { .cap = 235, .power = 33, }, /* 450 MHz */ ++ { .cap = 302, .power = 46, }, /* 575 MHz */ ++ { .cap = 368, .power = 61, }, /* 700 MHz */ ++ { .cap = 406, .power = 76, }, /* 775 MHz */ ++ { .cap = 447, .power = 93, }, /* 850 Mhz */ ++}; ++ ++static struct capacity_state cap_states_core_juno_a57[] = { ++ { .cap = 417, .power = 168, }, /* 450 MHz */ ++ { .cap = 579, .power = 251, }, /* 625 MHz */ ++ { .cap = 744, .power = 359, }, /* 800 MHz */ ++ { .cap = 883, .power = 479, }, /* 950 MHz */ ++ { .cap = 1024, .power = 616, }, /* 1100 MHz */ ++}; ++ ++static struct sched_group_energy energy_core_juno_a53 = { ++ .nr_idle_states = ARRAY_SIZE(idle_states_core_juno_a53), ++ .idle_states = idle_states_core_juno_a53, ++ .nr_cap_states = ARRAY_SIZE(cap_states_core_juno_a53), ++ .cap_states = cap_states_core_juno_a53, ++}; ++ ++static struct sched_group_energy energy_core_juno_a57 = { ++ .nr_idle_states = ARRAY_SIZE(idle_states_core_juno_a57), ++ .idle_states = idle_states_core_juno_a57, ++ .nr_cap_states = ARRAY_SIZE(cap_states_core_juno_a57), ++ .cap_states = cap_states_core_juno_a57, ++}; ++ ++/* An energy model contains core and cluster sched group energy for 2 ++ * clusters (cluster id 0 and 1). set_energy_model() relies on this ++ * feature. It is enforced by a BUG_ON in energy(). ++ */ ++ ++struct energy_model { ++ struct sched_group_energy *core_energy[2]; ++ struct sched_group_energy *cluster_energy[2]; ++}; ++ ++static struct energy_model juno_model = { ++ { &energy_core_juno_a57, &energy_core_juno_a53, }, ++ { &energy_cluster_juno_a57, &energy_cluster_juno_a53, }, ++}; ++ ++static struct of_device_id model_matches[] = { ++ { .compatible = "arm,juno", .data = &juno_model }, ++ {}, ++}; ++ ++static struct sched_group_energy **core_energy, **cluster_energy; ++ ++static void __init set_energy_model(void) ++{ ++ const struct of_device_id *match; ++ struct energy_model *em; ++ ++ BUG_ON(core_energy || cluster_energy); ++ ++ match = of_match_node(model_matches, of_root); ++ ++ if (!match) ++ return; ++ ++ em = (struct energy_model *) match->data; ++ ++ core_energy = em->core_energy; ++ cluster_energy = em->cluster_energy; ++ ++ pr_debug("energy model core[0,1]=[%p,%p] cluster=[%p,%p]\n", ++ em->core_energy[0], em->core_energy[1], ++ em->cluster_energy[0], em->cluster_energy[1]); ++} ++ ++static inline ++struct sched_group_energy *energy(int cpu, struct sched_group_energy **sge) ++{ ++ int idx = cpu_topology[cpu].cluster_id; ++ ++ BUG_ON(idx != 0 && idx != 1); ++ ++ pr_debug("cpu=%d %s%s[%d]=%p\n", cpu, (sge == core_energy) ? ++ "core" : "cluster", "_energy", idx, sge[idx]); ++ ++ return sge[idx]; ++} ++ ++static inline ++const struct sched_group_energy * const cpu_core_energy(int cpu) ++{ ++ return core_energy ? energy(cpu, core_energy) : NULL; ++} ++ ++static inline ++const struct sched_group_energy * const cpu_cluster_energy(int cpu) ++{ ++ return cluster_energy ? energy(cpu, cluster_energy) : NULL; ++} +diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c +index 761fcb6..baaab53 100644 +--- a/arch/arm64/kernel/topology.c ++++ b/arch/arm64/kernel/topology.c +@@ -26,6 +26,8 @@ + #include + #include + ++#include "energy_model.h" ++ + static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; + static DEFINE_MUTEX(cpu_scale_mutex); + static bool asym_cpucap; +@@ -503,6 +505,8 @@ static int __init parse_dt_topology(void) + goto out; + } + ++ set_energy_model(); ++ + ret = parse_cluster(map, 0); + if (ret != 0) + goto out_map; +@@ -530,120 +534,6 @@ static int __init parse_dt_topology(void) + struct cpu_topology cpu_topology[NR_CPUS]; + EXPORT_SYMBOL_GPL(cpu_topology); + +-/* +- * ARM JUNO specific energy cost model data. There are no unit requirements for +- * the data. Data can be normalized to any reference point, but the +- * normalization must be consistent. That is, one bogo-joule/watt must be the +- * same quantity for all data, but we don't care what it is. +- */ +- +-static struct idle_state idle_states_cluster_a53[] = { +- { .power = 56 }, /* arch_cpu_idle() (active idle) = WFI */ +- { .power = 56 }, /* WFI */ +- { .power = 56 }, /* cpu-sleep-0 */ +- { .power = 17 }, /* cluster-sleep-0 */ +-}; +- +-static struct idle_state idle_states_cluster_a57[] = { +- { .power = 65 }, /* arch_cpu_idle() (active idle) = WFI */ +- { .power = 65 }, /* WFI */ +- { .power = 65 }, /* cpu-sleep-0 */ +- { .power = 24 }, /* cluster-sleep-0 */ +-}; +- +-static struct capacity_state cap_states_cluster_a53[] = { +- /* Power per cluster */ +- { .cap = 235, .power = 26, }, /* 450 MHz */ +- { .cap = 303, .power = 30, }, /* 575 MHz */ +- { .cap = 368, .power = 39, }, /* 700 MHz */ +- { .cap = 406, .power = 47, }, /* 775 MHz */ +- { .cap = 447, .power = 57, }, /* 850 Mhz */ +-}; +- +-static struct capacity_state cap_states_cluster_a57[] = { +- /* Power per cluster */ +- { .cap = 417, .power = 24, }, /* 450 MHz */ +- { .cap = 579, .power = 32, }, /* 625 MHz */ +- { .cap = 744, .power = 43, }, /* 800 MHz */ +- { .cap = 883, .power = 49, }, /* 950 MHz */ +- { .cap = 1024, .power = 64, }, /* 1100 MHz */ +-}; +- +-static struct sched_group_energy energy_cluster_a53 = { +- .nr_idle_states = ARRAY_SIZE(idle_states_cluster_a53), +- .idle_states = idle_states_cluster_a53, +- .nr_cap_states = ARRAY_SIZE(cap_states_cluster_a53), +- .cap_states = cap_states_cluster_a53, +-}; +- +-static struct sched_group_energy energy_cluster_a57 = { +- .nr_idle_states = ARRAY_SIZE(idle_states_cluster_a57), +- .idle_states = idle_states_cluster_a57, +- .nr_cap_states = ARRAY_SIZE(cap_states_cluster_a57), +- .cap_states = cap_states_cluster_a57, +-}; +- +-static struct idle_state idle_states_core_a53[] = { +- { .power = 6 }, /* arch_cpu_idle() (active idle) = WFI */ +- { .power = 6 }, /* WFI */ +- { .power = 0 }, /* cpu-sleep-0 */ +- { .power = 0 }, /* cluster-sleep-0 */ +-}; +- +-static struct idle_state idle_states_core_a57[] = { +- { .power = 15 }, /* arch_cpu_idle() (active idle) = WFI */ +- { .power = 15 }, /* WFI */ +- { .power = 0 }, /* cpu-sleep-0 */ +- { .power = 0 }, /* cluster-sleep-0 */ +-}; +- +-static struct capacity_state cap_states_core_a53[] = { +- /* Power per cpu */ +- { .cap = 235, .power = 33, }, /* 450 MHz */ +- { .cap = 302, .power = 46, }, /* 575 MHz */ +- { .cap = 368, .power = 61, }, /* 700 MHz */ +- { .cap = 406, .power = 76, }, /* 775 MHz */ +- { .cap = 447, .power = 93, }, /* 850 Mhz */ +-}; +- +-static struct capacity_state cap_states_core_a57[] = { +- /* Power per cpu */ +- { .cap = 417, .power = 168, }, /* 450 MHz */ +- { .cap = 579, .power = 251, }, /* 625 MHz */ +- { .cap = 744, .power = 359, }, /* 800 MHz */ +- { .cap = 883, .power = 479, }, /* 950 MHz */ +- { .cap = 1024, .power = 616, }, /* 1100 MHz */ +-}; +- +-static struct sched_group_energy energy_core_a53 = { +- .nr_idle_states = ARRAY_SIZE(idle_states_core_a53), +- .idle_states = idle_states_core_a53, +- .nr_cap_states = ARRAY_SIZE(cap_states_core_a53), +- .cap_states = cap_states_core_a53, +-}; +- +-static struct sched_group_energy energy_core_a57 = { +- .nr_idle_states = ARRAY_SIZE(idle_states_core_a57), +- .idle_states = idle_states_core_a57, +- .nr_cap_states = ARRAY_SIZE(cap_states_core_a57), +- .cap_states = cap_states_core_a57, +-}; +- +-/* sd energy functions */ +-static inline +-const struct sched_group_energy * const cpu_cluster_energy(int cpu) +-{ +- return cpu_topology[cpu].cluster_id ? &energy_cluster_a53 : +- &energy_cluster_a57; +-} +- +-static inline +-const struct sched_group_energy * const cpu_core_energy(int cpu) +-{ +- return cpu_topology[cpu].cluster_id ? &energy_core_a53 : +- &energy_core_a57; +-} +- + const struct cpumask *cpu_coregroup_mask(int cpu) + { + return &cpu_topology[cpu].core_sibling; +-- +1.9.1 + -- cgit 1.2.3-korg