Revert 2 patches to fix https://bugs.gentoo.org/show_bug.cgi?id=245927 From: Thomas Gleixner Date: Sat, 6 Sep 2008 01:01:45 +0000 (+0200) Subject: clockevents: broadcast fixup possible waiters X-Git-Tag: v2.6.26.6~27 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fstable%2Flinux-2.6-stable.git;a=commitdiff_plain;h=92741d2d653769b582015c6a379e7b46e113435d clockevents: broadcast fixup possible waiters commit 7300711e8c6824fcfbd42a126980ff50439d8dd0 upstream 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. and From: Thomas Gleixner Date: Wed, 3 Sep 2008 21:37:08 +0000 (+0000) Subject: clockevents: prevent multiple init/shutdown X-Git-Tag: v2.6.26.6~30 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fstable%2Flinux-2.6-stable.git;a=commitdiff_plain;h=7f0a673a75d3f9f50a64f83055b71be67526efd7 clockevents: prevent multiple init/shutdown commit 9c17bcda991000351cb2373f78be7e4b1c44caa3 upstream While chasing the C1E/HPET bugreports I went through the clock events code inch by inch and found that the broadcast device can be initialized and shutdown multiple times. Multiple shutdowns are not critical, but useless waste of time. Multiple initializations are simply broken. Another CPU might have the device in use already after the first initialization and the second init could just render it unusable again. Index: linux-2.6.26-gentoo-r3/kernel/time/tick-broadcast.c =================================================================== --- linux-2.6.26-gentoo-r3.orig/kernel/time/tick-broadcast.c +++ linux-2.6.26-gentoo-r3/kernel/time/tick-broadcast.c @@ -209,7 +209,7 @@ static void tick_do_broadcast_on_off(voi struct clock_event_device *bc, *dev; struct tick_device *td; unsigned long flags, *reason = why; - int cpu, bc_stopped; + int cpu; spin_lock_irqsave(&tick_broadcast_lock, flags); @@ -227,8 +227,6 @@ static void tick_do_broadcast_on_off(voi if (!tick_device_is_functional(dev)) goto out; - bc_stopped = cpus_empty(tick_broadcast_mask); - switch (*reason) { case CLOCK_EVT_NOTIFY_BROADCAST_ON: case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: @@ -250,10 +248,9 @@ static void tick_do_broadcast_on_off(voi break; } - if (cpus_empty(tick_broadcast_mask)) { - if (!bc_stopped) - clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); - } else if (bc_stopped) { + if (cpus_empty(tick_broadcast_mask)) + clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); + else { if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) tick_broadcast_start_periodic(bc); else @@ -490,52 +487,14 @@ static void tick_broadcast_clear_oneshot 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 */ void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { - /* Set it up only once ! */ - 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; - 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->event_handler = tick_handle_oneshot_broadcast; + clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); + bc->next_event.tv64 = KTIME_MAX; } /*