The 'mult' element of struct clock_event_device must never be wider than 32-bits. If it were, it would get truncated when used by clockevent_delta2ns() when this calls do_div(). We meet the requirement by ensuring that the relationship: (mips_hpt_frequency >> (32 - shift)) < NSEC_PER_SEC Always holds. Signed-off-by: David Daney <ddaney@xxxxxxxxxxxxxxxxxx> CC: Thomas Gleixner <tglx@xxxxxxxxxxxxx> --- arch/mips/kernel/cevt-r4k.c | 16 +++++++++++++--- 1 files changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 0b2450c..4495158 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -163,10 +163,11 @@ int c0_compare_int_usable(void) int __cpuinit r4k_clockevent_init(void) { - uint64_t mips_freq = mips_hpt_frequency; + uint64_t scaled_freq = mips_hpt_frequency; unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; unsigned int irq; + int shift; if (!cpu_has_counter || !mips_hpt_frequency) return -ENXIO; @@ -189,8 +190,17 @@ int __cpuinit r4k_clockevent_init(void) cd->features = CLOCK_EVT_FEAT_ONESHOT; /* Calculate the min / max delta */ - cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); - cd->shift = 32; + shift = 32; + while (scaled_freq >= NSEC_PER_SEC && shift) { + scaled_freq = scaled_freq >> 1; + shift--; + } + BUG_ON(shift == 0); + + cd->mult = div_sc((unsigned long) mips_hpt_frequency, + NSEC_PER_SEC, shift); + cd->shift = shift; + cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); cd->min_delta_ns = clockevent_delta2ns(0x300, cd); -- 1.6.6.1