A common piece of data used by cpuidle governors, is the information about
when the next timer/tick is going to fire. Rather than having each governor
calling tick_nohz_get_next_timer|hrtimer() separately, let's consolidate
the code by calling these functions before invoking the ->select() callback
of the governor - and store the output data in the struct cpuidle_device.

Besides the consolidation benefit, the purpose of this change is also to
make the information about the next timer/tick, available outside the
cpuidle framework. Following changes that implements a new genpd governor,
makes use of this.

Signed-off-by: Ulf Hansson <[email protected]>
---

Changes in v11:
        - New patch.

---
 drivers/cpuidle/cpuidle.c        | 2 ++
 drivers/cpuidle/governors/menu.c | 6 ++----
 drivers/cpuidle/governors/teo.c  | 6 ++----
 include/linux/cpuidle.h          | 2 ++
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 7f108309e871..3b148253036b 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -312,6 +312,8 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct 
cpuidle_driver *drv,
 int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                   bool *stop_tick)
 {
+       dev->next_timer = tick_nohz_get_next_timer();
+       dev->next_hrtimer = tick_nohz_get_next_hrtimer();
        return cpuidle_curr_governor->select(drv, dev, stop_tick);
 }
 
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 95e9122d6047..cdbe434e783d 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -287,8 +287,6 @@ static int menu_select(struct cpuidle_driver *drv, struct 
cpuidle_device *dev,
        unsigned long nr_iowaiters;
        ktime_t delta_next;
        ktime_t now = ktime_get();
-       ktime_t next_hrtimer = tick_nohz_get_next_hrtimer();
-       ktime_t next_timer = tick_nohz_get_next_timer();
 
        if (data->needs_update) {
                menu_update(drv, dev);
@@ -298,14 +296,14 @@ static int menu_select(struct cpuidle_driver *drv, struct 
cpuidle_device *dev,
        /*
         * Compute the duration before the next timer, whatever the origin
         */
-       delta_next = ktime_sub(next_timer, now);
+       delta_next = ktime_sub(dev->next_timer, now);
        data->next_timer_us = ktime_to_us(delta_next);
 
        /*
         * Compute the duration before next hrtimer which is the tick
         * or an earliest hrtimer
         */
-       delta_next = ktime_sub(next_hrtimer, now);
+       delta_next = ktime_sub(dev->next_hrtimer, now);
 
        nr_iowaiters = nr_iowait_cpu(dev->cpu);
        data->bucket = which_bucket(data->next_timer_us, nr_iowaiters);
diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c
index bef1e95c597e..7af9851d9d40 100644
--- a/drivers/cpuidle/governors/teo.c
+++ b/drivers/cpuidle/governors/teo.c
@@ -245,8 +245,6 @@ static int teo_select(struct cpuidle_driver *drv, struct 
cpuidle_device *dev,
        int max_early_idx, idx, i;
        ktime_t delta_tick;
        ktime_t now = ktime_get();
-       ktime_t next_hrtimer = tick_nohz_get_next_hrtimer();
-       ktime_t next_timer = tick_nohz_get_next_timer();
 
        if (cpu_data->last_state >= 0) {
                teo_update(drv, dev);
@@ -255,8 +253,8 @@ static int teo_select(struct cpuidle_driver *drv, struct 
cpuidle_device *dev,
 
        cpu_data->time_span_ns = local_clock();
 
-       cpu_data->sleep_length_ns = ktime_sub(next_timer, now);
-       delta_tick = ktime_sub(next_hrtimer, now);
+       cpu_data->sleep_length_ns = ktime_sub(dev->next_timer, now);
+       delta_tick = ktime_sub(dev->next_hrtimer, now);
        duration_us = ktime_to_us(cpu_data->sleep_length_ns);
 
        count = 0;
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 3b39472324a3..81ec924206f0 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -83,6 +83,8 @@ struct cpuidle_device {
        unsigned int            use_deepest_state:1;
        unsigned int            poll_time_limit:1;
        unsigned int            cpu;
+       ktime_t                 next_timer;
+       ktime_t                 next_hrtimer;
 
        int                     last_residency;
        struct cpuidle_state_usage      states_usage[CPUIDLE_STATE_MAX];
-- 
2.17.1

Reply via email to