diff options
Diffstat (limited to 'kernel/time/tick-oneshot.c')
-rw-r--r-- | kernel/time/tick-oneshot.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c index 06595c64b0c9..2e35501e61dd 100644 --- a/kernel/time/tick-oneshot.c +++ b/kernel/time/tick-oneshot.c | |||
@@ -25,18 +25,42 @@ | |||
25 | /** | 25 | /** |
26 | * tick_program_event internal worker function | 26 | * tick_program_event internal worker function |
27 | */ | 27 | */ |
28 | static int __tick_program_event(struct clock_event_device *dev, | 28 | int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, |
29 | ktime_t expires, int force) | 29 | int force) |
30 | { | 30 | { |
31 | ktime_t now = ktime_get(); | 31 | ktime_t now = ktime_get(); |
32 | int i; | ||
32 | 33 | ||
33 | while (1) { | 34 | for (i = 0;;) { |
34 | int ret = clockevents_program_event(dev, expires, now); | 35 | int ret = clockevents_program_event(dev, expires, now); |
35 | 36 | ||
36 | if (!ret || !force) | 37 | if (!ret || !force) |
37 | return ret; | 38 | return ret; |
39 | |||
40 | /* | ||
41 | * We tried 2 times to program the device with the given | ||
42 | * min_delta_ns. If that's not working then we double it | ||
43 | * and emit a warning. | ||
44 | */ | ||
45 | if (++i > 2) { | ||
46 | printk(KERN_WARNING "CE: __tick_program_event of %s is " | ||
47 | "stuck %llx %llx\n", dev->name ? dev->name : "?", | ||
48 | now.tv64, expires.tv64); | ||
49 | printk(KERN_WARNING | ||
50 | "CE: increasing min_delta_ns %ld to %ld nsec\n", | ||
51 | dev->min_delta_ns, dev->min_delta_ns << 1); | ||
52 | WARN_ON(1); | ||
53 | |||
54 | /* Double the min. delta and try again */ | ||
55 | if (!dev->min_delta_ns) | ||
56 | dev->min_delta_ns = 5000; | ||
57 | else | ||
58 | dev->min_delta_ns <<= 1; | ||
59 | i = 0; | ||
60 | } | ||
61 | |||
38 | now = ktime_get(); | 62 | now = ktime_get(); |
39 | expires = ktime_add(now, ktime_set(0, dev->min_delta_ns)); | 63 | expires = ktime_add_ns(now, dev->min_delta_ns); |
40 | } | 64 | } |
41 | } | 65 | } |
42 | 66 | ||
@@ -47,7 +71,7 @@ int tick_program_event(ktime_t expires, int force) | |||
47 | { | 71 | { |
48 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; | 72 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; |
49 | 73 | ||
50 | return __tick_program_event(dev, expires, force); | 74 | return tick_dev_program_event(dev, expires, force); |
51 | } | 75 | } |
52 | 76 | ||
53 | /** | 77 | /** |
@@ -71,7 +95,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev, | |||
71 | { | 95 | { |
72 | newdev->event_handler = handler; | 96 | newdev->event_handler = handler; |
73 | clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT); | 97 | clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT); |
74 | __tick_program_event(newdev, next_event, 1); | 98 | tick_dev_program_event(newdev, next_event, 1); |
75 | } | 99 | } |
76 | 100 | ||
77 | /** | 101 | /** |