| From 9b0cf16ceeaf8820401a8a9853c0f94910ffc6e2 Mon Sep 17 00:00:00 2001 |
| From: Daniel Lezcano <daniel.lezcano@linaro.org> |
| Date: Mon, 27 May 2019 22:55:14 +0200 |
| Subject: [PATCH] genirq/timings: Fix next event index function |
| |
| commit 619c1baa91b2820eae9ff5d89eb525df81ea7a5a upstream. |
| |
| The current code is luckily working with most of the interval samples |
| testing but actually it fails to correctly detect pattern repetition |
| breaking at the end of the buffer. |
| |
| Narrowing down the bug has been a real pain because of the pointers, |
| so the routine is rewrittne by using indexes instead. |
| |
| Fixes: bbba0e7c5cda "genirq/timings: Add array suffix computation code" |
| Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Cc: andriy.shevchenko@linux.intel.com |
| Link: https://lkml.kernel.org/r/20190527205521.12091-2-daniel.lezcano@linaro.org |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/kernel/irq/timings.c b/kernel/irq/timings.c |
| index 90c735da15d0..4f5daf3db13b 100644 |
| --- a/kernel/irq/timings.c |
| +++ b/kernel/irq/timings.c |
| @@ -297,7 +297,16 @@ static u64 irq_timings_ema_new(u64 value, u64 ema_old) |
| |
| static int irq_timings_next_event_index(int *buffer, size_t len, int period_max) |
| { |
| - int i; |
| + int period; |
| + |
| + /* |
| + * Move the beginning pointer to the end minus the max period x 3. |
| + * We are at the point we can begin searching the pattern |
| + */ |
| + buffer = &buffer[len - (period_max * 3)]; |
| + |
| + /* Adjust the length to the maximum allowed period x 3 */ |
| + len = period_max * 3; |
| |
| /* |
| * The buffer contains the suite of intervals, in a ilog2 |
| @@ -306,21 +315,45 @@ static int irq_timings_next_event_index(int *buffer, size_t len, int period_max) |
| * period beginning at the end of the buffer. We do that for |
| * each suffix. |
| */ |
| - for (i = period_max; i >= PREDICTION_PERIOD_MIN ; i--) { |
| + for (period = period_max; period >= PREDICTION_PERIOD_MIN; period--) { |
| |
| - int *begin = &buffer[len - (i * 3)]; |
| - int *ptr = begin; |
| + /* |
| + * The first comparison always succeed because the |
| + * suffix is deduced from the first n-period bytes of |
| + * the buffer and we compare the initial suffix with |
| + * itself, so we can skip the first iteration. |
| + */ |
| + int idx = period; |
| + size_t size = period; |
| |
| /* |
| * We look if the suite with period 'i' repeat |
| * itself. If it is truncated at the end, as it |
| * repeats we can use the period to find out the next |
| - * element. |
| + * element with the modulo. |
| */ |
| - while (!memcmp(ptr, begin, i * sizeof(*ptr))) { |
| - ptr += i; |
| - if (ptr >= &buffer[len]) |
| - return begin[((i * 3) % i)]; |
| + while (!memcmp(buffer, &buffer[idx], size * sizeof(int))) { |
| + |
| + /* |
| + * Move the index in a period basis |
| + */ |
| + idx += size; |
| + |
| + /* |
| + * If this condition is reached, all previous |
| + * memcmp were successful, so the period is |
| + * found. |
| + */ |
| + if (idx == len) |
| + return buffer[len % period]; |
| + |
| + /* |
| + * If the remaining elements to compare are |
| + * smaller than the period, readjust the size |
| + * of the comparison for the last iteration. |
| + */ |
| + if (len - idx < period) |
| + size = len - idx; |
| } |
| } |
| |
| -- |
| 2.27.0 |
| |