Merge branch 'drm-patches' of ssh://master.kernel.org/pub/scm/linux/kernel/git/airlie...
[pandora-kernel.git] / kernel / time / tick-broadcast.c
index 5567745..8001d37 100644 (file)
@@ -243,11 +243,18 @@ void tick_broadcast_on_off(unsigned long reason, int *oncpu)
 {
        int cpu = get_cpu();
 
-       if (cpu == *oncpu)
-               tick_do_broadcast_on_off(&reason);
-       else
-               smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
-                                        &reason, 1, 1);
+       if (!cpu_isset(*oncpu, cpu_online_map)) {
+               printk(KERN_ERR "tick-braodcast: ignoring broadcast for "
+                      "offline CPU #%d\n", *oncpu);
+       } else {
+
+               if (cpu == *oncpu)
+                       tick_do_broadcast_on_off(&reason);
+               else
+                       smp_call_function_single(*oncpu,
+                                                tick_do_broadcast_on_off,
+                                                &reason, 1, 1);
+       }
        put_cpu();
 }
 
@@ -307,12 +314,19 @@ int tick_resume_broadcast(void)
        spin_lock_irqsave(&tick_broadcast_lock, flags);
 
        bc = tick_broadcast_device.evtdev;
-       if (bc) {
-               if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC &&
-                   !cpus_empty(tick_broadcast_mask))
-                       tick_broadcast_start_periodic(bc);
 
-               broadcast = cpu_isset(smp_processor_id(), tick_broadcast_mask);
+       if (bc) {
+               switch (tick_broadcast_device.mode) {
+               case TICKDEV_MODE_PERIODIC:
+                       if(!cpus_empty(tick_broadcast_mask))
+                               tick_broadcast_start_periodic(bc);
+                       broadcast = cpu_isset(smp_processor_id(),
+                                             tick_broadcast_mask);
+                       break;
+               case TICKDEV_MODE_ONESHOT:
+                       broadcast = tick_resume_broadcast_oneshot(bc);
+                       break;
+               }
        }
        spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 
@@ -347,6 +361,16 @@ static int tick_broadcast_set_event(ktime_t expires, int force)
        }
 }
 
+int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
+{
+       clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+
+       if(!cpus_empty(tick_broadcast_oneshot_mask))
+               tick_broadcast_set_event(ktime_get(), 1);
+
+       return cpu_isset(smp_processor_id(), tick_broadcast_oneshot_mask);
+}
+
 /*
  * Reprogram the broadcast device:
  *