>From ac90d5a2bd4886f7087026d204734ed3691ca03f Mon Sep 17 00:00:00 2001
From: Patrick Bellasi <patrick.bellasi@arm.com>
Date: Tue, 6 Mar 2018 11:11:17 +0000
Subject: [PATCH] sched/fair: fix backup selection for !prefer_idle

Non prefer_idle tasks should be scheduled preferably on more energy
efficient CPUs when there are only IDLE CPUs in the system.
This was the behavior (at least for !sysctl_sched_cstate_aware) systems
provided by find_best_target before:

   88a968ca63f8 sched/fair: use min capacity when evaluating idle backup cpus

which instead forces the selection of a big IDLE CPU over a LITTLE IDLE
CPU, especially when CPUs are visited from big to LITTLEs.

Since we wanna find_best_target to provide the same behaviors
independently from the CPUs visiting ordering, this patch fixes the
above issue by resetting the "min capacity" search criteria (i.e. the
maximization of the spare capacity) conditions every time we find a more
energy efficient CPU (i.e. assuming lower capacity_orig means more
energy efficient CPU).

While at fixing this, we also rename "target_idle_max_spare_cap" into
"best_idle_max_spare_cap" which better matches the naming conventions
used for case B related variables.

Change-Id: Ie6b693b11202a98a675a93c25a472be572623dc0
Reported-by: Viresh Kumar <viresh.kumar@linaro.org>
Reported-by: Leo Yan <leo.yan@linaro.org>
Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com>
---
 kernel/sched/fair.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 1f1a73c8b7c9..9d2780c8c80b 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6743,7 +6743,7 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu,
 	unsigned long target_max_spare_cap = 0;
 	unsigned long target_util = ULONG_MAX;
 	unsigned long best_active_util = ULONG_MAX;
-	unsigned long target_idle_max_spare_cap = 0;
+	unsigned long best_idle_max_spare_cap = 0;
 	int best_idle_cstate = INT_MAX;
 	struct sched_domain *sd;
 	struct sched_group *sg;
@@ -6929,15 +6929,25 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu,
 			 */
 			if (idle_cpu(i)) {
 				int idle_idx = idle_get_state_idx(cpu_rq(i));
+				int max_spare_cap;

 				/* Select idle CPU with lower cap_orig */
 				if (capacity_orig > best_idle_min_cap_orig)
 					continue;
-				/* Favor CPUs that won't end up running at a
+
+				/*
+				 * A more energy efficient CPU has been found,
+				 * let's reset the conditions for the
+				 * following min_capped_utilization check
+				 */
+				best_idle_max_spare_cap = 0;
+
+				/*
+				 * Favor CPUs that won't end up running at a
 				 * high OPP.
 				 */
-				if ((capacity_orig - min_capped_util) <
-					target_idle_max_spare_cap)
+				max_spare_cap = capacity_orig - min_capped_util;
+				if (max_spare_cap < best_idle_max_spare_cap)
 					continue;

 				/*
@@ -6951,9 +6961,8 @@ static inline int find_best_target(struct task_struct *p, int *backup_cpu,
 					continue;

 				/* Keep track of best idle CPU */
+				best_idle_max_spare_cap = max_spare_cap;
 				best_idle_min_cap_orig = capacity_orig;
-				target_idle_max_spare_cap = capacity_orig -
-							    min_capped_util;
 				best_idle_cstate = idle_idx;
 				best_idle_cpu = i;
 				continue;
--
2.15.1

