aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/tick-broadcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/tick-broadcast.c')
-rw-r--r--kernel/time/tick-broadcast.c85
1 files changed, 61 insertions, 24 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 31463d370b9..f1f3eee2811 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -175,6 +175,8 @@ static void tick_do_periodic_broadcast(void)
175 */ 175 */
176static void tick_handle_periodic_broadcast(struct clock_event_device *dev) 176static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
177{ 177{
178 ktime_t next;
179
178 tick_do_periodic_broadcast(); 180 tick_do_periodic_broadcast();
179 181
180 /* 182 /*
@@ -185,10 +187,13 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
185 187
186 /* 188 /*
187 * Setup the next period for devices, which do not have 189 * Setup the next period for devices, which do not have
188 * periodic mode: 190 * periodic mode. We read dev->next_event first and add to it
191 * when the event alrady expired. clockevents_program_event()
192 * sets dev->next_event only when the event is really
193 * programmed to the device.
189 */ 194 */
190 for (;;) { 195 for (next = dev->next_event; ;) {
191 ktime_t next = ktime_add(dev->next_event, tick_period); 196 next = ktime_add(next, tick_period);
192 197
193 if (!clockevents_program_event(dev, next, ktime_get())) 198 if (!clockevents_program_event(dev, next, ktime_get()))
194 return; 199 return;
@@ -205,7 +210,7 @@ static void tick_do_broadcast_on_off(void *why)
205 struct clock_event_device *bc, *dev; 210 struct clock_event_device *bc, *dev;
206 struct tick_device *td; 211 struct tick_device *td;
207 unsigned long flags, *reason = why; 212 unsigned long flags, *reason = why;
208 int cpu; 213 int cpu, bc_stopped;
209 214
210 spin_lock_irqsave(&tick_broadcast_lock, flags); 215 spin_lock_irqsave(&tick_broadcast_lock, flags);
211 216
@@ -223,14 +228,15 @@ static void tick_do_broadcast_on_off(void *why)
223 if (!tick_device_is_functional(dev)) 228 if (!tick_device_is_functional(dev))
224 goto out; 229 goto out;
225 230
231 bc_stopped = cpus_empty(tick_broadcast_mask);
232
226 switch (*reason) { 233 switch (*reason) {
227 case CLOCK_EVT_NOTIFY_BROADCAST_ON: 234 case CLOCK_EVT_NOTIFY_BROADCAST_ON:
228 case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: 235 case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
229 if (!cpu_isset(cpu, tick_broadcast_mask)) { 236 if (!cpu_isset(cpu, tick_broadcast_mask)) {
230 cpu_set(cpu, tick_broadcast_mask); 237 cpu_set(cpu, tick_broadcast_mask);
231 if (td->mode == TICKDEV_MODE_PERIODIC) 238 if (td->mode == TICKDEV_MODE_PERIODIC)
232 clockevents_set_mode(dev, 239 clockevents_shutdown(dev);
233 CLOCK_EVT_MODE_SHUTDOWN);
234 } 240 }
235 if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) 241 if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
236 tick_broadcast_force = 1; 242 tick_broadcast_force = 1;
@@ -245,9 +251,10 @@ static void tick_do_broadcast_on_off(void *why)
245 break; 251 break;
246 } 252 }
247 253
248 if (cpus_empty(tick_broadcast_mask)) 254 if (cpus_empty(tick_broadcast_mask)) {
249 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 255 if (!bc_stopped)
250 else { 256 clockevents_shutdown(bc);
257 } else if (bc_stopped) {
251 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) 258 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
252 tick_broadcast_start_periodic(bc); 259 tick_broadcast_start_periodic(bc);
253 else 260 else
@@ -298,7 +305,7 @@ void tick_shutdown_broadcast(unsigned int *cpup)
298 305
299 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { 306 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
300 if (bc && cpus_empty(tick_broadcast_mask)) 307 if (bc && cpus_empty(tick_broadcast_mask))
301 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 308 clockevents_shutdown(bc);
302 } 309 }
303 310
304 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 311 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
@@ -313,7 +320,7 @@ void tick_suspend_broadcast(void)
313 320
314 bc = tick_broadcast_device.evtdev; 321 bc = tick_broadcast_device.evtdev;
315 if (bc) 322 if (bc)
316 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 323 clockevents_shutdown(bc);
317 324
318 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 325 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
319} 326}
@@ -364,16 +371,8 @@ cpumask_t *tick_get_broadcast_oneshot_mask(void)
364static int tick_broadcast_set_event(ktime_t expires, int force) 371static int tick_broadcast_set_event(ktime_t expires, int force)
365{ 372{
366 struct clock_event_device *bc = tick_broadcast_device.evtdev; 373 struct clock_event_device *bc = tick_broadcast_device.evtdev;
367 ktime_t now = ktime_get(); 374
368 int res; 375 return tick_dev_program_event(bc, expires, force);
369
370 for(;;) {
371 res = clockevents_program_event(bc, expires, now);
372 if (!res || !force)
373 return res;
374 now = ktime_get();
375 expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
376 }
377} 376}
378 377
379int tick_resume_broadcast_oneshot(struct clock_event_device *bc) 378int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
@@ -491,14 +490,52 @@ static void tick_broadcast_clear_oneshot(int cpu)
491 cpu_clear(cpu, tick_broadcast_oneshot_mask); 490 cpu_clear(cpu, tick_broadcast_oneshot_mask);
492} 491}
493 492
493static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
494{
495 struct tick_device *td;
496 int cpu;
497
498 for_each_cpu_mask_nr(cpu, *mask) {
499 td = &per_cpu(tick_cpu_device, cpu);
500 if (td->evtdev)
501 td->evtdev->next_event = expires;
502 }
503}
504
494/** 505/**
495 * tick_broadcast_setup_oneshot - setup the broadcast device 506 * tick_broadcast_setup_oneshot - setup the broadcast device
496 */ 507 */
497void tick_broadcast_setup_oneshot(struct clock_event_device *bc) 508void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
498{ 509{
499 bc->event_handler = tick_handle_oneshot_broadcast; 510 /* Set it up only once ! */
500 clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); 511 if (bc->event_handler != tick_handle_oneshot_broadcast) {
501 bc->next_event.tv64 = KTIME_MAX; 512 int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
513 int cpu = smp_processor_id();
514 cpumask_t mask;
515
516 bc->event_handler = tick_handle_oneshot_broadcast;
517 clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
518
519 /* Take the do_timer update */
520 tick_do_timer_cpu = cpu;
521
522 /*
523 * We must be careful here. There might be other CPUs
524 * waiting for periodic broadcast. We need to set the
525 * oneshot_mask bits for those and program the
526 * broadcast device to fire.
527 */
528 mask = tick_broadcast_mask;
529 cpu_clear(cpu, mask);
530 cpus_or(tick_broadcast_oneshot_mask,
531 tick_broadcast_oneshot_mask, mask);
532
533 if (was_periodic && !cpus_empty(mask)) {
534 tick_broadcast_init_next_event(&mask, tick_next_period);
535 tick_broadcast_set_event(tick_next_period, 1);
536 } else
537 bc->next_event.tv64 = KTIME_MAX;
538 }
502} 539}
503 540
504/* 541/*