[PATCH] thermal/drivers/cpuidle_cooling: Change the latency limit
From: zhuguangqing83
Date: Sat Sep 19 2020 - 00:47:40 EST
From: zhuguangqing <zhuguangqing@xxxxxxxxxx>
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@xxxxxxxxxx>
---
drivers/thermal/cpuidle_cooling.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
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);
--
2.17.1