|
@@ -196,7 +196,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
|
|
|
* of points is below a threshold. If it is... then use the
|
|
|
* average of these 8 points as the estimated value.
|
|
|
*/
|
|
|
-static void get_typical_interval(struct menu_device *data)
|
|
|
+static unsigned int get_typical_interval(struct menu_device *data)
|
|
|
{
|
|
|
int i, divisor;
|
|
|
unsigned int max, thresh, avg;
|
|
@@ -253,9 +253,7 @@ again:
|
|
|
if (likely(variance <= U64_MAX/36)) {
|
|
|
if ((((u64)avg*avg > variance*36) && (divisor * 4 >= INTERVALS * 3))
|
|
|
|| variance <= 400) {
|
|
|
- if (data->next_timer_us > avg)
|
|
|
- data->predicted_us = avg;
|
|
|
- return;
|
|
|
+ return avg;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -269,7 +267,7 @@ again:
|
|
|
* with sporadic activity with a bunch of short pauses.
|
|
|
*/
|
|
|
if ((divisor * 4) <= INTERVALS * 3)
|
|
|
- return;
|
|
|
+ return UINT_MAX;
|
|
|
|
|
|
thresh = max - 1;
|
|
|
goto again;
|
|
@@ -286,6 +284,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
|
|
|
int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
|
|
|
int i;
|
|
|
unsigned int interactivity_req;
|
|
|
+ unsigned int expected_interval;
|
|
|
unsigned long nr_iowaiters, cpu_load;
|
|
|
|
|
|
if (data->needs_update) {
|
|
@@ -312,31 +311,38 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
|
|
|
data->correction_factor[data->bucket],
|
|
|
RESOLUTION * DECAY);
|
|
|
|
|
|
- get_typical_interval(data);
|
|
|
-
|
|
|
- /*
|
|
|
- * Performance multiplier defines a minimum predicted idle
|
|
|
- * duration / latency ratio. Adjust the latency limit if
|
|
|
- * necessary.
|
|
|
- */
|
|
|
- interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load);
|
|
|
- if (latency_req > interactivity_req)
|
|
|
- latency_req = interactivity_req;
|
|
|
+ expected_interval = get_typical_interval(data);
|
|
|
+ expected_interval = min(expected_interval, data->next_timer_us);
|
|
|
|
|
|
if (CPUIDLE_DRIVER_STATE_START > 0) {
|
|
|
data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1;
|
|
|
/*
|
|
|
* We want to default to C1 (hlt), not to busy polling
|
|
|
- * unless the timer is happening really really soon.
|
|
|
+ * unless the timer is happening really really soon, or
|
|
|
+ * C1's exit latency exceeds the user configured limit.
|
|
|
*/
|
|
|
- if (interactivity_req > 20 &&
|
|
|
+ if (expected_interval > drv->states[CPUIDLE_DRIVER_STATE_START].target_residency &&
|
|
|
+ latency_req > drv->states[CPUIDLE_DRIVER_STATE_START].exit_latency &&
|
|
|
!drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
|
|
|
- dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)
|
|
|
+ !dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable)
|
|
|
data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
|
|
|
} else {
|
|
|
data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Use the lowest expected idle interval to pick the idle state.
|
|
|
+ */
|
|
|
+ data->predicted_us = min(data->predicted_us, expected_interval);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Use the performance multiplier and the user-configurable
|
|
|
+ * latency_req to determine the maximum exit latency.
|
|
|
+ */
|
|
|
+ interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load);
|
|
|
+ if (latency_req > interactivity_req)
|
|
|
+ latency_req = interactivity_req;
|
|
|
+
|
|
|
/*
|
|
|
* Find the idle state with the lowest power while satisfying
|
|
|
* our constraints.
|