diff -urN oldtree/include/linux/clocksource.h newtree.2/include/linux/clocksource.h --- oldtree/include/linux/clocksource.h 2006-07-05 10:06:57.000000000 -0400 +++ newtree.2/include/linux/clocksource.h 2006-07-06 19:39:16.000000000 -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.2/kernel/timer.c --- oldtree/kernel/timer.c 2006-07-05 10:06:57.000000000 -0400 +++ newtree.2/kernel/timer.c 2006-07-06 19:39:40.000000000 -0400 @@ -1051,6 +1051,12 @@ if (sign > 0 ? error > *interval : error < *interval) adj++; + 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 sign << adj;