These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / kernel / time / clockevents.c
index 637a094..a9b76a4 100644 (file)
@@ -94,23 +94,9 @@ u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt)
 }
 EXPORT_SYMBOL_GPL(clockevent_delta2ns);
 
-static int __clockevents_set_state(struct clock_event_device *dev,
-                                  enum clock_event_state state)
+static int __clockevents_switch_state(struct clock_event_device *dev,
+                                     enum clock_event_state state)
 {
-       /* Transition with legacy set_mode() callback */
-       if (dev->set_mode) {
-               /* Legacy callback doesn't support new modes */
-               if (state > CLOCK_EVT_STATE_ONESHOT)
-                       return -ENOSYS;
-               /*
-                * 'clock_event_state' and 'clock_event_mode' have 1-to-1
-                * mapping until *_ONESHOT, and so a simple cast will work.
-                */
-               dev->set_mode((enum clock_event_mode)state, dev);
-               dev->mode = (enum clock_event_mode)state;
-               return 0;
-       }
-
        if (dev->features & CLOCK_EVT_FEAT_DUMMY)
                return 0;
 
@@ -120,19 +106,37 @@ static int __clockevents_set_state(struct clock_event_device *dev,
                /* The clockevent device is getting replaced. Shut it down. */
 
        case CLOCK_EVT_STATE_SHUTDOWN:
-               return dev->set_state_shutdown(dev);
+               if (dev->set_state_shutdown)
+                       return dev->set_state_shutdown(dev);
+               return 0;
 
        case CLOCK_EVT_STATE_PERIODIC:
                /* Core internal bug */
                if (!(dev->features & CLOCK_EVT_FEAT_PERIODIC))
                        return -ENOSYS;
-               return dev->set_state_periodic(dev);
+               if (dev->set_state_periodic)
+                       return dev->set_state_periodic(dev);
+               return 0;
 
        case CLOCK_EVT_STATE_ONESHOT:
                /* Core internal bug */
                if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))
                        return -ENOSYS;
-               return dev->set_state_oneshot(dev);
+               if (dev->set_state_oneshot)
+                       return dev->set_state_oneshot(dev);
+               return 0;
+
+       case CLOCK_EVT_STATE_ONESHOT_STOPPED:
+               /* Core internal bug */
+               if (WARN_ONCE(!clockevent_state_oneshot(dev),
+                             "Current state: %d\n",
+                             clockevent_get_state(dev)))
+                       return -EINVAL;
+
+               if (dev->set_state_oneshot_stopped)
+                       return dev->set_state_oneshot_stopped(dev);
+               else
+                       return -ENOSYS;
 
        default:
                return -ENOSYS;
@@ -140,26 +144,26 @@ static int __clockevents_set_state(struct clock_event_device *dev,
 }
 
 /**
- * clockevents_set_state - set the operating state of a clock event device
+ * clockevents_switch_state - set the operating state of a clock event device
  * @dev:       device to modify
  * @state:     new state
  *
  * Must be called with interrupts disabled !
  */
-void clockevents_set_state(struct clock_event_device *dev,
-                          enum clock_event_state state)
+void clockevents_switch_state(struct clock_event_device *dev,
+                             enum clock_event_state state)
 {
-       if (dev->state != state) {
-               if (__clockevents_set_state(dev, state))
+       if (clockevent_get_state(dev) != state) {
+               if (__clockevents_switch_state(dev, state))
                        return;
 
-               dev->state = state;
+               clockevent_set_state(dev, state);
 
                /*
                 * A nsec2cyc multiplicator of 0 is invalid and we'd crash
                 * on it, so fix it up and emit a warning:
                 */
-               if (state == CLOCK_EVT_STATE_ONESHOT) {
+               if (clockevent_state_oneshot(dev)) {
                        if (unlikely(!dev->mult)) {
                                dev->mult = 1;
                                WARN_ON(1);
@@ -174,7 +178,7 @@ void clockevents_set_state(struct clock_event_device *dev,
  */
 void clockevents_shutdown(struct clock_event_device *dev)
 {
-       clockevents_set_state(dev, CLOCK_EVT_STATE_SHUTDOWN);
+       clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN);
        dev->next_event.tv64 = KTIME_MAX;
 }
 
@@ -186,12 +190,8 @@ int clockevents_tick_resume(struct clock_event_device *dev)
 {
        int ret = 0;
 
-       if (dev->set_mode) {
-               dev->set_mode(CLOCK_EVT_MODE_RESUME, dev);
-               dev->mode = CLOCK_EVT_MODE_RESUME;
-       } else if (dev->tick_resume) {
+       if (dev->tick_resume)
                ret = dev->tick_resume(dev);
-       }
 
        return ret;
 }
@@ -248,7 +248,7 @@ static int clockevents_program_min_delta(struct clock_event_device *dev)
                delta = dev->min_delta_ns;
                dev->next_event = ktime_add_ns(ktime_get(), delta);
 
-               if (dev->state == CLOCK_EVT_STATE_SHUTDOWN)
+               if (clockevent_state_shutdown(dev))
                        return 0;
 
                dev->retries++;
@@ -285,7 +285,7 @@ static int clockevents_program_min_delta(struct clock_event_device *dev)
        delta = dev->min_delta_ns;
        dev->next_event = ktime_add_ns(ktime_get(), delta);
 
-       if (dev->state == CLOCK_EVT_STATE_SHUTDOWN)
+       if (clockevent_state_shutdown(dev))
                return 0;
 
        dev->retries++;
@@ -317,9 +317,13 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
 
        dev->next_event = expires;
 
-       if (dev->state == CLOCK_EVT_STATE_SHUTDOWN)
+       if (clockevent_state_shutdown(dev))
                return 0;
 
+       /* We must be in ONESHOT state here */
+       WARN_ONCE(!clockevent_state_oneshot(dev), "Current state: %d\n",
+                 clockevent_get_state(dev));
+
        /* Shortcut for clockevent devices that can deal with ktime. */
        if (dev->features & CLOCK_EVT_FEAT_KTIME)
                return dev->set_next_ktime(expires, dev);
@@ -362,7 +366,7 @@ static int clockevents_replace(struct clock_event_device *ced)
        struct clock_event_device *dev, *newdev = NULL;
 
        list_for_each_entry(dev, &clockevent_devices, list) {
-               if (dev == ced || dev->state != CLOCK_EVT_STATE_DETACHED)
+               if (dev == ced || !clockevent_state_detached(dev))
                        continue;
 
                if (!tick_check_replacement(newdev, dev))
@@ -388,7 +392,7 @@ static int clockevents_replace(struct clock_event_device *ced)
 static int __clockevents_try_unbind(struct clock_event_device *ced, int cpu)
 {
        /* Fast track. Device is unused */
-       if (ced->state == CLOCK_EVT_STATE_DETACHED) {
+       if (clockevent_state_detached(ced)) {
                list_del_init(&ced->list);
                return 0;
        }
@@ -438,37 +442,6 @@ int clockevents_unbind_device(struct clock_event_device *ced, int cpu)
 }
 EXPORT_SYMBOL_GPL(clockevents_unbind_device);
 
-/* Sanity check of state transition callbacks */
-static int clockevents_sanity_check(struct clock_event_device *dev)
-{
-       /* Legacy set_mode() callback */
-       if (dev->set_mode) {
-               /* We shouldn't be supporting new modes now */
-               WARN_ON(dev->set_state_periodic || dev->set_state_oneshot ||
-                       dev->set_state_shutdown || dev->tick_resume);
-
-               BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
-               return 0;
-       }
-
-       if (dev->features & CLOCK_EVT_FEAT_DUMMY)
-               return 0;
-
-       /* New state-specific callbacks */
-       if (!dev->set_state_shutdown)
-               return -EINVAL;
-
-       if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) &&
-           !dev->set_state_periodic)
-               return -EINVAL;
-
-       if ((dev->features & CLOCK_EVT_FEAT_ONESHOT) &&
-           !dev->set_state_oneshot)
-               return -EINVAL;
-
-       return 0;
-}
-
 /**
  * clockevents_register_device - register a clock event device
  * @dev:       device to register
@@ -477,10 +450,8 @@ void clockevents_register_device(struct clock_event_device *dev)
 {
        unsigned long flags;
 
-       BUG_ON(clockevents_sanity_check(dev));
-
        /* Initialize state to DETACHED */
-       dev->state = CLOCK_EVT_STATE_DETACHED;
+       clockevent_set_state(dev, CLOCK_EVT_STATE_DETACHED);
 
        if (!dev->cpumask) {
                WARN_ON(num_possible_cpus() > 1);
@@ -545,11 +516,11 @@ int __clockevents_update_freq(struct clock_event_device *dev, u32 freq)
 {
        clockevents_config(dev, freq);
 
-       if (dev->state == CLOCK_EVT_STATE_ONESHOT)
+       if (clockevent_state_oneshot(dev))
                return clockevents_program_event(dev, dev->next_event, false);
 
-       if (dev->state == CLOCK_EVT_STATE_PERIODIC)
-               return __clockevents_set_state(dev, CLOCK_EVT_STATE_PERIODIC);
+       if (clockevent_state_periodic(dev))
+               return __clockevents_switch_state(dev, CLOCK_EVT_STATE_PERIODIC);
 
        return 0;
 }
@@ -603,13 +574,13 @@ void clockevents_exchange_device(struct clock_event_device *old,
         */
        if (old) {
                module_put(old->owner);
-               clockevents_set_state(old, CLOCK_EVT_STATE_DETACHED);
+               clockevents_switch_state(old, CLOCK_EVT_STATE_DETACHED);
                list_del(&old->list);
                list_add(&old->list, &clockevents_released);
        }
 
        if (new) {
-               BUG_ON(new->state != CLOCK_EVT_STATE_DETACHED);
+               BUG_ON(!clockevent_state_detached(new));
                clockevents_shutdown(new);
        }
 }
@@ -622,7 +593,7 @@ void clockevents_suspend(void)
        struct clock_event_device *dev;
 
        list_for_each_entry_reverse(dev, &clockevent_devices, list)
-               if (dev->suspend)
+               if (dev->suspend && !clockevent_state_detached(dev))
                        dev->suspend(dev);
 }
 
@@ -634,7 +605,7 @@ void clockevents_resume(void)
        struct clock_event_device *dev;
 
        list_for_each_entry(dev, &clockevent_devices, list)
-               if (dev->resume)
+               if (dev->resume && !clockevent_state_detached(dev))
                        dev->resume(dev);
 }
 
@@ -665,7 +636,7 @@ void tick_cleanup_dead_cpu(int cpu)
                if (cpumask_test_cpu(cpu, dev->cpumask) &&
                    cpumask_weight(dev->cpumask) == 1 &&
                    !tick_is_broadcast_device(dev)) {
-                       BUG_ON(dev->state != CLOCK_EVT_STATE_DETACHED);
+                       BUG_ON(!clockevent_state_detached(dev));
                        list_del(&dev->list);
                }
        }