| From trenn@suse.de Tue Feb 3 14:59:11 2009 |
| From: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> |
| Date: Tue, 27 Jan 2009 17:38:46 +0100 |
| Subject: cpuidle: Add decaying history logic to menu idle predictor |
| To: stable@kernel.org |
| Cc: Len Brown <len.brown@intel.com>, <venkatesh.pallipadi@intel.com> |
| Message-ID: <1233074343-23414-5-git-send-email-trenn@suse.de> |
| |
| |
| From: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> |
| |
| commit 816bb611e41be29b476dc16f6297eb551bf4d747 upstream |
| |
| Add decaying history of predicted idle time, instead of using the last early |
| wakeup. This logic helps menu governor do better job of predicting idle time. |
| |
| With this change, we also measured noticable (~8%) power savings on |
| a DP server system with CPUs supporting deep C states, when system |
| was lightly loaded. There was no change to power or perf on other load |
| conditions. |
| |
| Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> |
| Signed-off-by: Len Brown <len.brown@intel.com> |
| Cc: Thomas Renninger <trenn@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/cpuidle/governors/menu.c | 10 +++++++++- |
| 1 file changed, 9 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/cpuidle/governors/menu.c |
| +++ b/drivers/cpuidle/governors/menu.c |
| @@ -15,12 +15,14 @@ |
| #include <linux/tick.h> |
| |
| #define BREAK_FUZZ 4 /* 4 us */ |
| +#define PRED_HISTORY_PCT 50 |
| |
| struct menu_device { |
| int last_state_idx; |
| |
| unsigned int expected_us; |
| unsigned int predicted_us; |
| + unsigned int current_predicted_us; |
| unsigned int last_measured_us; |
| unsigned int elapsed_us; |
| }; |
| @@ -47,6 +49,12 @@ static int menu_select(struct cpuidle_de |
| data->expected_us = |
| (u32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000; |
| |
| + /* Recalculate predicted_us based on prediction_history_pct */ |
| + data->predicted_us *= PRED_HISTORY_PCT; |
| + data->predicted_us += (100 - PRED_HISTORY_PCT) * |
| + data->current_predicted_us; |
| + data->predicted_us /= 100; |
| + |
| /* find the deepest idle state that satisfies our constraints */ |
| for (i = CPUIDLE_DRIVER_STATE_START + 1; i < dev->state_count; i++) { |
| struct cpuidle_state *s = &dev->states[i]; |
| @@ -97,7 +105,7 @@ static void menu_reflect(struct cpuidle_ |
| measured_us = -1; |
| |
| /* Predict time until next break event */ |
| - data->predicted_us = max(measured_us, data->last_measured_us); |
| + data->current_predicted_us = max(measured_us, data->last_measured_us); |
| |
| if (last_idle_us + BREAK_FUZZ < |
| data->expected_us - target->exit_latency) { |