diff -urN oldtree/include/linux/clocksource.h newtree.new/include/linux/clocksource.h --- oldtree/include/linux/clocksource.h 2006-06-27 12:28:59.000000000 +0000 +++ newtree.new/include/linux/clocksource.h 2006-06-28 11:57:55.000000000 +0000 @@ -55,7 +55,7 @@ int rating; cycle_t (*read)(void); cycle_t mask; - u32 mult; + u32 mult, multi_min; u32 shift; int (*update_callback)(void); int is_continuous; @@ -169,6 +169,8 @@ tmp += c->mult/2; do_div(tmp, c->mult); + c->multi_min = max(c->multi >> 2, 1u); + c->cycle_interval = (cycle_t)tmp; if (c->cycle_interval == 0) c->cycle_interval = 1; diff -urN oldtree/kernel/timer.c newtree.new/kernel/timer.c --- oldtree/kernel/timer.c 2006-06-27 12:28:59.000000000 +0000 +++ newtree.new/kernel/timer.c 2006-06-28 12:01:32.000000000 +0000 @@ -1051,6 +1051,12 @@ if (sign > 0 ? error > *interval : error < *interval) adj++; + if (sign < 0 && unlikely(clock->multi < clock->multi_min + (1 << adj))) { + if (clock->multi <= clock->multi_min) + return 0; + adj = fls(clock->multi - clock->multi_min) - 1; + } + *interval <<= adj; *offset <<= adj; return sign << adj;