diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0083-hrtimer-Update-hrtimer-base-offsets-each-hrtimer_int.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0083-hrtimer-Update-hrtimer-base-offsets-each-hrtimer_int.patch | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0083-hrtimer-Update-hrtimer-base-offsets-each-hrtimer_int.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0083-hrtimer-Update-hrtimer-base-offsets-each-hrtimer_int.patch new file mode 100644 index 00000000..d047f31b --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0083-hrtimer-Update-hrtimer-base-offsets-each-hrtimer_int.patch | |||
@@ -0,0 +1,125 @@ | |||
1 | From 532c526ac9349430b41f6a16f32fc808c4270647 Mon Sep 17 00:00:00 2001 | ||
2 | From: John Stultz <johnstul@us.ibm.com> | ||
3 | Date: Tue, 10 Jul 2012 18:43:25 -0400 | ||
4 | Subject: [PATCH 083/109] hrtimer: Update hrtimer base offsets each | ||
5 | hrtimer_interrupt | ||
6 | |||
7 | commit 5baefd6d84163443215f4a99f6a20f054ef11236 upstream. | ||
8 | |||
9 | The update of the hrtimer base offsets on all cpus cannot be made | ||
10 | atomically from the timekeeper.lock held and interrupt disabled region | ||
11 | as smp function calls are not allowed there. | ||
12 | |||
13 | clock_was_set(), which enforces the update on all cpus, is called | ||
14 | either from preemptible process context in case of do_settimeofday() | ||
15 | or from the softirq context when the offset modification happened in | ||
16 | the timer interrupt itself due to a leap second. | ||
17 | |||
18 | In both cases there is a race window for an hrtimer interrupt between | ||
19 | dropping timekeeper lock, enabling interrupts and clock_was_set() | ||
20 | issuing the updates. Any interrupt which arrives in that window will | ||
21 | see the new time but operate on stale offsets. | ||
22 | |||
23 | So we need to make sure that an hrtimer interrupt always sees a | ||
24 | consistent state of time and offsets. | ||
25 | |||
26 | ktime_get_update_offsets() allows us to get the current monotonic time | ||
27 | and update the per cpu hrtimer base offsets from hrtimer_interrupt() | ||
28 | to capture a consistent state of monotonic time and the offsets. The | ||
29 | function replaces the existing ktime_get() calls in hrtimer_interrupt(). | ||
30 | |||
31 | The overhead of the new function vs. ktime_get() is minimal as it just | ||
32 | adds two store operations. | ||
33 | |||
34 | This ensures that any changes to realtime or boottime offsets are | ||
35 | noticed and stored into the per-cpu hrtimer base structures, prior to | ||
36 | any hrtimer expiration and guarantees that timers are not expired early. | ||
37 | |||
38 | Signed-off-by: John Stultz <johnstul@us.ibm.com> | ||
39 | Reviewed-by: Ingo Molnar <mingo@kernel.org> | ||
40 | Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> | ||
41 | Acked-by: Prarit Bhargava <prarit@redhat.com> | ||
42 | Link: http://lkml.kernel.org/r/1341960205-56738-8-git-send-email-johnstul@us.ibm.com | ||
43 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | ||
44 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | ||
45 | --- | ||
46 | kernel/hrtimer.c | 28 ++++++++++++++-------------- | ||
47 | 1 files changed, 14 insertions(+), 14 deletions(-) | ||
48 | |||
49 | diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c | ||
50 | index 8f320af..6db7a5e 100644 | ||
51 | --- a/kernel/hrtimer.c | ||
52 | +++ b/kernel/hrtimer.c | ||
53 | @@ -657,6 +657,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | +static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) | ||
58 | +{ | ||
59 | + ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; | ||
60 | + ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; | ||
61 | + | ||
62 | + return ktime_get_update_offsets(offs_real, offs_boot); | ||
63 | +} | ||
64 | + | ||
65 | /* | ||
66 | * Retrigger next event is called after clock was set | ||
67 | * | ||
68 | @@ -665,22 +673,12 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | ||
69 | static void retrigger_next_event(void *arg) | ||
70 | { | ||
71 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); | ||
72 | - struct timespec realtime_offset, xtim, wtm, sleep; | ||
73 | |||
74 | if (!hrtimer_hres_active()) | ||
75 | return; | ||
76 | |||
77 | - /* Optimized out for !HIGH_RES */ | ||
78 | - get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); | ||
79 | - set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); | ||
80 | - | ||
81 | - /* Adjust CLOCK_REALTIME offset */ | ||
82 | raw_spin_lock(&base->lock); | ||
83 | - base->clock_base[HRTIMER_BASE_REALTIME].offset = | ||
84 | - timespec_to_ktime(realtime_offset); | ||
85 | - base->clock_base[HRTIMER_BASE_BOOTTIME].offset = | ||
86 | - timespec_to_ktime(sleep); | ||
87 | - | ||
88 | + hrtimer_update_base(base); | ||
89 | hrtimer_force_reprogram(base, 0); | ||
90 | raw_spin_unlock(&base->lock); | ||
91 | } | ||
92 | @@ -710,7 +708,6 @@ static int hrtimer_switch_to_hres(void) | ||
93 | base->clock_base[i].resolution = KTIME_HIGH_RES; | ||
94 | |||
95 | tick_setup_sched_timer(); | ||
96 | - | ||
97 | /* "Retrigger" the interrupt to get things going */ | ||
98 | retrigger_next_event(NULL); | ||
99 | local_irq_restore(flags); | ||
100 | @@ -1264,7 +1261,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) | ||
101 | dev->next_event.tv64 = KTIME_MAX; | ||
102 | |||
103 | raw_spin_lock(&cpu_base->lock); | ||
104 | - entry_time = now = ktime_get(); | ||
105 | + entry_time = now = hrtimer_update_base(cpu_base); | ||
106 | retry: | ||
107 | expires_next.tv64 = KTIME_MAX; | ||
108 | /* | ||
109 | @@ -1342,9 +1339,12 @@ retry: | ||
110 | * We need to prevent that we loop forever in the hrtimer | ||
111 | * interrupt routine. We give it 3 attempts to avoid | ||
112 | * overreacting on some spurious event. | ||
113 | + * | ||
114 | + * Acquire base lock for updating the offsets and retrieving | ||
115 | + * the current time. | ||
116 | */ | ||
117 | raw_spin_lock(&cpu_base->lock); | ||
118 | - now = ktime_get(); | ||
119 | + now = hrtimer_update_base(cpu_base); | ||
120 | cpu_base->nr_retries++; | ||
121 | if (++retries < 3) | ||
122 | goto retry; | ||
123 | -- | ||
124 | 1.7.7.6 | ||
125 | |||