Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 336727
b: refs/heads/master
c: e11538d
h: refs/heads/master
i:
  336725: 57aaef5
  336723: 8af6de9
  336719: 7f0dbfc
v: v3
  • Loading branch information
Youquan Song authored and Rafael J. Wysocki committed Nov 14, 2012
1 parent 23cd6a9 commit 572b23d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 69a37beabf1f0a6705c08e879bdd5d82ff6486c4
refs/heads/master: e11538d1f03914eb92af5a1a378375c05ae8520c
34 changes: 33 additions & 1 deletion trunk/drivers/cpuidle/governors/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer);
static DEFINE_PER_CPU(int, hrtimer_status);
/* menu hrtimer mode */
enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT};
enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL};

/*
* Concepts and ideas behind the menu governor
Expand Down Expand Up @@ -116,6 +116,13 @@ enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT};
*
*/

/*
* The C-state residency is so long that is is worthwhile to exit
* from the shallow C-state and re-enter into a deeper C-state.
*/
static unsigned int perfect_cstate_ms __read_mostly = 30;
module_param(perfect_cstate_ms, uint, 0000);

struct menu_device {
int last_state_idx;
int needs_update;
Expand Down Expand Up @@ -216,6 +223,16 @@ EXPORT_SYMBOL_GPL(menu_hrtimer_cancel);
static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer)
{
int cpu = smp_processor_id();
struct menu_device *data = &per_cpu(menu_devices, cpu);

/* In general case, the expected residency is much larger than
* deepest C-state target residency, but prediction logic still
* predicts a small predicted residency, so the prediction
* history is totally broken if the timer is triggered.
* So reset the correction factor.
*/
if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL)
data->correction_factor[data->bucket] = RESOLUTION * DECAY;

per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP;

Expand Down Expand Up @@ -353,6 +370,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
/* not deepest C-state chosen for low predicted residency */
if (low_predicted) {
unsigned int timer_us = 0;
unsigned int perfect_us = 0;

/*
* Set a timer to detect whether this sleep is much
Expand All @@ -363,12 +381,26 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
*/
timer_us = 2 * (data->predicted_us + MAX_DEVIATION);

perfect_us = perfect_cstate_ms * 1000;

if (repeat && (4 * timer_us < data->expected_us)) {
hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us),
HRTIMER_MODE_REL_PINNED);
/* In repeat case, menu hrtimer is started */
per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT;
} else if (perfect_us < data->expected_us) {
/*
* The next timer is long. This could be because
* we did not make a useful prediction.
* In that case, it makes sense to re-enter
* into a deeper C-state after some time.
*/
hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us),
HRTIMER_MODE_REL_PINNED);
/* In general case, menu hrtimer is started */
per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL;
}

}

return data->last_state_idx;
Expand Down

0 comments on commit 572b23d

Please sign in to comment.