diff options
Diffstat (limited to 'kernel/time/tick-oneshot.c')
-rw-r--r-- | kernel/time/tick-oneshot.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c index 450c04935b66..2e35501e61dd 100644 --- a/kernel/time/tick-oneshot.c +++ b/kernel/time/tick-oneshot.c | |||
@@ -23,24 +23,58 @@ | |||
23 | #include "tick-internal.h" | 23 | #include "tick-internal.h" |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * tick_program_event | 26 | * tick_program_event internal worker function |
27 | */ | 27 | */ |
28 | int tick_program_event(ktime_t expires, int force) | 28 | int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, |
29 | int force) | ||
29 | { | 30 | { |
30 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; | ||
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 | ||
43 | /** | 67 | /** |
68 | * tick_program_event | ||
69 | */ | ||
70 | int tick_program_event(ktime_t expires, int force) | ||
71 | { | ||
72 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; | ||
73 | |||
74 | return tick_dev_program_event(dev, expires, force); | ||
75 | } | ||
76 | |||
77 | /** | ||
44 | * tick_resume_onshot - resume oneshot mode | 78 | * tick_resume_onshot - resume oneshot mode |
45 | */ | 79 | */ |
46 | void tick_resume_oneshot(void) | 80 | void tick_resume_oneshot(void) |
@@ -61,7 +95,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev, | |||
61 | { | 95 | { |
62 | newdev->event_handler = handler; | 96 | newdev->event_handler = handler; |
63 | clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT); | 97 | clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT); |
64 | clockevents_program_event(newdev, next_event, ktime_get()); | 98 | tick_dev_program_event(newdev, next_event, 1); |
65 | } | 99 | } |
66 | 100 | ||
67 | /** | 101 | /** |