The mips processor on PNX833x is a stubborn mips chip and takes a few attempts to hit the timer ack. Introduce a loop of 10 attempts to ack the timer. cevt-r4k.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) Signed-off-by: daniel.j.laird <daniel.j.laird@xxxxxxx> diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/kernel/cevt-r4k.c linux-2.6.26-rc4/arch/mips/kernel/cevt-r4k.c --- linux-2.6.26-rc4.orig/arch/mips/kernel/cevt-r4k.c 2008-06-03 10:56:51.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/kernel/cevt-r4k.c 2008-06-16 14:12:18.000000000 +0100 @@ -47,11 +47,25 @@ static int cp0_timer_irq_installed; /* + * FIXME: This doesn't hold for the relocated E9000 compare interrupt. + */ +static inline int c0_compare_int_pending(void) +{ + return (read_c0_cause() >> cp0_compare_irq) & 0x100; +} + +/* * Timer ack for an R4k-compatible timer of a known frequency. */ -static void c0_timer_ack(void) +static inline void c0_timer_ack(bool timeout) { - write_c0_compare(read_c0_compare()); + int attempts_remaining = 10; + do { + write_c0_compare(read_c0_compare()); + irq_disable_hazard(); + if (timeout) + attempts_remaining--; + } while (c0_compare_int_pending() && attempts_remaining); } /* @@ -93,7 +107,7 @@ * interrupt. Being the paranoiacs we are we check anyway. */ if (!r2 || (read_c0_cause() & (1 << 30))) { - c0_timer_ack(); + c0_timer_ack(false); #ifdef CONFIG_MIPS_MT_SMTC if (cpu_data[cpu].vpe_id) goto out; @@ -169,13 +183,6 @@ { } -/* - * FIXME: This doesn't hold for the relocated E9000 compare interrupt. - */ -static int c0_compare_int_pending(void) -{ - return (read_c0_cause() >> cp0_compare_irq) & 0x100; -} static int c0_compare_int_usable(void) { @@ -186,8 +193,7 @@ * IP7 already pending? Try to clear it by acking the timer. */ if (c0_compare_int_pending()) { - write_c0_compare(read_c0_count()); - irq_disable_hazard(); + c0_timer_ack(true); if (c0_compare_int_pending()) return 0; } @@ -208,8 +214,7 @@ if (!c0_compare_int_pending()) return 0; - write_c0_compare(read_c0_count()); - irq_disable_hazard(); + c0_timer_ack(true); if (c0_compare_int_pending()) return 0;
The mips processor on PNX833x is a stubborn mips chip and takes a few attempts to hit the timer ack. Introduce a loop of 10 attempts to ack the timer. cevt-r4k.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) Signed-off-by: daniel.j.laird <daniel.j.laird@xxxxxxx> diff -urN --exclude=.svn linux-2.6.26-rc4.orig/arch/mips/kernel/cevt-r4k.c linux-2.6.26-rc4/arch/mips/kernel/cevt-r4k.c --- linux-2.6.26-rc4.orig/arch/mips/kernel/cevt-r4k.c 2008-06-03 10:56:51.000000000 +0100 +++ linux-2.6.26-rc4/arch/mips/kernel/cevt-r4k.c 2008-06-16 14:12:18.000000000 +0100 @@ -47,11 +47,25 @@ static int cp0_timer_irq_installed; /* + * FIXME: This doesn't hold for the relocated E9000 compare interrupt. + */ +static inline int c0_compare_int_pending(void) +{ + return (read_c0_cause() >> cp0_compare_irq) & 0x100; +} + +/* * Timer ack for an R4k-compatible timer of a known frequency. */ -static void c0_timer_ack(void) +static inline void c0_timer_ack(bool timeout) { - write_c0_compare(read_c0_compare()); + int attempts_remaining = 10; + do { + write_c0_compare(read_c0_compare()); + irq_disable_hazard(); + if (timeout) + attempts_remaining--; + } while (c0_compare_int_pending() && attempts_remaining); } /* @@ -93,7 +107,7 @@ * interrupt. Being the paranoiacs we are we check anyway. */ if (!r2 || (read_c0_cause() & (1 << 30))) { - c0_timer_ack(); + c0_timer_ack(false); #ifdef CONFIG_MIPS_MT_SMTC if (cpu_data[cpu].vpe_id) goto out; @@ -169,13 +183,6 @@ { } -/* - * FIXME: This doesn't hold for the relocated E9000 compare interrupt. - */ -static int c0_compare_int_pending(void) -{ - return (read_c0_cause() >> cp0_compare_irq) & 0x100; -} static int c0_compare_int_usable(void) { @@ -186,8 +193,7 @@ * IP7 already pending? Try to clear it by acking the timer. */ if (c0_compare_int_pending()) { - write_c0_compare(read_c0_count()); - irq_disable_hazard(); + c0_timer_ack(true); if (c0_compare_int_pending()) return 0; } @@ -208,8 +214,7 @@ if (!c0_compare_int_pending()) return 0; - write_c0_compare(read_c0_count()); - irq_disable_hazard(); + c0_timer_ack(true); if (c0_compare_int_pending()) return 0;