[MIPS] Make sure cpu_has_fpu is used only in atomic context

Make sure cpu_has_fpu (which uses smp_processor_id()) is used only in
atomic context.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 46ee5a6..4ed37ba 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -107,7 +107,7 @@
 
 	seq_printf(m, "processor\t\t: %ld\n", n);
 	sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
-	        cpu_has_fpu ? "  FPU V%d.%d" : "");
+	        cpu_data[n].options & MIPS_CPU_FPU ? "  FPU V%d.%d" : "");
 	seq_printf(m, fmt, cpu_name[cpu_data[n].cputype <= CPU_LAST ?
 	                            cpu_data[n].cputype : CPU_UNKNOWN],
 	                           (version >> 4) & 0x0f, version & 0x0f,
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 045d987..9f307eb 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -115,7 +115,7 @@
 	status |= KU_USER;
 	regs->cp0_status = status;
 	clear_used_math();
-	lose_fpu();
+	clear_fpu_owner();
 	if (cpu_has_dsp)
 		__init_dsp();
 	regs->cp0_epc = pc;
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 362d172..258d74f 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -106,6 +106,7 @@
 int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
 {
 	int i;
+	unsigned int tmp;
 
 	if (!access_ok(VERIFY_WRITE, data, 33 * 8))
 		return -EIO;
@@ -121,10 +122,10 @@
 
 	__put_user (child->thread.fpu.fcr31, data + 64);
 
+	preempt_disable();
 	if (cpu_has_fpu) {
-		unsigned int flags, tmp;
+		unsigned int flags;
 
-		preempt_disable();
 		if (cpu_has_mipsmt) {
 			unsigned int vpflags = dvpe();
 			flags = read_c0_status();
@@ -138,11 +139,11 @@
 			__asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp));
 			write_c0_status(flags);
 		}
-		preempt_enable();
-		__put_user (tmp, data + 65);
 	} else {
-		__put_user ((__u32) 0, data + 65);
+		tmp = 0;
 	}
+	preempt_enable();
+	__put_user (tmp, data + 65);
 
 	return 0;
 }
@@ -245,16 +246,17 @@
 			unsigned int mtflags;
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-			if (!cpu_has_fpu)
+			preempt_disable();
+			if (!cpu_has_fpu) {
+				preempt_enable();
 				break;
+			}
 
 #ifdef CONFIG_MIPS_MT_SMTC
 			/* Read-modify-write of Status must be atomic */
 			local_irq_save(irqflags);
 			mtflags = dmt();
 #endif /* CONFIG_MIPS_MT_SMTC */
-
-			preempt_disable();
 			if (cpu_has_mipsmt) {
 				unsigned int vpflags = dvpe();
 				flags = read_c0_status();
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index f40ecd8..d9a39c1 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -175,7 +175,9 @@
 			unsigned int mtflags;
 #endif /* CONFIG_MIPS_MT_SMTC */
 
+			preempt_disable();
 			if (!cpu_has_fpu) {
+				preempt_enable();
 				tmp = 0;
 				break;
 			}
@@ -186,7 +188,6 @@
 			mtflags = dmt();
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-			preempt_disable();
 			if (cpu_has_mipsmt) {
 				unsigned int vpflags = dvpe();
 				flags = read_c0_status();
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b7292a5..cce8313 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -66,7 +66,7 @@
 extern asmlinkage void handle_reserved(void);
 
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-	struct mips_fpu_struct *ctx);
+	struct mips_fpu_struct *ctx, int has_fpu);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -641,7 +641,7 @@
 		preempt_enable();
 
 		/* Run the emulator */
-		sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu);
+		sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu, 1);
 
 		preempt_disable();
 
@@ -791,11 +791,13 @@
 			set_used_math();
 		}
 
-		preempt_enable();
-
-		if (!cpu_has_fpu) {
-			int sig = fpu_emulator_cop1Handler(regs,
-						&current->thread.fpu);
+		if (cpu_has_fpu) {
+			preempt_enable();
+		} else {
+			int sig;
+			preempt_enable();
+			sig = fpu_emulator_cop1Handler(regs,
+						&current->thread.fpu, 0);
 			if (sig)
 				force_sig(sig, current);
 #ifdef CONFIG_MIPS_MT_FPAFF