From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753994Ab2GPSRd (ORCPT ); Mon, 16 Jul 2012 14:17:33 -0400 Received: from mail-wi0-f202.google.com ([209.85.212.202]:49824 "EHLO mail-wi0-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751919Ab2GPSRb (ORCPT ); Mon, 16 Jul 2012 14:17:31 -0400 From: Colin Cross To: linux-arm-kernel@lists.infradead.org Cc: Catalin Marinas , Will Deacon , Nicolas Pitre , Colin Cross , Russell King , Barry Song , Catalin Marinas , Ido Yariv , Daniel Drake , linux-kernel@vger.kernel.org Subject: [PATCH v6] ARM: vfp: Always save VFP state in vfp_pm_suspend on UP Date: Mon, 16 Jul 2012 11:17:20 -0700 Message-Id: <1342462640-18410-1-git-send-email-ccross@android.com> X-Mailer: git-send-email 1.7.7.3 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org vfp_pm_suspend should save the VFP state in suspend after any lazy context switch. If it only saves when the VFP is enabled, the state can get lost when, on a UP system: Thread 1 uses the VFP Context switch occurs to thread 2, VFP is disabled but the VFP context is not saved Thread 2 initiates suspend vfp_pm_suspend is called with the VFP disabled, and the unsaved VFP context of Thread 1 in the registers Modify vfp_pm_suspend to save the VFP context whenever vfp_current_hw_state is not NULL. Includes a fix from Ido Yariv , who pointed out that on SMP systems, the state pointer can be pointing to a freed task struct if a task exited on another cpu, fixed by using #ifdef CONFIG_SMP in the new if clause. Cc: Russell King Cc: Barry Song Cc: Catalin Marinas Cc: Ido Yariv Cc: Daniel Drake Cc: Will Deacon Signed-off-by: Colin Cross --- arch/arm/vfp/vfpmodule.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 58696192..ce55f05 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -457,6 +457,12 @@ static int vfp_pm_suspend(void) /* disable, just in case */ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + } else if (vfp_current_hw_state[ti->cpu]) { +#ifndef CONFIG_SMP + fmxr(FPEXC, fpexc | FPEXC_EN); + vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc); + fmxr(FPEXC, fpexc); +#endif } /* clear any information we had about last context state */ -- 1.7.7.3