diff options
Diffstat (limited to 'recipes/kexecboot/linux-kexecboot-2.6.29/vfp/01-vfp-pm.patch')
-rw-r--r-- | recipes/kexecboot/linux-kexecboot-2.6.29/vfp/01-vfp-pm.patch | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/recipes/kexecboot/linux-kexecboot-2.6.29/vfp/01-vfp-pm.patch b/recipes/kexecboot/linux-kexecboot-2.6.29/vfp/01-vfp-pm.patch new file mode 100644 index 0000000000..70d4d1efc5 --- /dev/null +++ b/recipes/kexecboot/linux-kexecboot-2.6.29/vfp/01-vfp-pm.patch @@ -0,0 +1,128 @@ +From: Ben Dooks <ben-linux@fluff.org> +Date: Thu, 18 Dec 2008 10:26:54 +0000 (+0100) +Subject: 5349/1: VFP: Add PM code to save and restore current VFP state +X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=d504d72ad38e54b5feda67e956834348d6a500e1 + +5349/1: VFP: Add PM code to save and restore current VFP state + +[ARM] 5349/1: VFP: Add PM code to save and restore current VFP state + +When CONFIG_PM is selected, the VFP code does not have any handler +installed to deal with either saving the VFP state of the current +task, nor does it do anything to try and restore the VFP after a +resume. + +On resume, the VFP will have been reset and the co-processor access +control registers are in an indeterminate state (very probably the +CP10 and CP11 the VFP uses will have been disabled by the ARM core +reset). When this happens, resume will break as soon as it tries to +unfreeze the tasks and restart scheduling. + +Add a sys device to allow us to hook the suspend call to save the +current thread state if the thread is using VFP and a resume hook +which restores the CP10/CP11 access and ensures the VFP is disabled +so that the lazy swapping will take place on next access. + +Signed-off-by: Ben Dooks <ben-linux@fluff.org> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +--- + +diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h +index c85860b..8de86e4 100644 +--- a/arch/arm/vfp/vfp.h ++++ b/arch/arm/vfp/vfp.h +@@ -377,6 +377,6 @@ struct op { + u32 flags; + }; + +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) || defined(CONFIG_PM) + extern void vfp_save_state(void *location, u32 fpexc); + #endif +diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S +index a62dcf7..b21f43f 100644 +--- a/arch/arm/vfp/vfphw.S ++++ b/arch/arm/vfp/vfphw.S +@@ -166,7 +166,7 @@ process_exception: + @ retry the faulted instruction + ENDPROC(vfp_support_entry) + +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) || defined(CONFIG_PM) + ENTRY(vfp_save_state) + @ Save the current VFP state + @ r0 - save location +diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c +index 67ca340..9f476a1 100644 +--- a/arch/arm/vfp/vfpmodule.c ++++ b/arch/arm/vfp/vfpmodule.c +@@ -322,6 +322,61 @@ static void vfp_enable(void *unused) + set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11)); + } + ++#ifdef CONFIG_PM ++#include <linux/sysdev.h> ++ ++static int vfp_pm_suspend(struct sys_device *dev, pm_message_t state) ++{ ++ struct thread_info *ti = current_thread_info(); ++ u32 fpexc = fmrx(FPEXC); ++ ++ /* if vfp is on, then save state for resumption */ ++ if (fpexc & FPEXC_EN) { ++ printk(KERN_DEBUG "%s: saving vfp state\n", __func__); ++ vfp_save_state(&ti->vfpstate, fpexc); ++ ++ /* disable, just in case */ ++ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); ++ } ++ ++ /* clear any information we had about last context state */ ++ memset(last_VFP_context, 0, sizeof(last_VFP_context)); ++ ++ return 0; ++} ++ ++static int vfp_pm_resume(struct sys_device *dev) ++{ ++ /* ensure we have access to the vfp */ ++ vfp_enable(NULL); ++ ++ /* and disable it to ensure the next usage restores the state */ ++ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); ++ ++ return 0; ++} ++ ++static struct sysdev_class vfp_pm_sysclass = { ++ .name = "vfp", ++ .suspend = vfp_pm_suspend, ++ .resume = vfp_pm_resume, ++}; ++ ++static struct sys_device vfp_pm_sysdev = { ++ .cls = &vfp_pm_sysclass, ++}; ++ ++static void vfp_pm_init(void) ++{ ++ sysdev_class_register(&vfp_pm_sysclass); ++ sysdev_register(&vfp_pm_sysdev); ++} ++ ++ ++#else ++static inline void vfp_pm_init(void) { } ++#endif /* CONFIG_PM */ ++ + #include <linux/smp.h> + + /* +@@ -365,6 +420,7 @@ static int __init vfp_init(void) + vfp_vector = vfp_support_entry; + + thread_register_notifier(&vfp_notifier_block); ++ vfp_pm_init(); + + /* + * We detected VFP, and the support code is |