The patch extends the patch to enhance the prediction for repeat mode by add a timer when menu governor choose a shallow C-state. The timer is set to time out in 50 milli-seconds by default. It is special twist that there are no power saving gains even sleep longer than it. When C-state is waken up prior to the adding timer, the timer will be cancelled initiatively. When the timer is triggered and menu governor will quickly notice prediction failure and re-evaluates deeper C-states possibility. Signed-off-by: Youquan Song <youquan.song@xxxxxxxxx> --- drivers/cpuidle/governors/menu.c | 48 ++++++++++++++++++++++++++------------ 1 files changed, 33 insertions(+), 15 deletions(-) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 8c23fbd..9f92dd4 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -113,6 +113,13 @@ static DEFINE_PER_CPU(int, hrtimer_started); * represented in the system load average. * */ + +/* + * Default set to 50 milliseconds based on special twist mentioned above that + * there are no power gains sleep longer than it. + */ +static unsigned int perfect_cstate_ms __read_mostly = 50; +module_param(perfect_cstate_ms, uint, 0000); struct menu_device { int last_state_idx; @@ -343,26 +350,37 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) data->exit_us = s->exit_latency; } } - + + /* not deepest C-state chosen */ if (data->last_state_idx < drv->state_count - 1) { + unsigned int repeat_us = 0; + unsigned int perfect_us = 0; + + /* + * Set enough timer to recognize the repeat mode broken. + * If the timer is time out, the repeat mode prediction + * fails,then re-evaluate deeper C-states possibility. + * If the timer is not triggered, the timer will be + * cancelled when CPU waken up. + */ + repeat_us = + (repeat ? (2 * data->predicted_us + MAX_DEVIATION) : 0); + perfect_us = perfect_cstate_ms * 1000; /* Repeat mode detected */ - if (repeat) { - unsigned int repeat_us = 0; - /* - * Set enough timer to recognize the repeat mode broken. - * If the timer is time out, the repeat mode prediction - * fails,then re-evaluate deeper C-states possibility. - * If the timer is not triggered, the timer will be - * cancelled when CPU waken up. - */ - repeat_us = 2 * data->predicted_us + MAX_DEVIATION; - hrtimer_start(hrtmr, ns_to_ktime(1000 * repeat_us), - HRTIMER_MODE_REL_PINNED); + if (repeat && (repeat_us < perfect_us)) { + hrtimer_start(hrtmr, ns_to_ktime(1000 * repeat_us), + HRTIMER_MODE_REL_PINNED); + /* menu hrtimer is started */ + per_cpu(hrtimer_started, cpu) = 1; + } else if (perfect_us < data->expected_us) { + /* expected time is larger than adding timer time */ + hrtimer_start(hrtmr, ns_to_ktime(1000 * perfect_us), + HRTIMER_MODE_REL_PINNED); /* menu hrtimer is started */ per_cpu(hrtimer_started, cpu) = 1; - } - } + } + } return data->last_state_idx; } -- 1.6.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html