From patchwork Thu Feb 25 12:16:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Lindgren X-Patchwork-Id: 12104037 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 67970C433E0 for ; Thu, 25 Feb 2021 12:18:14 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1084064F0C for ; Thu, 25 Feb 2021 12:18:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1084064F0C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=atomide.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:To:From: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=Ut0492H387Ghq/LXtWXcCX8cy1XUX4PXxWiVIuePEg8=; b=HT4UCSXSESbAZPaK5/U0GUjHLm /q/N+UzxcQsKBDWY0/YR5YQpqwrfpqgYkLGahf8BKEFn8dKlcZCzUXhHzDpYSWhSd9Q81A9kxCqON rNPheiD9b8fyX951D9hDf9/yMqwhQT/17WZmwggIIKC2xvPEzcZ/Oe7v3B2FNdiw1M5V7RH8z3y7r H69zRf/M7Al/nWdDRebctPtOS4tJvug5h3mEgiSUSB2Zd1K2VrJDkkSkJdNj532XCWuCUS1YZq2HD qO++d9K30PZZ8/vhEUhbtkaMdwJvDU9l6Fy39ilfHreB3fw0xojU0EM5AuQJImxCCS0Ac1dMQRjoB rVnwYt9g==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1lFFZA-0004w2-EJ; Thu, 25 Feb 2021 12:16:24 +0000 Received: from muru.com ([72.249.23.125]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1lFFZ7-0004v3-5A for linux-arm-kernel@lists.infradead.org; Thu, 25 Feb 2021 12:16:21 +0000 Received: from hillo.muru.com (localhost [127.0.0.1]) by muru.com (Postfix) with ESMTP id 3E663807A; Thu, 25 Feb 2021 12:16:48 +0000 (UTC) From: Tony Lindgren To: linux-omap@vger.kernel.org Subject: [PATCH] ARM: OMAP4: Fix cpu_pm handling for HS/EMU interrupt save Date: Thu, 25 Feb 2021 14:16:12 +0200 Message-Id: <20210225121612.18818-1-tony@atomide.com> X-Mailer: git-send-email 2.30.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210225_071621_265302_ED511B10 X-CRM114-Status: GOOD ( 18.70 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Carl Philipp Klemm , Ivan Jelincic , Merlijn Wajer , Sebastian Reichel , Pavel Machek , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Since commit 55be2f50336f ("ARM: OMAP2+: Handle errors for cpu_pm") we allow the drivers to block deeper idle states with cpu_pm notifiers. Turns out this change causes random hangs on a mostly idle droid4. The hang seems to be caused by reconfiguring the MPUSS domain registers after we have already called irq_save_secure_context(). This happens on the cpu_pm notifier error path if a driver is busy and returns NOTIFY_BAD in CPU_CLUSTER_PM_ENTER handling to block the deeper idle states. Note that this issue does not exist for the GP SoCs, for them we just save and restore the context in the cpu_pm notifier. Let's fix the issue by calling omap4_irq_save_secure_context() later on after the cpu_pm notifiers are done. And since we have omap-secure.c, let's move omap4_irq_save_secure_context() there. Fixes: 55be2f50336f ("ARM: OMAP2+: Handle errors for cpu_pm") Reported-by: Carl Philipp Klemm Reported-by: Merlijn Wajer Cc: Ivan Jelincic Cc: Pavel Machek Cc: Sebastian Reichel Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap-mpuss-lowpower.c | 17 ++++++++++++----- arch/arm/mach-omap2/omap-secure.c | 16 ++++++++++++++++ arch/arm/mach-omap2/omap-secure.h | 1 + arch/arm/mach-omap2/omap-wakeupgen.c | 20 ++++---------------- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -48,6 +48,7 @@ #include "soc.h" #include "common.h" +#include "omap-secure.h" #include "omap44xx.h" #include "omap4-sar-layout.h" #include "pm.h" @@ -256,15 +257,21 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) pwrdm_pre_transition(NULL); - /* - * Check MPUSS next state and save interrupt controller if needed. - * In MPUSS OSWR or device OFF, interrupt controller contest is lost. - */ + /* Check MPUSS next state to see if context is lost */ mpuss_clear_prev_logic_pwrst(); if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) && - (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) + (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) { save_state = 2; + /* + * Save interrupt controller for HS/EMU if needed. In MPUSS OSWR + * and device OFF, interrupt controller context is lost. For GP + * SoCs, see the cpu_pm notifiers and cpu_pm irq_notifier(). + */ + if (!cpu && omap_type() != OMAP2_DEVICE_TYPE_GP) + omap4_irq_save_secure_context(); + } + cpu_clear_prev_logic_pwrst(cpu); pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); pwrdm_set_logic_retst(pm_info->pwrdm, cpu_logic_state); diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c --- a/arch/arm/mach-omap2/omap-secure.c +++ b/arch/arm/mach-omap2/omap-secure.c @@ -135,6 +135,22 @@ u32 omap3_save_secure_ram(void __iomem *addr, int size) } #endif +/* + * Save GIC and Wakeupgen interrupt context using secure API for HS/EMU devices. + * Must be called after cpu_pm notifiers to avoid reconfiguring MPUSS on the + * cpu_pm notifier error path. + */ +void __maybe_unused omap4_irq_save_secure_context(void) +{ + u32 ret; + + ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX, + FLAG_START_CRITICAL, + 0, 0, 0, 0, 0); + if (ret != API_HAL_RET_VALUE_OK) + pr_err("GIC and Wakeupgen context save failed\n"); +} + /** * rx51_secure_dispatcher: Routine to dispatch secure PPA API calls * @idx: The PPA API index diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h --- a/arch/arm/mach-omap2/omap-secure.h +++ b/arch/arm/mach-omap2/omap-secure.h @@ -73,6 +73,7 @@ extern phys_addr_t omap_secure_ram_mempool_base(void); extern int omap_secure_ram_reserve_memblock(void); extern u32 save_secure_ram_context(u32 args_pa); extern u32 omap3_save_secure_ram(void __iomem *save_regs, int size); +extern void omap4_irq_save_secure_context(void); extern u32 rx51_secure_dispatcher(u32 idx, u32 process, u32 flag, u32 nargs, u32 arg1, u32 arg2, u32 arg3, u32 arg4); diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -367,20 +367,6 @@ static void irq_restore_context(void) wakeupgen_ops->restore_context(); } -/* - * Save GIC and Wakeupgen interrupt context using secure API - * for HS/EMU devices. - */ -static void irq_save_secure_context(void) -{ - u32 ret; - ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX, - FLAG_START_CRITICAL, - 0, 0, 0, 0, 0); - if (ret != API_HAL_RET_VALUE_OK) - pr_err("GIC and Wakeupgen context save failed\n"); -} - /* Define ops for context save and restore for each SoC */ static struct omap_wakeupgen_ops omap4_wakeupgen_ops = { .save_context = omap4_irq_save_context, @@ -429,14 +415,16 @@ static void __init irq_hotplug_init(void) #endif #ifdef CONFIG_CPU_PM +/* + * Note that gic context save for HS/EMU devices must be done after the cpu_pm + * notifiers, see omap4_irq_save_secure_context(). + */ static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v) { switch (cmd) { case CPU_CLUSTER_PM_ENTER: if (omap_type() == OMAP2_DEVICE_TYPE_GP || soc_is_am43xx()) irq_save_context(); - else - irq_save_secure_context(); break; case CPU_CLUSTER_PM_EXIT: if (omap_type() == OMAP2_DEVICE_TYPE_GP || soc_is_am43xx())