From c208338efc650057c49cd5c91ff0cdf43d84d194 Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Wed, 27 Mar 2019 09:51:24 -0700 Subject: [PATCH] power: em: correct increasing freq/power ratio As freq increases freq/power should decrease, indicating nonlinearly higher power is required for running at higher frequencies. If freq/power increases, the cost associated with that freq will be lower than its previous one, causing the energy calculations to choose a cpu with that frequency over a cpu with the previous lesser freq. For some frequencies, if their voltage increment from the previous ones is very small (or is the same), we could end up with higher freq/power ratio. This is primarily because of_dev_pm_opp_get_cpu_power() returns power in mW and looses precision. But instead of addressing it, enforce the same cost as the previous frequency. The energy evaluation code prefers the previous cpu when the energy costs are same as other candidates. By keeping the energy costs same in these situations we are increasing the likely hood of selecting prev cpu even if it results in a slight freq bump. In general, selecting prev cpu is beneficial because it avoids warming up the caches at a different cpu. Change-Id: Ic66ab18ba65f2917b73d9fbe92a39b743b9839a0 Signed-off-by: Abhijeet Dharmapurikar --- kernel/power/energy_model.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c index 7d66ee68aaaf..a2845e25e075 100644 --- a/kernel/power/energy_model.c +++ b/kernel/power/energy_model.c @@ -141,7 +141,7 @@ static struct em_perf_domain *em_create_pd(cpumask_t *span, int nr_states, */ opp_eff = freq / power; if (opp_eff >= prev_opp_eff) - pr_warn("pd%d: hertz/watts ratio non-monotonically decreasing: em_cap_state %d >= em_cap_state%d\n", + pr_debug("pd%d: hertz/watts ratio non-monotonically decreasing: em_cap_state %d >= em_cap_state%d\n", cpu, i, i - 1); prev_opp_eff = opp_eff; } @@ -151,6 +151,10 @@ static struct em_perf_domain *em_create_pd(cpumask_t *span, int nr_states, for (i = 0; i < nr_states; i++) { table[i].cost = div64_u64(fmax * table[i].power, table[i].frequency); + if (i > 0 && (table[i].cost < table[i - 1].cost) && + (table[i].power > table[i - 1].power)) { + table[i].cost = table[i - 1].cost; + } } pd->table = table;