clock events: allow replacement of broadcast timer
[powerpc.git] / kernel / time / tick-broadcast.c
index db8e0f3..298bc7c 100644 (file)
@@ -64,8 +64,9 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc)
  */
 int tick_check_broadcast_device(struct clock_event_device *dev)
 {
-       if (tick_broadcast_device.evtdev ||
-           (dev->features & CLOCK_EVT_FEAT_C3STOP))
+       if ((tick_broadcast_device.evtdev &&
+            tick_broadcast_device.evtdev->rating >= dev->rating) ||
+            (dev->features & CLOCK_EVT_FEAT_C3STOP))
                return 0;
 
        clockevents_exchange_device(NULL, dev);
@@ -176,8 +177,6 @@ static void tick_do_periodic_broadcast(void)
  */
 static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
 {
-       dev->next_event.tv64 = KTIME_MAX;
-
        tick_do_periodic_broadcast();
 
        /*
@@ -383,11 +382,7 @@ 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);
+       return 0;
 }
 
 /*
@@ -519,11 +514,9 @@ static void tick_broadcast_clear_oneshot(int cpu)
  */
 void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
-       if (bc->mode != CLOCK_EVT_MODE_ONESHOT) {
-               bc->event_handler = tick_handle_oneshot_broadcast;
-               clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
-               bc->next_event.tv64 = KTIME_MAX;
-       }
+       bc->event_handler = tick_handle_oneshot_broadcast;
+       clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+       bc->next_event.tv64 = KTIME_MAX;
 }
 
 /*
@@ -549,20 +542,17 @@ void tick_broadcast_switch_to_oneshot(void)
  */
 void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
 {
-       struct clock_event_device *bc;
        unsigned long flags;
        unsigned int cpu = *cpup;
 
        spin_lock_irqsave(&tick_broadcast_lock, flags);
 
-       bc = tick_broadcast_device.evtdev;
+       /*
+        * Clear the broadcast mask flag for the dead cpu, but do not
+        * stop the broadcast device!
+        */
        cpu_clear(cpu, tick_broadcast_oneshot_mask);
 
-       if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT) {
-               if (bc && cpus_empty(tick_broadcast_oneshot_mask))
-                       clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
-       }
-
        spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }