These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / kernel / time / tick-broadcast-hrtimer.c
index 6aac4be..1b4ac33 100644 (file)
 
 static struct hrtimer bctimer;
 
-static void bc_set_mode(enum clock_event_mode mode,
-                       struct clock_event_device *bc)
+static int bc_shutdown(struct clock_event_device *evt)
 {
-       switch (mode) {
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               /*
-                * Note, we cannot cancel the timer here as we might
-                * run into the following live lock scenario:
-                *
-                * cpu 0                cpu1
-                * lock(broadcast_lock);
-                *                      hrtimer_interrupt()
-                *                      bc_handler()
-                *                         tick_handle_oneshot_broadcast();
-                *                          lock(broadcast_lock);
-                * hrtimer_cancel()
-                *  wait_for_callback()
-                */
-               hrtimer_try_to_cancel(&bctimer);
-               break;
-       default:
-               break;
-       }
+       /*
+        * Note, we cannot cancel the timer here as we might
+        * run into the following live lock scenario:
+        *
+        * cpu 0                cpu1
+        * lock(broadcast_lock);
+        *                      hrtimer_interrupt()
+        *                      bc_handler()
+        *                         tick_handle_oneshot_broadcast();
+        *                          lock(broadcast_lock);
+        * hrtimer_cancel()
+        *  wait_for_callback()
+        */
+       hrtimer_try_to_cancel(&bctimer);
+       return 0;
 }
 
 /*
@@ -66,9 +60,11 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
         * hrtimer_{start/cancel} functions call into tracing,
         * calls to these functions must be bound within RCU_NONIDLE.
         */
-       RCU_NONIDLE(bc_moved = (hrtimer_try_to_cancel(&bctimer) >= 0) ?
-               !hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED) :
-                       0);
+       RCU_NONIDLE({
+                       bc_moved = hrtimer_try_to_cancel(&bctimer) >= 0;
+                       if (bc_moved)
+                               hrtimer_start(&bctimer, expires,
+                                             HRTIMER_MODE_ABS_PINNED);});
        if (bc_moved) {
                /* Bind the "device" to the cpu */
                bc->bound_on = smp_processor_id();
@@ -79,7 +75,7 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
 }
 
 static struct clock_event_device ce_broadcast_hrtimer = {
-       .set_mode               = bc_set_mode,
+       .set_state_shutdown     = bc_shutdown,
        .set_next_ktime         = bc_set_next,
        .features               = CLOCK_EVT_FEAT_ONESHOT |
                                  CLOCK_EVT_FEAT_KTIME |
@@ -99,15 +95,17 @@ static enum hrtimer_restart bc_handler(struct hrtimer *t)
 {
        ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer);
 
-       if (ce_broadcast_hrtimer.next_event.tv64 == KTIME_MAX)
-               return HRTIMER_NORESTART;
+       if (clockevent_state_oneshot(&ce_broadcast_hrtimer))
+               if (ce_broadcast_hrtimer.next_event.tv64 != KTIME_MAX)
+                       return HRTIMER_RESTART;
 
-       return HRTIMER_RESTART;
+       return HRTIMER_NORESTART;
 }
 
 void tick_setup_hrtimer_broadcast(void)
 {
        hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
        bctimer.function = bc_handler;
+       bctimer.irqsafe = true;
        clockevents_register_device(&ce_broadcast_hrtimer);
 }