]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
cpuidle: menu: Better idle duration measurement without using CPUIDLE_FLAG_TIME_INVALID
authorLen Brown <len.brown@intel.com>
Tue, 16 Dec 2014 06:52:06 +0000 (01:52 -0500)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 17 Dec 2014 01:26:28 +0000 (02:26 +0100)
When menu sees CPUIDLE_FLAG_TIME_INVALID, it ignores its timestamps,
and assumes that idle lasted as long as the time till next predicted
timer expiration.

But if an interrupt was seen and serviced before that duration,
it would actually be more accurate to use the measured time
rather than rounding up to the next predicted timer expiration.

And if an interrupt is seen and serviced such that the mesured time
exceeds the time till next predicted timer expiration, then
truncating to that expiration is the right thing to do --
since we can never stay idle past that timer expiration.

So the code can do a better job without
checking for CPUIDLE_FLAG_TIME_INVALID.

Signed-off-by: Len Brown <len.brown@intel.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Tuukka Tikkanen <tuukka.tikkanen@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/cpuidle/governors/menu.c

index 659d7b0c9ebfd1e78348d539f497112c36f2cdc5..40580794e23dc00f4d086a696c803ed35b4c0f25 100644 (file)
@@ -396,8 +396,8 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         * power state and occurrence of the wakeup event.
         *
         * If the entered idle state didn't support residency measurements,
-        * we are basically lost in the dark how much time passed.
-        * As a compromise, assume we slept for the whole expected time.
+        * we use them anyway if they are short, and if long,
+        * truncate to the whole expected time.
         *
         * Any measured amount of time will include the exit latency.
         * Since we are interested in when the wakeup begun, not when it
@@ -405,22 +405,17 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         * the measured amount of time is less than the exit latency,
         * assume the state was never reached and the exit latency is 0.
         */
-       if (unlikely(target->flags & CPUIDLE_FLAG_TIME_INVALID)) {
-               /* Use timer value as is */
-               measured_us = data->next_timer_us;
 
-       } else {
-               /* Use measured value */
-               measured_us = cpuidle_get_last_residency(dev);
+       /* measured value */
+       measured_us = cpuidle_get_last_residency(dev);
 
-               /* Deduct exit latency */
-               if (measured_us > target->exit_latency)
-                       measured_us -= target->exit_latency;
+       /* Deduct exit latency */
+       if (measured_us > target->exit_latency)
+               measured_us -= target->exit_latency;
 
-               /* Make sure our coefficients do not exceed unity */
-               if (measured_us > data->next_timer_us)
-                       measured_us = data->next_timer_us;
-       }
+       /* Make sure our coefficients do not exceed unity */
+       if (measured_us > data->next_timer_us)
+               measured_us = data->next_timer_us;
 
        /* Update our correction ratio */
        new_factor = data->correction_factor[data->bucket];