]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/time/tick-broadcast.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / kernel / time / tick-broadcast.c
index 8cfb8b2ce773ed4838b3bb4c699b22c4c34423c7..e1bd50cbbf5d232896b4ae470bf005adb84e543d 100644 (file)
@@ -126,9 +126,9 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
 /*
  * Broadcast the event to the cpus, which are set in the mask
  */
-int tick_do_broadcast(cpumask_t mask)
+static void tick_do_broadcast(cpumask_t mask)
 {
-       int ret = 0, cpu = smp_processor_id();
+       int cpu = smp_processor_id();
        struct tick_device *td;
 
        /*
@@ -138,7 +138,6 @@ int tick_do_broadcast(cpumask_t mask)
                cpu_clear(cpu, mask);
                td = &per_cpu(tick_cpu_device, cpu);
                td->evtdev->event_handler(td->evtdev);
-               ret = 1;
        }
 
        if (!cpus_empty(mask)) {
@@ -151,9 +150,7 @@ int tick_do_broadcast(cpumask_t mask)
                cpu = first_cpu(mask);
                td = &per_cpu(tick_cpu_device, cpu);
                td->evtdev->broadcast(mask);
-               ret = 1;
        }
-       return ret;
 }
 
 /*
@@ -383,33 +380,6 @@ int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
        return 0;
 }
 
-/*
- * Reprogram the broadcast device:
- *
- * Called with tick_broadcast_lock held and interrupts disabled.
- */
-static int tick_broadcast_reprogram(void)
-{
-       ktime_t expires = { .tv64 = KTIME_MAX };
-       struct tick_device *td;
-       int cpu;
-
-       /*
-        * Find the event which expires next:
-        */
-       for (cpu = first_cpu(tick_broadcast_oneshot_mask); cpu != NR_CPUS;
-            cpu = next_cpu(cpu, tick_broadcast_oneshot_mask)) {
-               td = &per_cpu(tick_cpu_device, cpu);
-               if (td->evtdev->next_event.tv64 < expires.tv64)
-                       expires = td->evtdev->next_event;
-       }
-
-       if (expires.tv64 == KTIME_MAX)
-               return 0;
-
-       return tick_broadcast_set_event(expires, 0);
-}
-
 /*
  * Handle oneshot mode broadcasting
  */
@@ -417,12 +387,13 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
 {
        struct tick_device *td;
        cpumask_t mask;
-       ktime_t now;
+       ktime_t now, next_event;
        int cpu;
 
        spin_lock(&tick_broadcast_lock);
 again:
        dev->next_event.tv64 = KTIME_MAX;
+       next_event.tv64 = KTIME_MAX;
        mask = CPU_MASK_NONE;
        now = ktime_get();
        /* Find all expired events */
@@ -431,19 +402,31 @@ again:
                td = &per_cpu(tick_cpu_device, cpu);
                if (td->evtdev->next_event.tv64 <= now.tv64)
                        cpu_set(cpu, mask);
+               else if (td->evtdev->next_event.tv64 < next_event.tv64)
+                       next_event.tv64 = td->evtdev->next_event.tv64;
        }
 
        /*
-        * Wakeup the cpus which have an expired event. The broadcast
-        * device is reprogrammed in the return from idle code.
+        * Wakeup the cpus which have an expired event.
+        */
+       tick_do_broadcast(mask);
+
+       /*
+        * Two reasons for reprogram:
+        *
+        * - The global event did not expire any CPU local
+        * events. This happens in dyntick mode, as the maximum PIT
+        * delta is quite small.
+        *
+        * - There are pending events on sleeping CPUs which were not
+        * in the event mask
         */
-       if (!tick_do_broadcast(mask)) {
+       if (next_event.tv64 != KTIME_MAX) {
                /*
-                * The global event did not expire any CPU local
-                * events. This happens in dyntick mode, as the
-                * maximum PIT delta is quite small.
+                * Rearm the broadcast device. If event expired,
+                * repeat the above
                 */
-               if (tick_broadcast_reprogram())
+               if (tick_broadcast_set_event(next_event, 0))
                        goto again;
        }
        spin_unlock(&tick_broadcast_lock);
@@ -508,7 +491,7 @@ static void tick_broadcast_clear_oneshot(int cpu)
 }
 
 /**
- * tick_broadcast_setup_highres - setup the broadcast device for highres
+ * tick_broadcast_setup_oneshot - setup the broadcast device
  */
 void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {