[MIPS] TRACE_IRQFLAGS_SUPPORT support.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 515f9e6..5d6afb5 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -1,5 +1,9 @@
 menu "Kernel hacking"
 
+config TRACE_IRQFLAGS_SUPPORT
+	bool
+	default y
+
 source "lib/Kconfig.debug"
 
 config CROSSCOMPILE
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 01e7fa8..766655f 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -113,6 +113,21 @@
 	RESTORE_AT
 	RESTORE_STATIC
 FEXPORT(restore_partial)		# restore partial frame
+#ifdef CONFIG_TRACE_IRQFLAGS
+	SAVE_STATIC
+	SAVE_AT
+	SAVE_TEMP
+	LONG_L	v0, PT_STATUS(sp)
+	and	v0, 1
+	beqz	v0, 1f
+	jal	trace_hardirqs_on
+	b	2f
+1:	jal	trace_hardirqs_off
+2:
+	RESTORE_TEMP
+	RESTORE_AT
+	RESTORE_STATIC
+#endif
 	RESTORE_SOME
 	RESTORE_SP_AND_RET
 	.set	at
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
index 666bc90..2c44606 100644
--- a/arch/mips/kernel/gdb-low.S
+++ b/arch/mips/kernel/gdb-low.S
@@ -7,6 +7,7 @@
 
 #include <asm/asm.h>
 #include <asm/errno.h>
+#include <asm/irqflags.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
@@ -120,6 +121,7 @@
 		LONG_S	$31, GDB_FR_REG31(sp)
 
 		CLI				/* disable interrupts */
+		TRACE_IRQS_OFF
 
 /*
  * Followed by the floating point registers
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index b563811..37fda3d 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -13,6 +13,7 @@
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/cacheops.h>
+#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
@@ -128,6 +129,7 @@
 NESTED(handle_int, PT_SIZE, sp)
 	SAVE_ALL
 	CLI
+	TRACE_IRQS_OFF
 
 	PTR_LA	ra, ret_from_irq
 	move	a0, sp
@@ -216,6 +218,7 @@
 	_ehb
 #endif /* CONFIG_MIPS_MT_SMTC */
 	CLI
+	TRACE_IRQS_OFF
 	move	a0, sp
 	jalr	v0
 	j	ret_from_irq
@@ -288,11 +291,13 @@
 	.endm
 
 	.macro	__build_clear_sti
+	TRACE_IRQS_ON
 	STI
 	.endm
 
 	.macro	__build_clear_cli
 	CLI
+	TRACE_IRQS_OFF
 	.endm
 
 	.macro	__build_clear_fpe
@@ -300,6 +305,7 @@
 	li	a2, ~(0x3f << 12)
 	and	a2, a1
 	ctc1	a2, fcr31
+	TRACE_IRQS_ON
 	STI
 	.endm
 
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 476c1eb..8c6db0f 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 1994, 1995 Waldorf Electronics
  * Written by Ralf Baechle and Andreas Busse
- * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 Ralf Baechle
+ * Copyright (C) 1994 - 99, 2003, 06 Ralf Baechle
  * Copyright (C) 1996 Paul M. Antoine
  * Modified for DECStation and hence R3000 support by Paul M. Antoine
  * Further modifications by David S. Miller and Harald Koerfgen
@@ -18,6 +18,7 @@
 
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
+#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/page.h>
 #include <asm/mipsregs.h>
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index c8e5f9c..ba1bcd8 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -3,13 +3,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle
+ * Copyright (C) 1995-99, 2000- 02, 06 Ralf Baechle <ralf@linux-mips.org>
  * Copyright (C) 2001 MIPS Technologies, Inc.
  * Copyright (C) 2004 Thiemo Seufer
  */
 #include <linux/errno.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
+#include <asm/irqflags.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
@@ -27,6 +28,18 @@
 NESTED(handle_sys, PT_SIZE, sp)
 	.set	noat
 	SAVE_SOME
+#ifdef CONFIG_TRACE_IRQFLAGS
+	TRACE_IRQS_ON
+#ifdef CONFIG_64BIT
+	LONG_L	$8, PT_R8(sp)
+	LONG_L	$9, PT_R9(sp)
+#endif
+	LONG_L	$7, PT_R7(sp)
+	LONG_L	$6, PT_R6(sp)
+	LONG_L	$5, PT_R5(sp)
+	LONG_L	$4, PT_R4(sp)
+	LONG_L	$2, PT_R2(sp)
+#endif
 	STI
 	.set	at
 
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 809fd1b..939e172d 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
+#include <asm/irqflags.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
@@ -33,6 +34,7 @@
 	 */
 	.set	noat
 	SAVE_SOME
+	TRACE_IRQS_ON
 	STI
 	.set	at
 #endif
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index b2b5cb9..98abbc5 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
+#include <asm/irqflags.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
@@ -32,6 +33,7 @@
 #ifndef CONFIG_MIPS32_O32
 	.set	noat
 	SAVE_SOME
+	TRACE_IRQS_ON
 	STI
 	.set	at
 #endif
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 3a138dc..505c9ee 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
+#include <asm/irqflags.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
@@ -27,6 +28,7 @@
 NESTED(handle_sys, PT_SIZE, sp)
 	.set	noat
 	SAVE_SOME
+	TRACE_IRQS_ON
 	STI
 	.set	at
 	ld	t1, PT_EPC(sp)		# skip syscall on return
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
index 72c6d98..4cc3dea 100644
--- a/arch/mips/kernel/smtc-asm.S
+++ b/arch/mips/kernel/smtc-asm.S
@@ -96,6 +96,7 @@
 	/* Save all will redundantly recompute the SP, but use it for now */
 	SAVE_ALL
 	CLI
+	TRACE_IRQS_OFF
 	move	a0,sp
 	/* Function to be invoked passed stack pad slot 5 */
 	lw	t0,PT_PADSLOT5(sp)
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index 13d44e1..e64abc0 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -22,8 +22,8 @@
 #ifndef _ASM_ATOMIC_H
 #define _ASM_ATOMIC_H
 
+#include <linux/irqflags.h>
 #include <asm/cpu-features.h>
-#include <asm/interrupt.h>
 #include <asm/war.h>
 
 typedef struct { volatile int counter; } atomic_t;
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 098cec2..1bb89c5 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -31,7 +31,7 @@
 
 #ifdef __KERNEL__
 
-#include <asm/interrupt.h>
+#include <linux/irqflags.h>
 #include <asm/sgidefs.h>
 #include <asm/war.h>
 
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/irqflags.h
similarity index 80%
rename from include/asm-mips/interrupt.h
rename to include/asm-mips/irqflags.h
index a99d686..43ca09a 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/irqflags.h
@@ -8,13 +8,15 @@
  * Copyright (C) 1999 Silicon Graphics
  * Copyright (C) 2000 MIPS Technologies, Inc.
  */
-#ifndef _ASM_INTERRUPT_H
-#define _ASM_INTERRUPT_H
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
 
 #include <asm/hazards.h>
 
 __asm__ (
-	"	.macro	local_irq_enable				\n"
+	"	.macro	raw_local_irq_enable				\n"
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
@@ -35,10 +37,10 @@
 	"	.set	pop						\n"
 	"	.endm");
 
-static inline void local_irq_enable(void)
+static inline void raw_local_irq_enable(void)
 {
 	__asm__ __volatile__(
-		"local_irq_enable"
+		"raw_local_irq_enable"
 		: /* no outputs */
 		: /* no inputs */
 		: "memory");
@@ -63,7 +65,7 @@
  * Workaround: mask EXL bit of the result or place a nop before mfc0.
  */
 __asm__ (
-	"	.macro	local_irq_disable\n"
+	"	.macro	raw_local_irq_disable\n"
 	"	.set	push						\n"
 	"	.set	noat						\n"
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -84,17 +86,17 @@
 	"	.set	pop						\n"
 	"	.endm							\n");
 
-static inline void local_irq_disable(void)
+static inline void raw_local_irq_disable(void)
 {
 	__asm__ __volatile__(
-		"local_irq_disable"
+		"raw_local_irq_disable"
 		: /* no outputs */
 		: /* no inputs */
 		: "memory");
 }
 
 __asm__ (
-	"	.macro	local_save_flags flags				\n"
+	"	.macro	raw_local_save_flags flags			\n"
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 #ifdef CONFIG_MIPS_MT_SMTC
@@ -105,13 +107,13 @@
 	"	.set	pop						\n"
 	"	.endm							\n");
 
-#define local_save_flags(x)						\
+#define raw_local_save_flags(x)						\
 __asm__ __volatile__(							\
-	"local_save_flags %0"						\
+	"raw_local_save_flags %0"					\
 	: "=r" (x))
 
 __asm__ (
-	"	.macro	local_irq_save result				\n"
+	"	.macro	raw_local_irq_save result			\n"
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
@@ -135,15 +137,15 @@
 	"	.set	pop						\n"
 	"	.endm							\n");
 
-#define local_irq_save(x)						\
+#define raw_local_irq_save(x)						\
 __asm__ __volatile__(							\
-	"local_irq_save\t%0"						\
+	"raw_local_irq_save\t%0"					\
 	: "=r" (x)							\
 	: /* no inputs */						\
 	: "memory")
 
 __asm__ (
-	"	.macro	local_irq_restore flags				\n"
+	"	.macro	raw_local_irq_restore flags			\n"
 	"	.set	push						\n"
 	"	.set	noreorder					\n"
 	"	.set	noat						\n"
@@ -182,40 +184,42 @@
 	"	.set	pop						\n"
 	"	.endm							\n");
 
-#define local_irq_restore(flags)					\
+#define raw_local_irq_restore(flags)					\
 do {									\
 	unsigned long __tmp1;						\
 									\
 	__asm__ __volatile__(						\
-		"local_irq_restore\t%0"					\
+		"raw_local_irq_restore\t%0"				\
 		: "=r" (__tmp1)						\
 		: "0" (flags)						\
 		: "memory");						\
 } while(0)
 
-static inline int irqs_disabled(void)
+static inline int raw_irqs_disabled_flags(unsigned long flags)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
 	/*
 	 * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
 	 */
-	unsigned long __result;
-
-	__asm__ __volatile__(
-	"	.set	noreorder					\n"
-	"	mfc0	%0, $2, 1					\n"
-	"	andi	%0, 0x400					\n"
-	"	slt	%0, $0, %0					\n"
-	"	.set	reorder						\n"
-	: "=r" (__result));
-
-	return __result;
+	return flags & 0x400;
 #else
-	unsigned long flags;
-	local_save_flags(flags);
-
 	return !(flags & 1);
 #endif
 }
 
-#endif /* _ASM_INTERRUPT_H */
+#endif
+
+/*
+ * Do the CPU's IRQ-state tracing from assembly code.
+ */
+#ifdef CONFIG_TRACE_IRQFLAGS
+# define TRACE_IRQS_ON							\
+	jal	trace_hardirqs_on
+# define TRACE_IRQS_OFF							\
+	jal	trace_hardirqs_off
+#else
+# define TRACE_IRQS_ON
+# define TRACE_IRQS_OFF
+#endif
+
+#endif /* _ASM_IRQFLAGS_H */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index b4169f0..6776688 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -1417,7 +1417,7 @@
 
 #else /* SMTC versions that manage MT scheduling */
 
-#include <asm/interrupt.h>
+#include <linux/irqflags.h>
 
 /*
  * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 130333d..13c98dd 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -13,13 +13,13 @@
 #define _ASM_SYSTEM_H
 
 #include <linux/types.h>
+#include <linux/irqflags.h>
 
 #include <asm/addrspace.h>
 #include <asm/cpu-features.h>
 #include <asm/dsp.h>
 #include <asm/ptrace.h>
 #include <asm/war.h>
-#include <asm/interrupt.h>
 
 /*
  * read_barrier_depends - Flush all pending reads that subsequents reads