From patchwork Wed Aug 5 16:32:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 51968 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f198.google.com (mail-lb0-f198.google.com [209.85.217.198]) by patches.linaro.org (Postfix) with ESMTPS id 196C6229FD for ; Wed, 5 Aug 2015 16:35:12 +0000 (UTC) Received: by lbcjf8 with SMTP id jf8sf14936563lbc.0 for ; Wed, 05 Aug 2015 09:35:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=nSrijifra5BTae8RrQ/n1bLT1ZGI/xIP3X4e55xNgXY=; b=XNEmJ5umk7k53ud0vjV5CC+m4ZAuwtPDnLHoPQXyyrJkFEuH9gXB6bTPBP2wCljfpV VYrhNqoAQebX08DXyj4MihbIhK8tfvzJk5lQjt2PLVKjoobYwZQiKIIzTrmGLeY2fxIc j29SeJi41Wm7nSBCijHJjU8FiCDfE7H5rSLhd5pR+YYs6Ja4l5LvVSmC8PX2h+VwhlnE IEOmrRZIm9OEZTIC+S04Q+GXyWJI+Jbwdr+LUtzLkqfReNK33+f7pfvXSSx8goOiKzuU QpdfemB7G8c4Cz5VFreea8T5L45r3ROzE30ltxbJdyKpptQZRQ29nwBeU79+z0fJ324x Z/Ww== X-Gm-Message-State: ALoCoQn62OKrOHUfmlPUDeLfApFJ7F8i3SHjUyZJkSAjteaUOnpo4ww13dNE92Q53lHmIMvzXgBd X-Received: by 10.112.138.2 with SMTP id qm2mr2983263lbb.19.1438792511097; Wed, 05 Aug 2015 09:35:11 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.5.200 with SMTP id u8ls197043lau.55.gmail; Wed, 05 Aug 2015 09:35:10 -0700 (PDT) X-Received: by 10.152.3.70 with SMTP id a6mr10085390laa.44.1438792510945; Wed, 05 Aug 2015 09:35:10 -0700 (PDT) Received: from mail-lb0-f170.google.com (mail-lb0-f170.google.com. [209.85.217.170]) by mx.google.com with ESMTPS id le10si2433830lac.158.2015.08.05.09.35.10 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Aug 2015 09:35:10 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) client-ip=209.85.217.170; Received: by lbbvv8 with SMTP id vv8so25229050lbb.1 for ; Wed, 05 Aug 2015 09:35:10 -0700 (PDT) X-Received: by 10.152.5.228 with SMTP id v4mr10055129lav.36.1438792510791; Wed, 05 Aug 2015 09:35:10 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.7.198 with SMTP id l6csp468072lba; Wed, 5 Aug 2015 09:35:09 -0700 (PDT) X-Received: by 10.68.116.77 with SMTP id ju13mr20886606pbb.50.1438792501857; Wed, 05 Aug 2015 09:35:01 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id mx11si6094900pbc.120.2015.08.05.09.35.00; Wed, 05 Aug 2015 09:35:01 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753341AbbHEQeJ (ORCPT + 8 others); Wed, 5 Aug 2015 12:34:09 -0400 Received: from mail-pa0-f46.google.com ([209.85.220.46]:33394 "EHLO mail-pa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753303AbbHEQdS (ORCPT ); Wed, 5 Aug 2015 12:33:18 -0400 Received: by pabyb7 with SMTP id yb7so8038601pab.0 for ; Wed, 05 Aug 2015 09:33:18 -0700 (PDT) X-Received: by 10.66.255.67 with SMTP id ao3mr21096772pad.60.1438792398098; Wed, 05 Aug 2015 09:33:18 -0700 (PDT) Received: from ubuntu.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id oq10sm3434036pdb.75.2015.08.05.09.33.16 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 05 Aug 2015 09:33:17 -0700 (PDT) From: Lina Iyer To: linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-pm@vger.kernel.org Cc: agross@codeaurora.org, msivasub@codeaurora.org, sboyd@codeaurora.org, robh@kernel.org, Lina Iyer Subject: [PATCH RFC 09/10] drivers: qcom: spm: Use hwspinlock to serialize entry into SCM Date: Wed, 5 Aug 2015 10:32:45 -0600 Message-Id: <1438792366-2737-10-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1438792366-2737-1-git-send-email-lina.iyer@linaro.org> References: <438731339-58317-1-git-send-email-lina.iyer@linaro.org> <1438792366-2737-1-git-send-email-lina.iyer@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: devicetree@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: lina.iyer@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , When the last CPU enters idle, the state of L2 is determined and the power controller for the L2 is programmed to power down. The power controllers' state machine is only triggered when all the CPUs have executed their WFI instruction. Multiple CPUs may enter SCM to power down at the same time. Linux identifies the last man down and determines the state of the cluster, but an FIQ could have kept another CPU busy. The last CPU to enter SCM may not be the last CPU as determined by Linux. So the state of the cluster would not be correctly relayed to the SCM. To ensure that the last CPU in Linux is the same in SCM, serialize the entry into SCM. Linux is responsible for flushing non-secure L2, while SCM flushes only the secure lines of L2. Invalidation for secure and non-secure L2 is done by the SCM when the first CPU resumes from idle. An example of the last man race - Say there are two cores powering down - CoreA and CoreB CoreA enters idle is not the last core and about to call into SCM CoreB enters idle and is the last core, determines L2 should be flushed CoreB receives an FIQ and gets busy handling the FIQ CoreA has an pending IRQ, bails out of SCM and cpuidle CoreB is still busy CoreA enters cpuidle again and now is the last core CoreA determines L2 should *not* be flushed and calls SCM CoreB finishes FIQ, enters SCM with a stale L2 state (L2 to be flushed) SCM records L2 as flushed and invalidates L2 when a core comes up. To avoid this race, serialize all entry from Linux to SCM for cpuidle. A hwspinlock is locked by Linux and released by the SCM when the context switches to Secure. This way, the last man view of both Linux and SCM, match with that of the L2 power controller configuration. A raw hwspinlock would not use s/w spinlocks around the hwspinlock. Since there is no possiblity of preemption in cpuidle, it is safe to use the raw variant of the hwspinlock. Signed-off-by: Lina Iyer --- drivers/soc/qcom/Kconfig | 1 + drivers/soc/qcom/spm.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index b6c2e5d..cb50efb 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -18,6 +18,7 @@ config QCOM_PM select PM_GENERIC_DOMAINS select PM_GENERIC_DOMAINS_SLEEP select PM_GENERIC_DOMAINS_OF + select HWSPINLOCK_QCOM help QCOM Platform specific power driver to manage cores and L2 low power modes. It interface with various system drivers to put the cores in diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index b6d75db..bd09514 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -38,6 +40,7 @@ #define SPM_CTL_INDEX 0x7f #define SPM_CTL_INDEX_SHIFT 4 #define SPM_CTL_EN BIT(0) +#define QCOM_PC_HWLOCK 7 enum pm_sleep_mode { PM_SLEEP_MODE_STBY, @@ -139,6 +142,7 @@ static int l2_flush_flag; typedef int (*idle_fn)(int); static DEFINE_PER_CPU(idle_fn*, qcom_idle_ops); +static struct hwspinlock *remote_lock; static inline void spm_register_write(struct spm_driver_data *drv, enum spm_reg reg, u32 val) @@ -198,6 +202,24 @@ static int qcom_pm_collapse(unsigned long int unused) if (l2_flush_flag == QCOM_SCM_CPU_PWR_DOWN_L2_OFF) flush_cache_all(); + /* + * Wait and acquire the hwspin lock to synchronize + * the entry into SCM. The view of the last core in Linux + * should be same for SCM so the l2_flush_flag is correct. + * + * * IMPORTANT * + * 1. SCM unlocks this lock. + * 2. We do not want to call api that would spinlock before + * acquiring the hwspin lock. It will not be unlocked. + * So call raw variant + * 3. Every core needs to acquire this lock and the entry into + * SCM would be serialized after this point. + */ + if (remote_lock) { + while (hwspin_trylock_raw(remote_lock)) + ; + } + qcom_scm_cpu_power_down(l2_flush_flag); /* @@ -439,6 +461,10 @@ static int spm_dev_probe(struct platform_device *pdev) else per_cpu(cpu_spm_drv, index) = drv; + /* Initialize hwspinlock, to serialize entry into secure */ + if (!remote_lock && of_match_node(cache_spm_table, pdev->dev.of_node)) + remote_lock = hwspin_lock_request_specific(QCOM_PC_HWLOCK); + dev_dbg(&pdev->dev, "SPM device probed.\n"); return 0; }