diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-18 10:59:49 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-20 15:09:13 +0000 |
commit | 90b44199e83ec780d6def11a602d825dc68438e3 (patch) | |
tree | 82e09f5b197b1fe759c122085e6e4e6c59e4c969 | |
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>
-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 @@ */ #include <linux/module.h> #include <linux/types.h> +#include <linux/cpu.h> #include <linux/kernel.h> +#include <linux/notifier.h> #include <linux/signal.h> #include <linux/sched.h> +#include <linux/smp.h> #include <linux/init.h> #include <asm/cputype.h> @@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_info *thread) put_cpu(); } -#include <linux/smp.h> +/* + * VFP hardware can lose all context when a CPU goes offline. + * Safely clear our held state when a CPU has been killed, and + * re-enable access to VFP when the CPU comes back online. + * + * Both CPU_DYING and CPU_STARTING are called on the CPU which + * is being offlined/onlined. + */ +static int vfp_hotplug(struct notifier_block *b, unsigned long action, + void *hcpu) +{ + if (action == CPU_DYING || action == CPU_DYING_FROZEN) { + unsigned int cpu = (long)hcpu; + last_VFP_context[cpu] = NULL; + } else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) + vfp_enable(NULL); + return NOTIFY_OK; +} /* * VFP support code initialisation. @@ -514,6 +534,8 @@ static int __init vfp_init(void) else if (vfpsid & FPSID_NODOUBLE) { printk("no double precision support\n"); } else { + hotcpu_notifier(vfp_hotplug, 0); + smp_call_function(vfp_enable, NULL, 1); VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ |