diff -urN oldtree/include/linux/clocksource.h newtree/include/linux/clocksource.h --- oldtree/include/linux/clocksource.h 2006-08-18 15:01:22.000000000 -0400 +++ newtree/include/linux/clocksource.h 2006-08-20 05:39:28.886165250 -0400 @@ -55,7 +55,7 @@ int rating; cycle_t (*read)(void); cycle_t mask; - u32 mult; + u32 mult, mult_min; u32 shift; int (*update_callback)(void); int is_continuous; @@ -169,6 +169,8 @@ tmp += c->mult/2; do_div(tmp, c->mult); + c->mult_min = max(c->mult >> 2, 1u); + c->cycle_interval = (cycle_t)tmp; if (c->cycle_interval == 0) c->cycle_interval = 1; diff -urN oldtree/kernel/timer.c newtree/kernel/timer.c --- oldtree/kernel/timer.c 2006-08-20 05:39:19.721592500 -0400 +++ newtree/kernel/timer.c 2006-08-20 05:39:28.902166250 -0400 @@ -867,6 +867,12 @@ for (adj = 0; error > i; adj++) error >>= 1; + if (sign < 0 && unlikely(clock->mult < clock->mult_min + (1 << adj))) { + if (clock->mult <= clock->mult_min) + return 0; + adj = fls(clock->mult - clock->mult_min) - 1; + } + *interval <<= adj; *offset <<= adj; return mult << adj;