Commit 7300711e authored by Thomas Gleixner's avatar Thomas Gleixner

clockevents: broadcast fixup possible waiters

Until the C1E patches arrived there where no users of periodic broadcast
before switching to oneshot mode. Now we need to trigger a possible
waiter for a periodic broadcast when switching to oneshot mode.
Otherwise we can starve them for ever.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 7cfb0435
...@@ -491,6 +491,18 @@ static void tick_broadcast_clear_oneshot(int cpu) ...@@ -491,6 +491,18 @@ static void tick_broadcast_clear_oneshot(int cpu)
cpu_clear(cpu, tick_broadcast_oneshot_mask); cpu_clear(cpu, tick_broadcast_oneshot_mask);
} }
static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
{
struct tick_device *td;
int cpu;
for_each_cpu_mask_nr(cpu, *mask) {
td = &per_cpu(tick_cpu_device, cpu);
if (td->evtdev)
td->evtdev->next_event = expires;
}
}
/** /**
* tick_broadcast_setup_oneshot - setup the broadcast device * tick_broadcast_setup_oneshot - setup the broadcast device
*/ */
...@@ -498,8 +510,31 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc) ...@@ -498,8 +510,31 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
{ {
/* Set it up only once ! */ /* Set it up only once ! */
if (bc->event_handler != tick_handle_oneshot_broadcast) { if (bc->event_handler != tick_handle_oneshot_broadcast) {
int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
int cpu = smp_processor_id();
cpumask_t mask;
bc->event_handler = tick_handle_oneshot_broadcast; bc->event_handler = tick_handle_oneshot_broadcast;
clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
/* Take the do_timer update */
tick_do_timer_cpu = cpu;
/*
* We must be careful here. There might be other CPUs
* waiting for periodic broadcast. We need to set the
* oneshot_mask bits for those and program the
* broadcast device to fire.
*/
mask = tick_broadcast_mask;
cpu_clear(cpu, mask);
cpus_or(tick_broadcast_oneshot_mask,
tick_broadcast_oneshot_mask, mask);
if (was_periodic && !cpus_empty(mask)) {
tick_broadcast_init_next_event(&mask, tick_next_period);
tick_broadcast_set_event(tick_next_period, 1);
} else
bc->next_event.tv64 = KTIME_MAX; bc->next_event.tv64 = KTIME_MAX;
} }
} }
......
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