diff mbox series

thermal/drivers/cpuidle_cooling: Change the latency limit

Message ID 20200919044725.2148-1-zhuguangqing83@gmail.com (mailing list archive)
State New, archived
Delegated to: Daniel Lezcano
Headers show
Series thermal/drivers/cpuidle_cooling: Change the latency limit | expand

Commit Message

guangqing zhu Sept. 19, 2020, 4:47 a.m. UTC
From: zhuguangqing <zhuguangqing@xiaomi.com>

The injected idle duration must be greater than the wake up latency
(entry + exit latency) or the idle state target residency (or  min
residency), otherwise we end up consuming more energy and potentially
invert the mitigation effect.

In function idle_inject_fn(), we call play_idle_precise() to specify
a latency limit which is finally used in find_deepest_state() to find
the deepest idle state. Although the latency limit is compared with
s->exit_latency_ns in find_deepest_state(), it should not be exit
latency, but the idle duraion minus entry latency which can ensure
that the injected idle duration is greater than the wake up latency
(entry + exit latency).

There are two timers in idle inject process, the length of the first
timer (timer_1) is idle duration, and the length of the second timer
(timer_2) is idle duration plus run duration. When timer_2 expires,
it's restarted and idle_inject_timer_fn() is called and it wakes up
idle injection tasks associated with the timer and they, in turn,
invoke play_idle_precise() to inject a specified amount (idle duration)
of CPU idle time. The major functions called are as follows:

play_idle_precise() ->
 do_idle() ->
  cpuidle_idle_call() ->
   cpuidle_find_deepest_state() ->
    find_deepest_state()

When we call find_deepest_state(), some time has been consumed from
the beginning of the idle duration which could be considered the
entry latency approximately, so the latency limit should be the idle
duraion minus entry latency which can ensure that the injected idle
duration is greater than the wake up latency (entry + exit latency).

Here are two sample scenes,
scene   entry latency(us)    exit latency(us)    idle duration(us)
1            500                     600               1000
2            500                     600               3000

In scene 1, if we use exit latency (600us) for the latency limit,
we may find a idle state which has a exit latency equal to or less
than 600us, suppose the idle state's exit latency is equal to 600us,
then the wake up latency (entry + exit latency) is greater than idle
duration.

In scene 2, if we use exit latency (600us) for the latency limit,
we may also find a idle state which has a exit latency equal to
600us. But if we use the idle duraion minus entry latency
(3000 - 500 = 2500us), we can find a deeper idle state to save
more power in idle duration.

Signed-off-by: zhuguangqing <zhuguangqing@xiaomi.com>
---
 drivers/thermal/cpuidle_cooling.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/thermal/cpuidle_cooling.c b/drivers/thermal/cpuidle_cooling.c
index 78e3e8238116..6f78c7816fcc 100644
--- a/drivers/thermal/cpuidle_cooling.c
+++ b/drivers/thermal/cpuidle_cooling.c
@@ -174,6 +174,7 @@  static int __cpuidle_cooling_register(struct device_node *np,
 	struct idle_inject_device *ii_dev;
 	struct cpuidle_cooling_device *idle_cdev;
 	struct thermal_cooling_device *cdev;
+	unsigned int entry_latency_us;
 	unsigned int idle_duration_us = TICK_USEC;
 	unsigned int latency_us = UINT_MAX;
 	char dev_name[THERMAL_NAME_LENGTH];
@@ -198,7 +199,9 @@  static int __cpuidle_cooling_register(struct device_node *np,
 	}
 
 	of_property_read_u32(np, "duration-us", &idle_duration_us);
-	of_property_read_u32(np, "exit-latency-us", &latency_us);
+	if (!of_property_read_u32(np, "entry-latency-us", &entry_latency_us) &&
+	    idle_duration_us > entry_latency_us)
+		latency_us = idle_duration_us - entry_latency_us;
 
 	idle_inject_set_duration(ii_dev, TICK_USEC, idle_duration_us);
 	idle_inject_set_latency(ii_dev, latency_us);