diff options
Diffstat (limited to 'kernel/time/tick-oneshot.c')
| -rw-r--r-- | kernel/time/tick-oneshot.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c index 0a8a213016f0..aada0e52680a 100644 --- a/kernel/time/tick-oneshot.c +++ b/kernel/time/tick-oneshot.c | |||
| @@ -22,6 +22,29 @@ | |||
| 22 | 22 | ||
| 23 | #include "tick-internal.h" | 23 | #include "tick-internal.h" |
| 24 | 24 | ||
| 25 | /* Limit min_delta to a jiffie */ | ||
| 26 | #define MIN_DELTA_LIMIT (NSEC_PER_SEC / HZ) | ||
| 27 | |||
| 28 | static int tick_increase_min_delta(struct clock_event_device *dev) | ||
| 29 | { | ||
| 30 | /* Nothing to do if we already reached the limit */ | ||
| 31 | if (dev->min_delta_ns >= MIN_DELTA_LIMIT) | ||
| 32 | return -ETIME; | ||
| 33 | |||
| 34 | if (dev->min_delta_ns < 5000) | ||
| 35 | dev->min_delta_ns = 5000; | ||
| 36 | else | ||
| 37 | dev->min_delta_ns += dev->min_delta_ns >> 1; | ||
| 38 | |||
| 39 | if (dev->min_delta_ns > MIN_DELTA_LIMIT) | ||
| 40 | dev->min_delta_ns = MIN_DELTA_LIMIT; | ||
| 41 | |||
| 42 | printk(KERN_WARNING "CE: %s increased min_delta_ns to %llu nsec\n", | ||
| 43 | dev->name ? dev->name : "?", | ||
| 44 | (unsigned long long) dev->min_delta_ns); | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | |||
| 25 | /** | 48 | /** |
| 26 | * tick_program_event internal worker function | 49 | * tick_program_event internal worker function |
| 27 | */ | 50 | */ |
| @@ -37,23 +60,28 @@ int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, | |||
| 37 | if (!ret || !force) | 60 | if (!ret || !force) |
| 38 | return ret; | 61 | return ret; |
| 39 | 62 | ||
| 63 | dev->retries++; | ||
| 40 | /* | 64 | /* |
| 41 | * We tried 2 times to program the device with the given | 65 | * We tried 3 times to program the device with the given |
| 42 | * min_delta_ns. If that's not working then we double it | 66 | * min_delta_ns. If that's not working then we increase it |
| 43 | * and emit a warning. | 67 | * and emit a warning. |
| 44 | */ | 68 | */ |
| 45 | if (++i > 2) { | 69 | if (++i > 2) { |
| 46 | /* Increase the min. delta and try again */ | 70 | /* Increase the min. delta and try again */ |
| 47 | if (!dev->min_delta_ns) | 71 | if (tick_increase_min_delta(dev)) { |
| 48 | dev->min_delta_ns = 5000; | 72 | /* |
| 49 | else | 73 | * Get out of the loop if min_delta_ns |
| 50 | dev->min_delta_ns += dev->min_delta_ns >> 1; | 74 | * hit the limit already. That's |
| 51 | 75 | * better than staying here forever. | |
| 52 | printk(KERN_WARNING | 76 | * |
| 53 | "CE: %s increasing min_delta_ns to %llu nsec\n", | 77 | * We clear next_event so we have a |
| 54 | dev->name ? dev->name : "?", | 78 | * chance that the box survives. |
| 55 | (unsigned long long) dev->min_delta_ns << 1); | 79 | */ |
| 56 | 80 | printk(KERN_WARNING | |
| 81 | "CE: Reprogramming failure. Giving up\n"); | ||
| 82 | dev->next_event.tv64 = KTIME_MAX; | ||
| 83 | return -ETIME; | ||
| 84 | } | ||
| 57 | i = 0; | 85 | i = 0; |
| 58 | } | 86 | } |
| 59 | 87 | ||
