|
@@ -31,6 +31,12 @@ struct tick_device tick_broadcast_device;
|
|
|
static cpumask_t tick_broadcast_mask;
|
|
|
static DEFINE_SPINLOCK(tick_broadcast_lock);
|
|
|
|
|
|
+#ifdef CONFIG_TICK_ONESHOT
|
|
|
+static void tick_broadcast_clear_oneshot(int cpu);
|
|
|
+#else
|
|
|
+static inline void tick_broadcast_clear_oneshot(int cpu) { }
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* Debugging: see timer_list.c
|
|
|
*/
|
|
@@ -99,8 +105,19 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
|
|
|
cpu_set(cpu, tick_broadcast_mask);
|
|
|
tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
|
|
|
ret = 1;
|
|
|
- }
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * When the new device is not affected by the stop
|
|
|
+ * feature and the cpu is marked in the broadcast mask
|
|
|
+ * then clear the broadcast bit.
|
|
|
+ */
|
|
|
+ if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
|
|
|
+ int cpu = smp_processor_id();
|
|
|
|
|
|
+ cpu_clear(cpu, tick_broadcast_mask);
|
|
|
+ tick_broadcast_clear_oneshot(cpu);
|
|
|
+ }
|
|
|
+ }
|
|
|
spin_unlock_irqrestore(&tick_broadcast_lock, flags);
|
|
|
return ret;
|
|
|
}
|
|
@@ -487,6 +504,16 @@ out:
|
|
|
spin_unlock_irqrestore(&tick_broadcast_lock, flags);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Reset the one shot broadcast for a cpu
|
|
|
+ *
|
|
|
+ * Called with tick_broadcast_lock held
|
|
|
+ */
|
|
|
+static void tick_broadcast_clear_oneshot(int cpu)
|
|
|
+{
|
|
|
+ cpu_clear(cpu, tick_broadcast_oneshot_mask);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* tick_broadcast_setup_highres - setup the broadcast device for highres
|
|
|
*/
|