[ARM] 3707/1: iwmmxt: use the generic thread notifier infrastructure
authorLennert Buytenhek <buytenh@wantstofly.org>
Sat, 1 Jul 2006 18:56:48 +0000 (19:56 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 1 Jul 2006 18:56:48 +0000 (19:56 +0100)
Patch from Lennert Buytenhek

This patch makes the iWMMXt context switch hook use the generic
thread notifier infrastructure that was recently merged in commit
d6551e884cf66de072b81f8b6d23259462c40baf.

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/kernel/Makefile
arch/arm/kernel/entry-armv.S
arch/arm/kernel/iwmmxt-notifier.c [new file with mode: 0644]
arch/arm/kernel/iwmmxt.S
arch/arm/kernel/process.c
include/asm-arm/thread_info.h

index 7cffbaef064ba60afcec20ca02638ebf70b89a9a..f0c0cdb1c183ff57f0202c36b8d7b3035052fee1 100644 (file)
@@ -25,7 +25,7 @@ obj-$(CONFIG_OABI_COMPAT)     += sys_oabi-compat.o
 obj-$(CONFIG_CRUNCH)           += crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o           := -Wa,-mcpu=ep9312
 
-obj-$(CONFIG_IWMMXT)           += iwmmxt.o
+obj-$(CONFIG_IWMMXT)           += iwmmxt.o iwmmxt-notifier.o
 AFLAGS_iwmmxt.o                        := -Wa,-mcpu=iwmmxt
 
 ifneq ($(CONFIG_ARCH_EBSA110),y)
index 6423a38839b8b4e86f6105399e209e00ce8f607c..0e8aeaf9ff1dd1626bbfb273e485227e564a13e8 100644 (file)
@@ -590,9 +590,7 @@ ENTRY(__switch_to)
 #ifdef CONFIG_MMU
        mcr     p15, 0, r6, c3, c0, 0           @ Set domain register
 #endif
-#if defined(CONFIG_IWMMXT)
-       bl      iwmmxt_task_switch
-#elif defined(CONFIG_CPU_XSCALE)
+#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
        add     r4, r2, #TI_CPU_DOMAIN + 40     @ cpu_context_save->extra
        ldmib   r4, {r4, r5}
        mar     acc0, r4, r5
diff --git a/arch/arm/kernel/iwmmxt-notifier.c b/arch/arm/kernel/iwmmxt-notifier.c
new file mode 100644 (file)
index 0000000..44a86c3
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/arm/kernel/iwmmxt-notifier.c
+ *
+ *  XScale iWMMXt (Concan) context switching and handling
+ *
+ *  Initial code:
+ *  Copyright (c) 2003, Intel Corporation
+ *
+ *  Full lazy switching support, optimizations and more, by Nicolas Pitre
+ *  Copyright (c) 2003-2004, MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/thread_notify.h>
+#include <asm/io.h>
+
+static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
+{
+       struct thread_info *thread = t;
+
+       switch (cmd) {
+       case THREAD_NOTIFY_FLUSH:
+               /*
+                * flush_thread() zeroes thread->fpstate, so no need
+                * to do anything here.
+                *
+                * FALLTHROUGH: Ensure we don't try to overwrite our newly
+                * initialised state information on the first fault.
+                */
+
+       case THREAD_NOTIFY_RELEASE:
+               iwmmxt_task_release(thread);
+               break;
+
+       case THREAD_NOTIFY_SWITCH:
+               iwmmxt_task_switch(thread);
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block iwmmxt_notifier_block = {
+       .notifier_call  = iwmmxt_do,
+};
+
+static int __init iwmmxt_init(void)
+{
+       thread_register_notifier(&iwmmxt_notifier_block);
+
+       return 0;
+}
+
+late_initcall(iwmmxt_init);
index a3bae95e536c0ddd4071847c2d3b220fe72f5bae..b63b528f22a693d4059680a98eb0d1a23182b1f2 100644 (file)
@@ -271,30 +271,27 @@ ENTRY(iwmmxt_task_restore)
 /*
  * Concan handling on task switch
  *
- * r0 = previous task_struct pointer (must be preserved)
- * r1 = previous thread_info pointer
- * r2 = next thread_info pointer (must be preserved)
+ * r0 = next thread_info pointer
  *
- * Called only from __switch_to with task preemption disabled.
- * No need to care about preserving r4 and above.
+ * Called only from the iwmmxt notifier with task preemption disabled.
  */
 ENTRY(iwmmxt_task_switch)
 
-       mrc     p15, 0, r4, c15, c1, 0
-       tst     r4, #0x3                        @ CP0 and CP1 accessible?
+       mrc     p15, 0, r1, c15, c1, 0
+       tst     r1, #0x3                        @ CP0 and CP1 accessible?
        bne     1f                              @ yes: block them for next task
 
-       ldr     r5, =concan_owner
-       add     r6, r2, #TI_IWMMXT_STATE        @ get next task Concan save area
-       ldr     r5, [r5]                        @ get current Concan owner
-       teq     r5, r6                          @ next task owns it?
+       ldr     r2, =concan_owner
+       add     r3, r0, #TI_IWMMXT_STATE        @ get next task Concan save area
+       ldr     r2, [r2]                        @ get current Concan owner
+       teq     r2, r3                          @ next task owns it?
        movne   pc, lr                          @ no: leave Concan disabled
 
-1:     eor     r4, r4, #3                      @ flip Concan access
-       mcr     p15, 0, r4, c15, c1, 0
+1:     eor     r1, r1, #3                      @ flip Concan access
+       mcr     p15, 0, r1, c15, c1, 0
 
-       mrc     p15, 0, r4, c2, c0, 0
-       sub     pc, lr, r4, lsr #32             @ cpwait and return
+       mrc     p15, 0, r1, c2, c0, 0
+       sub     pc, lr, r1, lsr #32             @ cpwait and return
 
 /*
  * Remove Concan ownership of given task
index e1c77ee885a7f98eaaa9ac213991874561d2b34d..b5773a2549ee44182d64b2b76d3a02e1d5c0cd6e 100644 (file)
@@ -353,9 +353,6 @@ void flush_thread(void)
        memset(&thread->fpstate, 0, sizeof(union fp_state));
 
        thread_notify(THREAD_NOTIFY_FLUSH, thread);
-#if defined(CONFIG_IWMMXT)
-       iwmmxt_task_release(thread);
-#endif
 }
 
 void release_thread(struct task_struct *dead_task)
@@ -363,9 +360,6 @@ void release_thread(struct task_struct *dead_task)
        struct thread_info *thread = task_thread_info(dead_task);
 
        thread_notify(THREAD_NOTIFY_RELEASE, thread);
-#if defined(CONFIG_IWMMXT)
-       iwmmxt_task_release(thread);
-#endif
 }
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
index c46b5c84275f3f2f5b2ac91d8a60002963fdc9f5..c52e0bf75353c7029040c7c3cc9511552de0c24b 100644 (file)
@@ -111,6 +111,7 @@ extern void iwmmxt_task_disable(struct thread_info *);
 extern void iwmmxt_task_copy(struct thread_info *, void *);
 extern void iwmmxt_task_restore(struct thread_info *, void *);
 extern void iwmmxt_task_release(struct thread_info *);
+extern void iwmmxt_task_switch(struct thread_info *);
 
 #endif