diff options
Diffstat (limited to 'arch/arm/vfp/vfpmodule.c')
| -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 8063a322c79..0797cb528b4 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 */  |