diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-01-30 11:29:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-01-30 11:29:05 -0500 |
commit | c9cc8e771cb62e495765793e4b7d06016ae1b525 (patch) | |
tree | 42c3ae364cd8b22e3263403f0baa2b5e8070b5da /arch/arm/vfp/vfpmodule.c | |
parent | 59df3230fc57fa8900bebf3d2d68221d549f3c7c (diff) | |
parent | b9d1902cd281d9b829fb3d6ee9148d28c8c63382 (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.c | 30 |
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); | |||
28 | void vfp_support_entry(void); | 28 | void vfp_support_entry(void); |
29 | 29 | ||
30 | void (*vfp_vector)(void) = vfp_testing_entry; | 30 | void (*vfp_vector)(void) = vfp_testing_entry; |
31 | union vfp_state *last_VFP_context; | 31 | union 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 | } |