[PATCH 2/2] : Patch to fix stubborn timers on PNX833x/(Others?)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
 

[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux