From fe99f1b184efb75c50dd8cbdfff99b559c2cb3b3 Mon Sep 17 00:00:00 2001
From: Chris Dearman <chris@mips.com>
Date: Mon, 26 Mar 2007 14:48:50 +0100
Subject: [PATCH] [MIPS] lockdep: Deal with interrupt disable hazard in
 TRACE_IRQFLAGS

Between the mtc0 or di instruction that disables interrupts and the
following hazard barrier a processor may still take interrupts.  If an
interrupt is taken after interrupts are disabled but before the state
is updated it will appear to restore_all that it is incorrectly returning
with interrupts disabled.

Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
 arch/mips/kernel/genex.S | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 83843a229be7..297bd56c2347 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -128,6 +128,37 @@ handle_vcei:
 
 	.align  5
 NESTED(handle_int, PT_SIZE, sp)
+#ifdef CONFIG_TRACE_IRQFLAGS
+	/*
+	 * Check to see if the interrupted code has just disabled
+	 * interrupts and ignore this interrupt for now if so.
+	 *
+	 * local_irq_disable() disables interrupts and then calls
+	 * trace_hardirqs_off() to track the state. If an interrupt is taken
+	 * after interrupts are disabled but before the state is updated
+	 * it will appear to restore_all that it is incorrectly returning with
+	 * interrupts disabled
+	 */
+	.set	push
+	.set	noat
+	mfc0	k0, CP0_STATUS
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+	and	k0, ST0_IEP
+	bnez	k0, 1f
+
+	mfc0	k0, EP0_EPC
+	.set	noreorder
+	j	k0
+	rfe
+#else
+	and	k0, ST0_IE
+	bnez	k0, 1f
+
+	eret
+#endif
+1:
+	.set pop
+#endif
 	SAVE_ALL
 	CLI
 	TRACE_IRQS_OFF
-- 
2.34.1