diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-18 05:59:49 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-20 10:09:13 -0500 |
commit | 90b44199e83ec780d6def11a602d825dc68438e3 (patch) | |
tree | 82e09f5b197b1fe759c122085e6e4e6c59e4c969 /arch/arm/vfp | |
parent | 3705ff6da538aff6dba535e2e9cbcbb9456d0d53 (diff) |
ARM: VFP: re-initialize VFP coprocessor access enables on CPU hotplug
We can not guarantee that VFP will be enabled when CPU hotplug brings
a CPU back online from a reset state. Add a hotplug CPU notifier to
ensure that the VFP coprocessor access is enabled whenever a CPU comes
back online.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r-- | arch/arm/vfp/vfpmodule.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 8063a322c790..0797cb528b46 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -10,9 +10,12 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/cpu.h> | ||
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/notifier.h> | ||
14 | #include <linux/signal.h> | 16 | #include <linux/signal.h> |
15 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/smp.h> | ||
16 | #include <linux/init.h> | 19 | #include <linux/init.h> |
17 | 20 | ||
18 | #include <asm/cputype.h> | 21 | #include <asm/cputype.h> |
@@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_info *thread) | |||
484 | put_cpu(); | 487 | put_cpu(); |
485 | } | 488 | } |
486 | 489 | ||
487 | #include <linux/smp.h> | 490 | /* |
491 | * VFP hardware can lose all context when a CPU goes offline. | ||
492 | * Safely clear our held state when a CPU has been killed, and | ||
493 | * re-enable access to VFP when the CPU comes back online. | ||
494 | * | ||
495 | * Both CPU_DYING and CPU_STARTING are called on the CPU which | ||
496 | * is being offlined/onlined. | ||
497 | */ | ||
498 | static int vfp_hotplug(struct notifier_block *b, unsigned long action, | ||
499 | void *hcpu) | ||
500 | { | ||
501 | if (action == CPU_DYING || action == CPU_DYING_FROZEN) { | ||
502 | unsigned int cpu = (long)hcpu; | ||
503 | last_VFP_context[cpu] = NULL; | ||
504 | } else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) | ||
505 | vfp_enable(NULL); | ||
506 | return NOTIFY_OK; | ||
507 | } | ||
488 | 508 | ||
489 | /* | 509 | /* |
490 | * VFP support code initialisation. | 510 | * VFP support code initialisation. |
@@ -514,6 +534,8 @@ static int __init vfp_init(void) | |||
514 | else if (vfpsid & FPSID_NODOUBLE) { | 534 | else if (vfpsid & FPSID_NODOUBLE) { |
515 | printk("no double precision support\n"); | 535 | printk("no double precision support\n"); |
516 | } else { | 536 | } else { |
537 | hotcpu_notifier(vfp_hotplug, 0); | ||
538 | |||
517 | smp_call_function(vfp_enable, NULL, 1); | 539 | smp_call_function(vfp_enable, NULL, 1); |
518 | 540 | ||
519 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ | 541 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ |