aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2006-07-01 14:56:48 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-07-01 14:56:48 -0400
commitae95bfbb2b67eba5d67a0478a8715682a87e2616 (patch)
tree39441dab1f8934f0596bfaef267994aefb266921 /arch
parent9b8417556cca8d56467fd47a39667a4cf3ae21f3 (diff)
[ARM] 3707/1: iwmmxt: use the generic thread notifier infrastructure
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/entry-armv.S4
-rw-r--r--arch/arm/kernel/iwmmxt-notifier.c64
-rw-r--r--arch/arm/kernel/iwmmxt.S27
-rw-r--r--arch/arm/kernel/process.c6
5 files changed, 78 insertions, 25 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 7cffbaef064b..f0c0cdb1c183 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -25,7 +25,7 @@ obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
25obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o 25obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
26AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 26AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
27 27
28obj-$(CONFIG_IWMMXT) += iwmmxt.o 28obj-$(CONFIG_IWMMXT) += iwmmxt.o iwmmxt-notifier.o
29AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt 29AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
30 30
31ifneq ($(CONFIG_ARCH_EBSA110),y) 31ifneq ($(CONFIG_ARCH_EBSA110),y)
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 6423a38839b8..0e8aeaf9ff1d 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -590,9 +590,7 @@ ENTRY(__switch_to)
590#ifdef CONFIG_MMU 590#ifdef CONFIG_MMU
591 mcr p15, 0, r6, c3, c0, 0 @ Set domain register 591 mcr p15, 0, r6, c3, c0, 0 @ Set domain register
592#endif 592#endif
593#if defined(CONFIG_IWMMXT) 593#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
594 bl iwmmxt_task_switch
595#elif defined(CONFIG_CPU_XSCALE)
596 add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra 594 add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra
597 ldmib r4, {r4, r5} 595 ldmib r4, {r4, r5}
598 mar acc0, r4, r5 596 mar acc0, r4, r5
diff --git a/arch/arm/kernel/iwmmxt-notifier.c b/arch/arm/kernel/iwmmxt-notifier.c
new file mode 100644
index 000000000000..44a86c33796e
--- /dev/null
+++ b/arch/arm/kernel/iwmmxt-notifier.c
@@ -0,0 +1,64 @@
1/*
2 * linux/arch/arm/kernel/iwmmxt-notifier.c
3 *
4 * XScale iWMMXt (Concan) context switching and handling
5 *
6 * Initial code:
7 * Copyright (c) 2003, Intel Corporation
8 *
9 * Full lazy switching support, optimizations and more, by Nicolas Pitre
10 * Copyright (c) 2003-2004, MontaVista Software, Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/module.h>
18#include <linux/config.h>
19#include <linux/types.h>
20#include <linux/kernel.h>
21#include <linux/signal.h>
22#include <linux/sched.h>
23#include <linux/init.h>
24#include <asm/thread_notify.h>
25#include <asm/io.h>
26
27static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
28{
29 struct thread_info *thread = t;
30
31 switch (cmd) {
32 case THREAD_NOTIFY_FLUSH:
33 /*
34 * flush_thread() zeroes thread->fpstate, so no need
35 * to do anything here.
36 *
37 * FALLTHROUGH: Ensure we don't try to overwrite our newly
38 * initialised state information on the first fault.
39 */
40
41 case THREAD_NOTIFY_RELEASE:
42 iwmmxt_task_release(thread);
43 break;
44
45 case THREAD_NOTIFY_SWITCH:
46 iwmmxt_task_switch(thread);
47 break;
48 }
49
50 return NOTIFY_DONE;
51}
52
53static struct notifier_block iwmmxt_notifier_block = {
54 .notifier_call = iwmmxt_do,
55};
56
57static int __init iwmmxt_init(void)
58{
59 thread_register_notifier(&iwmmxt_notifier_block);
60
61 return 0;
62}
63
64late_initcall(iwmmxt_init);
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index a3bae95e536c..b63b528f22a6 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -271,30 +271,27 @@ ENTRY(iwmmxt_task_restore)
271/* 271/*
272 * Concan handling on task switch 272 * Concan handling on task switch
273 * 273 *
274 * r0 = previous task_struct pointer (must be preserved) 274 * r0 = next thread_info pointer
275 * r1 = previous thread_info pointer
276 * r2 = next thread_info pointer (must be preserved)
277 * 275 *
278 * Called only from __switch_to with task preemption disabled. 276 * Called only from the iwmmxt notifier with task preemption disabled.
279 * No need to care about preserving r4 and above.
280 */ 277 */
281ENTRY(iwmmxt_task_switch) 278ENTRY(iwmmxt_task_switch)
282 279
283 mrc p15, 0, r4, c15, c1, 0 280 mrc p15, 0, r1, c15, c1, 0
284 tst r4, #0x3 @ CP0 and CP1 accessible? 281 tst r1, #0x3 @ CP0 and CP1 accessible?
285 bne 1f @ yes: block them for next task 282 bne 1f @ yes: block them for next task
286 283
287 ldr r5, =concan_owner 284 ldr r2, =concan_owner
288 add r6, r2, #TI_IWMMXT_STATE @ get next task Concan save area 285 add r3, r0, #TI_IWMMXT_STATE @ get next task Concan save area
289 ldr r5, [r5] @ get current Concan owner 286 ldr r2, [r2] @ get current Concan owner
290 teq r5, r6 @ next task owns it? 287 teq r2, r3 @ next task owns it?
291 movne pc, lr @ no: leave Concan disabled 288 movne pc, lr @ no: leave Concan disabled
292 289
2931: eor r4, r4, #3 @ flip Concan access 2901: eor r1, r1, #3 @ flip Concan access
294 mcr p15, 0, r4, c15, c1, 0 291 mcr p15, 0, r1, c15, c1, 0
295 292
296 mrc p15, 0, r4, c2, c0, 0 293 mrc p15, 0, r1, c2, c0, 0
297 sub pc, lr, r4, lsr #32 @ cpwait and return 294 sub pc, lr, r1, lsr #32 @ cpwait and return
298 295
299/* 296/*
300 * Remove Concan ownership of given task 297 * Remove Concan ownership of given task
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index e1c77ee885a7..b5773a2549ee 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -353,9 +353,6 @@ void flush_thread(void)
353 memset(&thread->fpstate, 0, sizeof(union fp_state)); 353 memset(&thread->fpstate, 0, sizeof(union fp_state));
354 354
355 thread_notify(THREAD_NOTIFY_FLUSH, thread); 355 thread_notify(THREAD_NOTIFY_FLUSH, thread);
356#if defined(CONFIG_IWMMXT)
357 iwmmxt_task_release(thread);
358#endif
359} 356}
360 357
361void release_thread(struct task_struct *dead_task) 358void release_thread(struct task_struct *dead_task)
@@ -363,9 +360,6 @@ void release_thread(struct task_struct *dead_task)
363 struct thread_info *thread = task_thread_info(dead_task); 360 struct thread_info *thread = task_thread_info(dead_task);
364 361
365 thread_notify(THREAD_NOTIFY_RELEASE, thread); 362 thread_notify(THREAD_NOTIFY_RELEASE, thread);
366#if defined(CONFIG_IWMMXT)
367 iwmmxt_task_release(thread);
368#endif
369} 363}
370 364
371asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 365asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");