]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
cpuidle: Fix incorrect optimization
authorArjan van de Ven <arjan@linux.intel.com>
Sat, 8 May 2010 22:47:37 +0000 (15:47 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 12 May 2010 22:03:10 +0000 (15:03 -0700)
commit 1c6fe0364fa7bf28248488753ee0afb6b759cd04 upstream.

commit 672917dcc78 ("cpuidle: menu governor: reduce latency on exit")
added an optimization, where the analysis on the past idle period moved
from the end of idle, to the beginning of the new idle.

Unfortunately, this optimization had a bug where it zeroed one key
variable for new use, that is needed for the analysis.  The fix is
simple, zero the variable after doing the work from the previous idle.

During the audit of the code that found this issue, another issue was
also found; the ->measured_us data structure member is never set, a
local variable is always used instead.

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Corrado Zoccolo <czoccolo@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/cpuidle/governors/menu.c

index 73655aeb3a60993e28fbbf9ea7930128e5a23407..f8e57c6303f2c17860d7f7700975ed5502743cb7 100644 (file)
@@ -101,7 +101,6 @@ struct menu_device {
 
        unsigned int    expected_us;
        u64             predicted_us;
-       unsigned int    measured_us;
        unsigned int    exit_us;
        unsigned int    bucket;
        u64             correction_factor[BUCKETS];
@@ -187,14 +186,14 @@ static int menu_select(struct cpuidle_device *dev)
        int i;
        int multiplier;
 
-       data->last_state_idx = 0;
-       data->exit_us = 0;
-
        if (data->needs_update) {
                menu_update(dev);
                data->needs_update = 0;
        }
 
+       data->last_state_idx = 0;
+       data->exit_us = 0;
+
        /* Special case when user has set very strict latency requirement */
        if (unlikely(latency_req == 0))
                return 0;
@@ -294,7 +293,7 @@ static void menu_update(struct cpuidle_device *dev)
        new_factor = data->correction_factor[data->bucket]
                        * (DECAY - 1) / DECAY;
 
-       if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING)
+       if (data->expected_us > 0 && measured_us < MAX_INTERESTING)
                new_factor += RESOLUTION * measured_us / data->expected_us;
        else
                /*