diff --git a/kernel/sched/energy.c b/kernel/sched/energy.c index b4764309dac4..1b913e364306 100755 --- a/kernel/sched/energy.c +++ b/kernel/sched/energy.c @@ -51,6 +51,7 @@ static void free_resources(void) } } static bool sge_ready; +static bool freq_energy_model; void check_max_cap_vs_cpu_scale(int cpu, struct sched_group_energy *sge) { @@ -62,7 +63,7 @@ void check_max_cap_vs_cpu_scale(int cpu, struct sched_group_energy *sge) if (max_cap == cpu_scale) return; - pr_debug("CPU%d max energy model capacity=%ld != cpu_scale=%ld\n", cpu, + pr_warn("CPU%d max energy model capacity=%ld != cpu_scale=%ld\n", cpu, max_cap, cpu_scale); } @@ -76,9 +77,6 @@ void init_sched_energy_costs(void) int sd_level, i, nstates, cpu; const __be32 *val; - if (!sched_is_energy_aware()) - return; - for_each_possible_cpu(cpu) { cn = of_get_cpu_node(cpu, NULL); if (!cn) { @@ -90,6 +88,9 @@ void init_sched_energy_costs(void) pr_warn("CPU device node has no sched-energy-costs\n"); return; } + /* Check if the energy model contains frequency/power values */ + if (of_find_property(cn, "freq-energy-model", NULL)) + freq_energy_model = true; for_each_possible_sd_level(sd_level) { cp = of_parse_phandle(cn, "sched-energy-costs", sd_level); @@ -104,21 +105,25 @@ void init_sched_energy_costs(void) sge = kcalloc(1, sizeof(struct sched_group_energy), GFP_NOWAIT); - if (!sge) - goto out; nstates = (prop->length / sizeof(u32)) / 2; cap_states = kcalloc(nstates, sizeof(struct capacity_state), GFP_NOWAIT); - if (!cap_states) { - kfree(sge); - goto out; - } for (i = 0, val = prop->value; i < nstates; i++) { - cap_states[i].cap = SCHED_CAPACITY_SCALE; - cap_states[i].frequency = be32_to_cpup(val++); + if (freq_energy_model) { + /* + * Capacity values will be calculated later using + * frequency reported by OPP driver and cpu_uarch_scale + * values. + */ + cap_states[i].frequency = be32_to_cpup(val++); + cap_states[i].cap = 0; + } else { + cap_states[i].frequency = 0; + cap_states[i].cap = be32_to_cpup(val++); + } cap_states[i].power = be32_to_cpup(val++); } @@ -128,8 +133,6 @@ void init_sched_energy_costs(void) prop = of_find_property(cp, "idle-cost-data", NULL); if (!prop || !prop->value) { pr_warn("No idle-cost data, skipping sched_energy init\n"); - kfree(sge); - kfree(cap_states); goto out; } @@ -137,11 +140,6 @@ void init_sched_energy_costs(void) idle_states = kcalloc(nstates, sizeof(struct idle_state), GFP_NOWAIT); - if (!idle_states) { - kfree(sge); - kfree(cap_states); - goto out; - } for (i = 0, val = prop->value; i < nstates; i++) idle_states[i].power = be32_to_cpup(val++); @@ -151,10 +149,9 @@ void init_sched_energy_costs(void) sge_array[cpu][sd_level] = sge; } - - check_max_cap_vs_cpu_scale(cpu, sge_array[cpu][SD_LEVEL0]); + if (!freq_energy_model) + check_max_cap_vs_cpu_scale(cpu, sge_array[cpu][SD_LEVEL0]); } - sge_ready = true; pr_info("Sched-energy-costs installed from DT\n"); return; @@ -165,17 +162,16 @@ out: static int sched_energy_probe(struct platform_device *pdev) { - unsigned long max_freq = 0; - int max_efficiency = INT_MIN; int cpu; unsigned long *max_frequencies = NULL; int ret; - if (!sched_is_energy_aware()) - return 0; if (!sge_ready) return -EPROBE_DEFER; + if (!energy_aware() || !freq_energy_model) + return 0; + max_frequencies = kmalloc_array(nr_cpu_ids, sizeof(unsigned long), GFP_KERNEL); if (!max_frequencies) { @@ -190,9 +186,6 @@ static int sched_energy_probe(struct platform_device *pdev) for_each_possible_cpu(cpu) { struct device *cpu_dev; struct dev_pm_opp *opp; - int efficiency = topology_get_cpu_efficiency(cpu); - - max_efficiency = max(efficiency, max_efficiency); cpu_dev = get_cpu_device(cpu); if (IS_ERR_OR_NULL(cpu_dev)) { @@ -217,19 +210,13 @@ static int sched_energy_probe(struct platform_device *pdev) /* Convert HZ to KHZ */ max_frequencies[cpu] /= 1000; - max_freq = max(max_freq, max_frequencies[cpu]); } /* update capacity in energy model */ for_each_possible_cpu(cpu) { unsigned long cpu_max_cap; struct sched_group_energy *sge_l0, *sge; - int efficiency = topology_get_cpu_efficiency(cpu); - - cpu_max_cap = DIV_ROUND_UP(SCHED_CAPACITY_SCALE * - max_frequencies[cpu], max_freq); - cpu_max_cap = DIV_ROUND_UP(cpu_max_cap * efficiency, - max_efficiency); + cpu_max_cap = topology_get_cpu_scale(NULL, cpu); /* * All the cap_states have same frequency table so use @@ -261,7 +248,6 @@ static int sched_energy_probe(struct platform_device *pdev) break; sge->cap_states[i].cap = cap; } - dev_dbg(&pdev->dev, "cpu=%d freq=%ld cap=%ld power_d0=%ld\n", cpu, freq, sge_l0->cap_states[i].cap, @@ -269,8 +255,8 @@ static int sched_energy_probe(struct platform_device *pdev) } dev_info(&pdev->dev, - "cpu=%d eff=%d [freq=%ld cap=%ld power_d0=%ld] -> [freq=%ld cap=%ld power_d0=%ld]\n", - cpu, efficiency, + "cpu=%d [freq=%ld cap=%ld power_d0=%ld] -> [freq=%ld cap=%ld power_d0=%ld]\n", + cpu, sge_l0->cap_states[0].frequency, sge_l0->cap_states[0].cap, sge_l0->cap_states[0].power, @@ -279,13 +265,6 @@ static int sched_energy_probe(struct platform_device *pdev) sge_l0->cap_states[ncapstates - 1].power ); } - - - dev_dbg(&pdev->dev, - "cpu=%d efficiency=%d max_frequency=%ld max_efficiency=%d cpu_max_capacity=%ld\n", - cpu, efficiency, max_frequencies[cpu], max_efficiency, - cpu_max_cap); - } kfree(max_frequencies); @@ -298,28 +277,33 @@ static int sched_energy_probe(struct platform_device *pdev) exit: if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "error=%d\n", ret); - kfree(max_frequencies); return ret; } -static const struct of_device_id of_sched_energy_dt[] = { - { - .compatible = "sched-energy", - }, - { } -}; - static struct platform_driver energy_driver = { .driver = { .name = "sched-energy", - .of_match_table = of_sched_energy_dt, }, .probe = sched_energy_probe, }; +static struct platform_device energy_device = { + .name = "sched-energy", +}; + static int __init sched_energy_init(void) { - return platform_driver_register(&energy_driver); + int ret; + + ret = platform_device_register(&energy_device); + if (ret) + pr_err("%s device_register failed:%d\n", __func__, ret); + ret = platform_driver_register(&energy_driver); + if (ret) { + pr_err("%s driver_register failed:%d\n", __func__, ret); + platform_device_unregister(&energy_device); + } + return ret; } subsys_initcall(sched_energy_init);