Commit 521c42990e9d561ed5ed9f501f07639d0512b3c9
Committed by
Thomas Gleixner
1 parent
55101e2d6c
Exists in
master
and in
13 other branches
tick-common: Fix wrong check in tick_check_replacement()
tick_check_replacement() returns if a replacement of clock_event_device is possible or not. It does this as the first check: if (tick_check_percpu(curdev, newdev, smp_processor_id())) return false; Thats wrong. tick_check_percpu() returns true when the device is useable. Check for false instead. [ tglx: Massaged changelog ] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: <stable@vger.kernel.org> # v3.11+ Cc: linaro-kernel@lists.linaro.org Cc: fweisbec@gmail.com Cc: Arvind.Chauhan@arm.com Cc: linaro-networking@linaro.org Link: http://lkml.kernel.org/r/486a02efe0246635aaba786e24b42d316438bf3b.1397537987.git.viresh.kumar@linaro.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Showing 1 changed file with 1 additions and 1 deletions Inline Diff
kernel/time/tick-common.c
1 | /* | 1 | /* |
2 | * linux/kernel/time/tick-common.c | 2 | * linux/kernel/time/tick-common.c |
3 | * | 3 | * |
4 | * This file contains the base functions to manage periodic tick | 4 | * This file contains the base functions to manage periodic tick |
5 | * related events. | 5 | * related events. |
6 | * | 6 | * |
7 | * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> | 7 | * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> |
8 | * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar | 8 | * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar |
9 | * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner | 9 | * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner |
10 | * | 10 | * |
11 | * This code is licenced under the GPL version 2. For details see | 11 | * This code is licenced under the GPL version 2. For details see |
12 | * kernel-base/COPYING. | 12 | * kernel-base/COPYING. |
13 | */ | 13 | */ |
14 | #include <linux/cpu.h> | 14 | #include <linux/cpu.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/hrtimer.h> | 16 | #include <linux/hrtimer.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/percpu.h> | 18 | #include <linux/percpu.h> |
19 | #include <linux/profile.h> | 19 | #include <linux/profile.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | 22 | ||
23 | #include <asm/irq_regs.h> | 23 | #include <asm/irq_regs.h> |
24 | 24 | ||
25 | #include "tick-internal.h" | 25 | #include "tick-internal.h" |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Tick devices | 28 | * Tick devices |
29 | */ | 29 | */ |
30 | DEFINE_PER_CPU(struct tick_device, tick_cpu_device); | 30 | DEFINE_PER_CPU(struct tick_device, tick_cpu_device); |
31 | /* | 31 | /* |
32 | * Tick next event: keeps track of the tick time | 32 | * Tick next event: keeps track of the tick time |
33 | */ | 33 | */ |
34 | ktime_t tick_next_period; | 34 | ktime_t tick_next_period; |
35 | ktime_t tick_period; | 35 | ktime_t tick_period; |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * tick_do_timer_cpu is a timer core internal variable which holds the CPU NR | 38 | * tick_do_timer_cpu is a timer core internal variable which holds the CPU NR |
39 | * which is responsible for calling do_timer(), i.e. the timekeeping stuff. This | 39 | * which is responsible for calling do_timer(), i.e. the timekeeping stuff. This |
40 | * variable has two functions: | 40 | * variable has two functions: |
41 | * | 41 | * |
42 | * 1) Prevent a thundering herd issue of a gazillion of CPUs trying to grab the | 42 | * 1) Prevent a thundering herd issue of a gazillion of CPUs trying to grab the |
43 | * timekeeping lock all at once. Only the CPU which is assigned to do the | 43 | * timekeeping lock all at once. Only the CPU which is assigned to do the |
44 | * update is handling it. | 44 | * update is handling it. |
45 | * | 45 | * |
46 | * 2) Hand off the duty in the NOHZ idle case by setting the value to | 46 | * 2) Hand off the duty in the NOHZ idle case by setting the value to |
47 | * TICK_DO_TIMER_NONE, i.e. a non existing CPU. So the next cpu which looks | 47 | * TICK_DO_TIMER_NONE, i.e. a non existing CPU. So the next cpu which looks |
48 | * at it will take over and keep the time keeping alive. The handover | 48 | * at it will take over and keep the time keeping alive. The handover |
49 | * procedure also covers cpu hotplug. | 49 | * procedure also covers cpu hotplug. |
50 | */ | 50 | */ |
51 | int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT; | 51 | int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT; |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Debugging: see timer_list.c | 54 | * Debugging: see timer_list.c |
55 | */ | 55 | */ |
56 | struct tick_device *tick_get_device(int cpu) | 56 | struct tick_device *tick_get_device(int cpu) |
57 | { | 57 | { |
58 | return &per_cpu(tick_cpu_device, cpu); | 58 | return &per_cpu(tick_cpu_device, cpu); |
59 | } | 59 | } |
60 | 60 | ||
61 | /** | 61 | /** |
62 | * tick_is_oneshot_available - check for a oneshot capable event device | 62 | * tick_is_oneshot_available - check for a oneshot capable event device |
63 | */ | 63 | */ |
64 | int tick_is_oneshot_available(void) | 64 | int tick_is_oneshot_available(void) |
65 | { | 65 | { |
66 | struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev); | 66 | struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev); |
67 | 67 | ||
68 | if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT)) | 68 | if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT)) |
69 | return 0; | 69 | return 0; |
70 | if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) | 70 | if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) |
71 | return 1; | 71 | return 1; |
72 | return tick_broadcast_oneshot_available(); | 72 | return tick_broadcast_oneshot_available(); |
73 | } | 73 | } |
74 | 74 | ||
75 | /* | 75 | /* |
76 | * Periodic tick | 76 | * Periodic tick |
77 | */ | 77 | */ |
78 | static void tick_periodic(int cpu) | 78 | static void tick_periodic(int cpu) |
79 | { | 79 | { |
80 | if (tick_do_timer_cpu == cpu) { | 80 | if (tick_do_timer_cpu == cpu) { |
81 | write_seqlock(&jiffies_lock); | 81 | write_seqlock(&jiffies_lock); |
82 | 82 | ||
83 | /* Keep track of the next tick event */ | 83 | /* Keep track of the next tick event */ |
84 | tick_next_period = ktime_add(tick_next_period, tick_period); | 84 | tick_next_period = ktime_add(tick_next_period, tick_period); |
85 | 85 | ||
86 | do_timer(1); | 86 | do_timer(1); |
87 | write_sequnlock(&jiffies_lock); | 87 | write_sequnlock(&jiffies_lock); |
88 | update_wall_time(); | 88 | update_wall_time(); |
89 | } | 89 | } |
90 | 90 | ||
91 | update_process_times(user_mode(get_irq_regs())); | 91 | update_process_times(user_mode(get_irq_regs())); |
92 | profile_tick(CPU_PROFILING); | 92 | profile_tick(CPU_PROFILING); |
93 | } | 93 | } |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * Event handler for periodic ticks | 96 | * Event handler for periodic ticks |
97 | */ | 97 | */ |
98 | void tick_handle_periodic(struct clock_event_device *dev) | 98 | void tick_handle_periodic(struct clock_event_device *dev) |
99 | { | 99 | { |
100 | int cpu = smp_processor_id(); | 100 | int cpu = smp_processor_id(); |
101 | ktime_t next = dev->next_event; | 101 | ktime_t next = dev->next_event; |
102 | 102 | ||
103 | tick_periodic(cpu); | 103 | tick_periodic(cpu); |
104 | 104 | ||
105 | if (dev->mode != CLOCK_EVT_MODE_ONESHOT) | 105 | if (dev->mode != CLOCK_EVT_MODE_ONESHOT) |
106 | return; | 106 | return; |
107 | for (;;) { | 107 | for (;;) { |
108 | /* | 108 | /* |
109 | * Setup the next period for devices, which do not have | 109 | * Setup the next period for devices, which do not have |
110 | * periodic mode: | 110 | * periodic mode: |
111 | */ | 111 | */ |
112 | next = ktime_add(next, tick_period); | 112 | next = ktime_add(next, tick_period); |
113 | 113 | ||
114 | if (!clockevents_program_event(dev, next, false)) | 114 | if (!clockevents_program_event(dev, next, false)) |
115 | return; | 115 | return; |
116 | /* | 116 | /* |
117 | * Have to be careful here. If we're in oneshot mode, | 117 | * Have to be careful here. If we're in oneshot mode, |
118 | * before we call tick_periodic() in a loop, we need | 118 | * before we call tick_periodic() in a loop, we need |
119 | * to be sure we're using a real hardware clocksource. | 119 | * to be sure we're using a real hardware clocksource. |
120 | * Otherwise we could get trapped in an infinite | 120 | * Otherwise we could get trapped in an infinite |
121 | * loop, as the tick_periodic() increments jiffies, | 121 | * loop, as the tick_periodic() increments jiffies, |
122 | * which then will increment time, possibly causing | 122 | * which then will increment time, possibly causing |
123 | * the loop to trigger again and again. | 123 | * the loop to trigger again and again. |
124 | */ | 124 | */ |
125 | if (timekeeping_valid_for_hres()) | 125 | if (timekeeping_valid_for_hres()) |
126 | tick_periodic(cpu); | 126 | tick_periodic(cpu); |
127 | } | 127 | } |
128 | } | 128 | } |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * Setup the device for a periodic tick | 131 | * Setup the device for a periodic tick |
132 | */ | 132 | */ |
133 | void tick_setup_periodic(struct clock_event_device *dev, int broadcast) | 133 | void tick_setup_periodic(struct clock_event_device *dev, int broadcast) |
134 | { | 134 | { |
135 | tick_set_periodic_handler(dev, broadcast); | 135 | tick_set_periodic_handler(dev, broadcast); |
136 | 136 | ||
137 | /* Broadcast setup ? */ | 137 | /* Broadcast setup ? */ |
138 | if (!tick_device_is_functional(dev)) | 138 | if (!tick_device_is_functional(dev)) |
139 | return; | 139 | return; |
140 | 140 | ||
141 | if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) && | 141 | if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) && |
142 | !tick_broadcast_oneshot_active()) { | 142 | !tick_broadcast_oneshot_active()) { |
143 | clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC); | 143 | clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC); |
144 | } else { | 144 | } else { |
145 | unsigned long seq; | 145 | unsigned long seq; |
146 | ktime_t next; | 146 | ktime_t next; |
147 | 147 | ||
148 | do { | 148 | do { |
149 | seq = read_seqbegin(&jiffies_lock); | 149 | seq = read_seqbegin(&jiffies_lock); |
150 | next = tick_next_period; | 150 | next = tick_next_period; |
151 | } while (read_seqretry(&jiffies_lock, seq)); | 151 | } while (read_seqretry(&jiffies_lock, seq)); |
152 | 152 | ||
153 | clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT); | 153 | clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT); |
154 | 154 | ||
155 | for (;;) { | 155 | for (;;) { |
156 | if (!clockevents_program_event(dev, next, false)) | 156 | if (!clockevents_program_event(dev, next, false)) |
157 | return; | 157 | return; |
158 | next = ktime_add(next, tick_period); | 158 | next = ktime_add(next, tick_period); |
159 | } | 159 | } |
160 | } | 160 | } |
161 | } | 161 | } |
162 | 162 | ||
163 | /* | 163 | /* |
164 | * Setup the tick device | 164 | * Setup the tick device |
165 | */ | 165 | */ |
166 | static void tick_setup_device(struct tick_device *td, | 166 | static void tick_setup_device(struct tick_device *td, |
167 | struct clock_event_device *newdev, int cpu, | 167 | struct clock_event_device *newdev, int cpu, |
168 | const struct cpumask *cpumask) | 168 | const struct cpumask *cpumask) |
169 | { | 169 | { |
170 | ktime_t next_event; | 170 | ktime_t next_event; |
171 | void (*handler)(struct clock_event_device *) = NULL; | 171 | void (*handler)(struct clock_event_device *) = NULL; |
172 | 172 | ||
173 | /* | 173 | /* |
174 | * First device setup ? | 174 | * First device setup ? |
175 | */ | 175 | */ |
176 | if (!td->evtdev) { | 176 | if (!td->evtdev) { |
177 | /* | 177 | /* |
178 | * If no cpu took the do_timer update, assign it to | 178 | * If no cpu took the do_timer update, assign it to |
179 | * this cpu: | 179 | * this cpu: |
180 | */ | 180 | */ |
181 | if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) { | 181 | if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) { |
182 | if (!tick_nohz_full_cpu(cpu)) | 182 | if (!tick_nohz_full_cpu(cpu)) |
183 | tick_do_timer_cpu = cpu; | 183 | tick_do_timer_cpu = cpu; |
184 | else | 184 | else |
185 | tick_do_timer_cpu = TICK_DO_TIMER_NONE; | 185 | tick_do_timer_cpu = TICK_DO_TIMER_NONE; |
186 | tick_next_period = ktime_get(); | 186 | tick_next_period = ktime_get(); |
187 | tick_period = ktime_set(0, NSEC_PER_SEC / HZ); | 187 | tick_period = ktime_set(0, NSEC_PER_SEC / HZ); |
188 | } | 188 | } |
189 | 189 | ||
190 | /* | 190 | /* |
191 | * Startup in periodic mode first. | 191 | * Startup in periodic mode first. |
192 | */ | 192 | */ |
193 | td->mode = TICKDEV_MODE_PERIODIC; | 193 | td->mode = TICKDEV_MODE_PERIODIC; |
194 | } else { | 194 | } else { |
195 | handler = td->evtdev->event_handler; | 195 | handler = td->evtdev->event_handler; |
196 | next_event = td->evtdev->next_event; | 196 | next_event = td->evtdev->next_event; |
197 | td->evtdev->event_handler = clockevents_handle_noop; | 197 | td->evtdev->event_handler = clockevents_handle_noop; |
198 | } | 198 | } |
199 | 199 | ||
200 | td->evtdev = newdev; | 200 | td->evtdev = newdev; |
201 | 201 | ||
202 | /* | 202 | /* |
203 | * When the device is not per cpu, pin the interrupt to the | 203 | * When the device is not per cpu, pin the interrupt to the |
204 | * current cpu: | 204 | * current cpu: |
205 | */ | 205 | */ |
206 | if (!cpumask_equal(newdev->cpumask, cpumask)) | 206 | if (!cpumask_equal(newdev->cpumask, cpumask)) |
207 | irq_set_affinity(newdev->irq, cpumask); | 207 | irq_set_affinity(newdev->irq, cpumask); |
208 | 208 | ||
209 | /* | 209 | /* |
210 | * When global broadcasting is active, check if the current | 210 | * When global broadcasting is active, check if the current |
211 | * device is registered as a placeholder for broadcast mode. | 211 | * device is registered as a placeholder for broadcast mode. |
212 | * This allows us to handle this x86 misfeature in a generic | 212 | * This allows us to handle this x86 misfeature in a generic |
213 | * way. This function also returns !=0 when we keep the | 213 | * way. This function also returns !=0 when we keep the |
214 | * current active broadcast state for this CPU. | 214 | * current active broadcast state for this CPU. |
215 | */ | 215 | */ |
216 | if (tick_device_uses_broadcast(newdev, cpu)) | 216 | if (tick_device_uses_broadcast(newdev, cpu)) |
217 | return; | 217 | return; |
218 | 218 | ||
219 | if (td->mode == TICKDEV_MODE_PERIODIC) | 219 | if (td->mode == TICKDEV_MODE_PERIODIC) |
220 | tick_setup_periodic(newdev, 0); | 220 | tick_setup_periodic(newdev, 0); |
221 | else | 221 | else |
222 | tick_setup_oneshot(newdev, handler, next_event); | 222 | tick_setup_oneshot(newdev, handler, next_event); |
223 | } | 223 | } |
224 | 224 | ||
225 | void tick_install_replacement(struct clock_event_device *newdev) | 225 | void tick_install_replacement(struct clock_event_device *newdev) |
226 | { | 226 | { |
227 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); | 227 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); |
228 | int cpu = smp_processor_id(); | 228 | int cpu = smp_processor_id(); |
229 | 229 | ||
230 | clockevents_exchange_device(td->evtdev, newdev); | 230 | clockevents_exchange_device(td->evtdev, newdev); |
231 | tick_setup_device(td, newdev, cpu, cpumask_of(cpu)); | 231 | tick_setup_device(td, newdev, cpu, cpumask_of(cpu)); |
232 | if (newdev->features & CLOCK_EVT_FEAT_ONESHOT) | 232 | if (newdev->features & CLOCK_EVT_FEAT_ONESHOT) |
233 | tick_oneshot_notify(); | 233 | tick_oneshot_notify(); |
234 | } | 234 | } |
235 | 235 | ||
236 | static bool tick_check_percpu(struct clock_event_device *curdev, | 236 | static bool tick_check_percpu(struct clock_event_device *curdev, |
237 | struct clock_event_device *newdev, int cpu) | 237 | struct clock_event_device *newdev, int cpu) |
238 | { | 238 | { |
239 | if (!cpumask_test_cpu(cpu, newdev->cpumask)) | 239 | if (!cpumask_test_cpu(cpu, newdev->cpumask)) |
240 | return false; | 240 | return false; |
241 | if (cpumask_equal(newdev->cpumask, cpumask_of(cpu))) | 241 | if (cpumask_equal(newdev->cpumask, cpumask_of(cpu))) |
242 | return true; | 242 | return true; |
243 | /* Check if irq affinity can be set */ | 243 | /* Check if irq affinity can be set */ |
244 | if (newdev->irq >= 0 && !irq_can_set_affinity(newdev->irq)) | 244 | if (newdev->irq >= 0 && !irq_can_set_affinity(newdev->irq)) |
245 | return false; | 245 | return false; |
246 | /* Prefer an existing cpu local device */ | 246 | /* Prefer an existing cpu local device */ |
247 | if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) | 247 | if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu))) |
248 | return false; | 248 | return false; |
249 | return true; | 249 | return true; |
250 | } | 250 | } |
251 | 251 | ||
252 | static bool tick_check_preferred(struct clock_event_device *curdev, | 252 | static bool tick_check_preferred(struct clock_event_device *curdev, |
253 | struct clock_event_device *newdev) | 253 | struct clock_event_device *newdev) |
254 | { | 254 | { |
255 | /* Prefer oneshot capable device */ | 255 | /* Prefer oneshot capable device */ |
256 | if (!(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) { | 256 | if (!(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) { |
257 | if (curdev && (curdev->features & CLOCK_EVT_FEAT_ONESHOT)) | 257 | if (curdev && (curdev->features & CLOCK_EVT_FEAT_ONESHOT)) |
258 | return false; | 258 | return false; |
259 | if (tick_oneshot_mode_active()) | 259 | if (tick_oneshot_mode_active()) |
260 | return false; | 260 | return false; |
261 | } | 261 | } |
262 | 262 | ||
263 | /* | 263 | /* |
264 | * Use the higher rated one, but prefer a CPU local device with a lower | 264 | * Use the higher rated one, but prefer a CPU local device with a lower |
265 | * rating than a non-CPU local device | 265 | * rating than a non-CPU local device |
266 | */ | 266 | */ |
267 | return !curdev || | 267 | return !curdev || |
268 | newdev->rating > curdev->rating || | 268 | newdev->rating > curdev->rating || |
269 | !cpumask_equal(curdev->cpumask, newdev->cpumask); | 269 | !cpumask_equal(curdev->cpumask, newdev->cpumask); |
270 | } | 270 | } |
271 | 271 | ||
272 | /* | 272 | /* |
273 | * Check whether the new device is a better fit than curdev. curdev | 273 | * Check whether the new device is a better fit than curdev. curdev |
274 | * can be NULL ! | 274 | * can be NULL ! |
275 | */ | 275 | */ |
276 | bool tick_check_replacement(struct clock_event_device *curdev, | 276 | bool tick_check_replacement(struct clock_event_device *curdev, |
277 | struct clock_event_device *newdev) | 277 | struct clock_event_device *newdev) |
278 | { | 278 | { |
279 | if (tick_check_percpu(curdev, newdev, smp_processor_id())) | 279 | if (!tick_check_percpu(curdev, newdev, smp_processor_id())) |
280 | return false; | 280 | return false; |
281 | 281 | ||
282 | return tick_check_preferred(curdev, newdev); | 282 | return tick_check_preferred(curdev, newdev); |
283 | } | 283 | } |
284 | 284 | ||
285 | /* | 285 | /* |
286 | * Check, if the new registered device should be used. Called with | 286 | * Check, if the new registered device should be used. Called with |
287 | * clockevents_lock held and interrupts disabled. | 287 | * clockevents_lock held and interrupts disabled. |
288 | */ | 288 | */ |
289 | void tick_check_new_device(struct clock_event_device *newdev) | 289 | void tick_check_new_device(struct clock_event_device *newdev) |
290 | { | 290 | { |
291 | struct clock_event_device *curdev; | 291 | struct clock_event_device *curdev; |
292 | struct tick_device *td; | 292 | struct tick_device *td; |
293 | int cpu; | 293 | int cpu; |
294 | 294 | ||
295 | cpu = smp_processor_id(); | 295 | cpu = smp_processor_id(); |
296 | if (!cpumask_test_cpu(cpu, newdev->cpumask)) | 296 | if (!cpumask_test_cpu(cpu, newdev->cpumask)) |
297 | goto out_bc; | 297 | goto out_bc; |
298 | 298 | ||
299 | td = &per_cpu(tick_cpu_device, cpu); | 299 | td = &per_cpu(tick_cpu_device, cpu); |
300 | curdev = td->evtdev; | 300 | curdev = td->evtdev; |
301 | 301 | ||
302 | /* cpu local device ? */ | 302 | /* cpu local device ? */ |
303 | if (!tick_check_percpu(curdev, newdev, cpu)) | 303 | if (!tick_check_percpu(curdev, newdev, cpu)) |
304 | goto out_bc; | 304 | goto out_bc; |
305 | 305 | ||
306 | /* Preference decision */ | 306 | /* Preference decision */ |
307 | if (!tick_check_preferred(curdev, newdev)) | 307 | if (!tick_check_preferred(curdev, newdev)) |
308 | goto out_bc; | 308 | goto out_bc; |
309 | 309 | ||
310 | if (!try_module_get(newdev->owner)) | 310 | if (!try_module_get(newdev->owner)) |
311 | return; | 311 | return; |
312 | 312 | ||
313 | /* | 313 | /* |
314 | * Replace the eventually existing device by the new | 314 | * Replace the eventually existing device by the new |
315 | * device. If the current device is the broadcast device, do | 315 | * device. If the current device is the broadcast device, do |
316 | * not give it back to the clockevents layer ! | 316 | * not give it back to the clockevents layer ! |
317 | */ | 317 | */ |
318 | if (tick_is_broadcast_device(curdev)) { | 318 | if (tick_is_broadcast_device(curdev)) { |
319 | clockevents_shutdown(curdev); | 319 | clockevents_shutdown(curdev); |
320 | curdev = NULL; | 320 | curdev = NULL; |
321 | } | 321 | } |
322 | clockevents_exchange_device(curdev, newdev); | 322 | clockevents_exchange_device(curdev, newdev); |
323 | tick_setup_device(td, newdev, cpu, cpumask_of(cpu)); | 323 | tick_setup_device(td, newdev, cpu, cpumask_of(cpu)); |
324 | if (newdev->features & CLOCK_EVT_FEAT_ONESHOT) | 324 | if (newdev->features & CLOCK_EVT_FEAT_ONESHOT) |
325 | tick_oneshot_notify(); | 325 | tick_oneshot_notify(); |
326 | return; | 326 | return; |
327 | 327 | ||
328 | out_bc: | 328 | out_bc: |
329 | /* | 329 | /* |
330 | * Can the new device be used as a broadcast device ? | 330 | * Can the new device be used as a broadcast device ? |
331 | */ | 331 | */ |
332 | tick_install_broadcast_device(newdev); | 332 | tick_install_broadcast_device(newdev); |
333 | } | 333 | } |
334 | 334 | ||
335 | /* | 335 | /* |
336 | * Transfer the do_timer job away from a dying cpu. | 336 | * Transfer the do_timer job away from a dying cpu. |
337 | * | 337 | * |
338 | * Called with interrupts disabled. | 338 | * Called with interrupts disabled. |
339 | */ | 339 | */ |
340 | void tick_handover_do_timer(int *cpup) | 340 | void tick_handover_do_timer(int *cpup) |
341 | { | 341 | { |
342 | if (*cpup == tick_do_timer_cpu) { | 342 | if (*cpup == tick_do_timer_cpu) { |
343 | int cpu = cpumask_first(cpu_online_mask); | 343 | int cpu = cpumask_first(cpu_online_mask); |
344 | 344 | ||
345 | tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu : | 345 | tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu : |
346 | TICK_DO_TIMER_NONE; | 346 | TICK_DO_TIMER_NONE; |
347 | } | 347 | } |
348 | } | 348 | } |
349 | 349 | ||
350 | /* | 350 | /* |
351 | * Shutdown an event device on a given cpu: | 351 | * Shutdown an event device on a given cpu: |
352 | * | 352 | * |
353 | * This is called on a life CPU, when a CPU is dead. So we cannot | 353 | * This is called on a life CPU, when a CPU is dead. So we cannot |
354 | * access the hardware device itself. | 354 | * access the hardware device itself. |
355 | * We just set the mode and remove it from the lists. | 355 | * We just set the mode and remove it from the lists. |
356 | */ | 356 | */ |
357 | void tick_shutdown(unsigned int *cpup) | 357 | void tick_shutdown(unsigned int *cpup) |
358 | { | 358 | { |
359 | struct tick_device *td = &per_cpu(tick_cpu_device, *cpup); | 359 | struct tick_device *td = &per_cpu(tick_cpu_device, *cpup); |
360 | struct clock_event_device *dev = td->evtdev; | 360 | struct clock_event_device *dev = td->evtdev; |
361 | 361 | ||
362 | td->mode = TICKDEV_MODE_PERIODIC; | 362 | td->mode = TICKDEV_MODE_PERIODIC; |
363 | if (dev) { | 363 | if (dev) { |
364 | /* | 364 | /* |
365 | * Prevent that the clock events layer tries to call | 365 | * Prevent that the clock events layer tries to call |
366 | * the set mode function! | 366 | * the set mode function! |
367 | */ | 367 | */ |
368 | dev->mode = CLOCK_EVT_MODE_UNUSED; | 368 | dev->mode = CLOCK_EVT_MODE_UNUSED; |
369 | clockevents_exchange_device(dev, NULL); | 369 | clockevents_exchange_device(dev, NULL); |
370 | dev->event_handler = clockevents_handle_noop; | 370 | dev->event_handler = clockevents_handle_noop; |
371 | td->evtdev = NULL; | 371 | td->evtdev = NULL; |
372 | } | 372 | } |
373 | } | 373 | } |
374 | 374 | ||
375 | void tick_suspend(void) | 375 | void tick_suspend(void) |
376 | { | 376 | { |
377 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); | 377 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); |
378 | 378 | ||
379 | clockevents_shutdown(td->evtdev); | 379 | clockevents_shutdown(td->evtdev); |
380 | } | 380 | } |
381 | 381 | ||
382 | void tick_resume(void) | 382 | void tick_resume(void) |
383 | { | 383 | { |
384 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); | 384 | struct tick_device *td = &__get_cpu_var(tick_cpu_device); |
385 | int broadcast = tick_resume_broadcast(); | 385 | int broadcast = tick_resume_broadcast(); |
386 | 386 | ||
387 | clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME); | 387 | clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME); |
388 | 388 | ||
389 | if (!broadcast) { | 389 | if (!broadcast) { |
390 | if (td->mode == TICKDEV_MODE_PERIODIC) | 390 | if (td->mode == TICKDEV_MODE_PERIODIC) |
391 | tick_setup_periodic(td->evtdev, 0); | 391 | tick_setup_periodic(td->evtdev, 0); |
392 | else | 392 | else |
393 | tick_resume_oneshot(); | 393 | tick_resume_oneshot(); |
394 | } | 394 | } |
395 | } | 395 | } |
396 | 396 | ||
397 | /** | 397 | /** |
398 | * tick_init - initialize the tick control | 398 | * tick_init - initialize the tick control |
399 | */ | 399 | */ |
400 | void __init tick_init(void) | 400 | void __init tick_init(void) |
401 | { | 401 | { |
402 | tick_broadcast_init(); | 402 | tick_broadcast_init(); |
403 | } | 403 | } |
404 | 404 |