Commit 5590a536 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Linus Torvalds

clockevents: fix device replacement

When a device is replaced by a better rated device, then the broadcast
mode needs to be evaluated again. When the new device has no requirement
for broadcasting, then the broadcast bits for the CPU must be cleared.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: john stultz <johnstul@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 18de5bc4
...@@ -31,6 +31,12 @@ struct tick_device tick_broadcast_device; ...@@ -31,6 +31,12 @@ struct tick_device tick_broadcast_device;
static cpumask_t tick_broadcast_mask; static cpumask_t tick_broadcast_mask;
static DEFINE_SPINLOCK(tick_broadcast_lock); 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 * Debugging: see timer_list.c
*/ */
...@@ -99,8 +105,19 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) ...@@ -99,8 +105,19 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
cpu_set(cpu, tick_broadcast_mask); cpu_set(cpu, tick_broadcast_mask);
tick_broadcast_start_periodic(tick_broadcast_device.evtdev); tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
ret = 1; 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); spin_unlock_irqrestore(&tick_broadcast_lock, flags);
return ret; return ret;
} }
...@@ -487,6 +504,16 @@ out: ...@@ -487,6 +504,16 @@ out:
spin_unlock_irqrestore(&tick_broadcast_lock, flags); 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 * tick_broadcast_setup_highres - setup the broadcast device for highres
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment