aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp/vfpmodule.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-01-30 11:29:05 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-01-30 11:29:05 -0500
commitc9cc8e771cb62e495765793e4b7d06016ae1b525 (patch)
tree42c3ae364cd8b22e3263403f0baa2b5e8070b5da /arch/arm/vfp/vfpmodule.c
parent59df3230fc57fa8900bebf3d2d68221d549f3c7c (diff)
parentb9d1902cd281d9b829fb3d6ee9148d28c8c63382 (diff)
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: [ARM] 4117/1: S3C2412: Fix writel() usage in selection code [ARM] 4111/1: Allow VFP to work with thread migration on SMP [ARM] 4112/1: Only ioremap to supersections if DOMAIN_IO is zero [ARM] 4106/1: S3C2410: typo fixes in register definitions [ARM] 4102/1: Allow for PHYS_OFFSET on any valid 2MiB address [ARM] Fix AMBA serial drivers for non-first serial ports [ARM] 4100/1: iop3xx: fix cpu mask for iop333 [ARM] Update mach-types [ARM] Fix show_mem() for discontigmem [ARM] 4096/1: S3C24XX: change return code form s3c2410_gpio_getcfg() [ARM] 4095/1: S3C24XX: Fix GPIO set for Bank A [ARM] 4092/1: i.MX/MX1 CPU Frequency scaling latency definition [ARM] 4089/1: AT91: GPIO wake IRQ cleanup [ARM] 4088/1: AT91: Unbalanced IRQ in serial driver suspend/resume [ARM] 4087/1: AT91: CPU reset for SAM9x processors [ARM] 4086/1: AT91: Whitespace cleanup [ARM] 4085/1: AT91: Header fixes. [ARM] 4084/1: Remove CONFIG_DEBUG_WAITQ
Diffstat (limited to 'arch/arm/vfp/vfpmodule.c')
-rw-r--r--arch/arm/vfp/vfpmodule.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 490d9d18a7d1..f1e5951dc721 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -28,7 +28,7 @@ void vfp_testing_entry(void);
28void vfp_support_entry(void); 28void vfp_support_entry(void);
29 29
30void (*vfp_vector)(void) = vfp_testing_entry; 30void (*vfp_vector)(void) = vfp_testing_entry;
31union vfp_state *last_VFP_context; 31union vfp_state *last_VFP_context[NR_CPUS];
32 32
33/* 33/*
34 * Dual-use variable. 34 * Dual-use variable.
@@ -41,13 +41,35 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
41{ 41{
42 struct thread_info *thread = v; 42 struct thread_info *thread = v;
43 union vfp_state *vfp; 43 union vfp_state *vfp;
44 __u32 cpu = thread->cpu;
44 45
45 if (likely(cmd == THREAD_NOTIFY_SWITCH)) { 46 if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
47 u32 fpexc = fmrx(FPEXC);
48
49#ifdef CONFIG_SMP
50 /*
51 * On SMP, if VFP is enabled, save the old state in
52 * case the thread migrates to a different CPU. The
53 * restoring is done lazily.
54 */
55 if ((fpexc & FPEXC_ENABLE) && last_VFP_context[cpu]) {
56 vfp_save_state(last_VFP_context[cpu], fpexc);
57 last_VFP_context[cpu]->hard.cpu = cpu;
58 }
59 /*
60 * Thread migration, just force the reloading of the
61 * state on the new CPU in case the VFP registers
62 * contain stale data.
63 */
64 if (thread->vfpstate.hard.cpu != cpu)
65 last_VFP_context[cpu] = NULL;
66#endif
67
46 /* 68 /*
47 * Always disable VFP so we can lazily save/restore the 69 * Always disable VFP so we can lazily save/restore the
48 * old state. 70 * old state.
49 */ 71 */
50 fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); 72 fmxr(FPEXC, fpexc & ~FPEXC_ENABLE);
51 return NOTIFY_DONE; 73 return NOTIFY_DONE;
52 } 74 }
53 75
@@ -68,8 +90,8 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
68 } 90 }
69 91
70 /* flush and release case: Per-thread VFP cleanup. */ 92 /* flush and release case: Per-thread VFP cleanup. */
71 if (last_VFP_context == vfp) 93 if (last_VFP_context[cpu] == vfp)
72 last_VFP_context = NULL; 94 last_VFP_context[cpu] = NULL;
73 95
74 return NOTIFY_DONE; 96 return NOTIFY_DONE;
75} 97}