cpuidle: extend cpuidle and menu governor to handle dynamic states
[sfrench/cifs-2.6.git] / drivers / cpuidle / governors / menu.c
index 1b128702d300bc5a07ba7ec09f03ec83f3b11b43..c2408bbe9c2eed3521f4eb21a86c1e9671774534 100644 (file)
@@ -234,6 +234,7 @@ static int menu_select(struct cpuidle_device *dev)
 {
        struct menu_device *data = &__get_cpu_var(menu_devices);
        int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
+       unsigned int power_usage = -1;
        int i;
        int multiplier;
 
@@ -278,19 +279,27 @@ static int menu_select(struct cpuidle_device *dev)
        if (data->expected_us > 5)
                data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
 
-
-       /* find the deepest idle state that satisfies our constraints */
+       /*
+        * Find the idle state with the lowest power while satisfying
+        * our constraints.
+        */
        for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
                struct cpuidle_state *s = &dev->states[i];
 
+               if (s->flags & CPUIDLE_FLAG_IGNORE)
+                       continue;
                if (s->target_residency > data->predicted_us)
-                       break;
+                       continue;
                if (s->exit_latency > latency_req)
-                       break;
+                       continue;
                if (s->exit_latency * multiplier > data->predicted_us)
-                       break;
-               data->exit_us = s->exit_latency;
-               data->last_state_idx = i;
+                       continue;
+
+               if (s->power_usage < power_usage) {
+                       power_usage = s->power_usage;
+                       data->last_state_idx = i;
+                       data->exit_us = s->exit_latency;
+               }
        }
 
        return data->last_state_idx;