diff -urN newtree/include/linux/clocksource.h newtree.2/include/linux/clocksource.h --- newtree/include/linux/clocksource.h 2006-07-15 14:53:08.000000000 -0700 +++ newtree.2/include/linux/clocksource.h 2006-08-04 10:26:59.000000000 -0700 @@ -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 newtree/kernel/timer.c newtree.2/kernel/timer.c --- newtree/kernel/timer.c 2006-08-04 10:26:48.000000000 -0700 +++ newtree.2/kernel/timer.c 2006-08-04 10:26:59.000000000 -0700 @@ -1074,6 +1074,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;