From patchwork Wed Jun 21 19:21:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 106121 Delivered-To: patches@linaro.org Received: by 10.140.91.2 with SMTP id y2csp2092673qgd; Wed, 21 Jun 2017 12:21:57 -0700 (PDT) X-Received: by 10.25.79.25 with SMTP id d25mr12194965lfb.133.1498072917068; Wed, 21 Jun 2017 12:21:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498072917; cv=none; d=google.com; s=arc-20160816; b=ADnMkpba6MsyqD/pUGj1dAv0zxwk7P9rmcaf/iyfxnCCvvR81pj0PG3+59nAmhnclt VCABlgbrCZMUiuf6aA7zPnVFFgk/ODPzv1vrDVD7zZT5ku6I2raKa8Mp0YRffXjNfoNP px5dB/deVzzK11o3ELYdQmiGNhC3nkuGo5YKZXcZz1siWRqe/PrAe2CIai9ABrFCEP4s dtWB5uXe3/QuhPCeY6N/lKqbjyVdCZKPs5jpDIKLLs3fwcjrBVArNpvTTvAMFhwrPTGQ /SbWqqOOUq+h8Jypj3rfFuteEZNSolLw8VXCDpo/uFvM0AjLwub/DkyBIY92Gh3Zkc9q QgjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=L0Bxj+RAgtEBUb4zoOfwrjAydIDoVxBTErkG28rFqDg=; b=EcqTFgLtu949ZwU/C0vDQ/UIEW1Sx+9sHfSQbFYJOhD1PpEe51v6dGO4cSh5Lr1mDD tfFoScGorYvzVZ5STZojSEVfEU6McpG0bIxP4s7c6W8DZV1wRyezFAiToeev6Xt72/ag Le5H8lPdX3wwA9g3or8OkfHrnUl+WhP+iSZ70QjGBGlUmiCDm6gBfVNSNlTCPk88EChh Tz2efgEMnQPlqLAl38rfZ5S4L1Euu5nePMV7O41/ikNClazX9kdOAFcqEACbCAb2ILeS o8cZ2c2efVS84RbKWSILUNhJFj2oJhcjNqXlX14mOYrkGhtvrvxI2gxyjVte35tLlbKS F6Mw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=JMZnweGX; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:4010:c07::22f as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-lf0-x22f.google.com (mail-lf0-x22f.google.com. [2a00:1450:4010:c07::22f]) by mx.google.com with ESMTPS id z2si6441453lfa.120.2017.06.21.12.21.56 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Jun 2017 12:21:57 -0700 (PDT) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:4010:c07::22f as permitted sender) client-ip=2a00:1450:4010:c07::22f; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.b=JMZnweGX; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:4010:c07::22f as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by mail-lf0-x22f.google.com with SMTP id p189so102985486lfe.2 for ; Wed, 21 Jun 2017 12:21:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=L0Bxj+RAgtEBUb4zoOfwrjAydIDoVxBTErkG28rFqDg=; b=JMZnweGXE6cfTzq7pnNuqP1d+D0VCi66aT+yTlyccON8Gg5x83vlianEiZiks0hjcT ZJUvK/r+8eR6QiD277Fy11GY8cW94xdUog3oZzCoAMdQunvyZjZG06Gu7C0hOAUBa/us uTGUmp2WZ+3cEnkkRMUP7xFVPjgAHsBhcckD0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=L0Bxj+RAgtEBUb4zoOfwrjAydIDoVxBTErkG28rFqDg=; b=Y1q7hnlRpmxC52QMBunR17JLJdUaXTWrQGPulUybi6gxRu3upU/yc9QELwFMS8gjRp 2qDzRbjppjWTejw56nnTfvpuJFNO04ACu/Q/BBOqU/pKw1EpuM90f+PK+5acrx+chP6u TCekfOmypPDXpuYTJvuH+10C38T2yDPx0cvfTLSZHqVYg//ubfLyFSxGX5jLAaEHAiq3 3L1lrdVe/W8d/FYBLH6oEvZORQLpKQsnxQDTQ1mUHfWBV9852vc1tTbBTWSKfogGrC6s TEuMYUgLFBwUn1e1OCLP4Jv0v8/9DIhhg5AkhoIgDFdrcJ1+zFW0uWTlOsidjFwMLhii n6cA== X-Gm-Message-State: AKS2vOx7tj7jZqixAdVw6TL81KczVwo9lrpCNYL1JjwD6j4t51rosK4D KSzs384bhWrq2T1uzA4= X-Received: by 10.46.83.13 with SMTP id h13mr9780791ljb.102.1498072916598; Wed, 21 Jun 2017 12:21:56 -0700 (PDT) Return-Path: Received: from localhost.localdomain (h-158-174-22-67.NA.cust.bahnhof.se. [158.174.22.67]) by smtp.gmail.com with ESMTPSA id t24sm3920047ljd.1.2017.06.21.12.21.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 21 Jun 2017 12:21:55 -0700 (PDT) From: Ulf Hansson To: Wolfram Sang , "Rafael J . Wysocki" , Len Brown , linux-acpi@vger.kernel.org, linux-pm@vger.kernel.org Cc: Kevin Hilman , Jarkko Nikula , Andy Shevchenko , Mika Westerberg , Jisheng Zhang , John Stultz , Guodong Xu , Sumit Semwal , Haojian Zhuang , linux-arm-kernel@lists.infradead.org, linux-i2c@vger.kernel.org, Ulf Hansson Subject: [PATCH 7/9] PM / ACPI: Enable the runtime PM centric approach for system sleep Date: Wed, 21 Jun 2017 21:21:26 +0200 Message-Id: <1498072888-14782-8-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1498072888-14782-1-git-send-email-ulf.hansson@linaro.org> References: <1498072888-14782-1-git-send-email-ulf.hansson@linaro.org> This change extends the interpretation of the ACPI's no_direct_complete flag to be used to enable the so called runtime PM centric approach, for devices being attached to the ACPI PM domain. The principle behind the runtime PM centric approach is to re-use the runtime PM callbacks to implement system sleep for drivers/subsystems. Moreover, using the runtime PM centric approach gives an optimized behaviour around avoiding to wake up a device from its low power state during system sleep, unless really needed. To deploy the runtime PM centric approach for a subsystem/driver, the following adaptations needs to be made. First, the runtime PM callbacks may be called when runtime PM has been disabled for the device. This serves as an indication for the callbacks to understand they are running in the system sleep sequence, instead of in the regular runtime PM path. In some cases, a callback needs to take different actions depending in what path it is being executed in, as is the case for the ACPI PM domain. In particular for the ACPI PM domain's ->runtime_suspend|resume() callbacks, when those finds runtime PM being disabled for the device, it instead executes the same operations as normally being run when ->suspend_late() and ->resume_early() callbacks are invoked during system sleep. Second, at the PM domain level, it is expected that the driver for the device makes use of pm_runtime_force_suspend|resume(), to re-use the runtime PM callbacks to put the device into low power state and to wake it up when needed during system sleep. For the ACPI PM domain's ->suspend_late() and ->resume_early() callbacks, it means bypassing the operations putting the device into low power state and the operations that wakes it up. Instead it shall invoke only the lower level ->suspend_late() and ->resume_early() callbacks for the driver, if present. Signed-off-by: Ulf Hansson --- drivers/acpi/acpi_lpss.c | 58 +++++++++++++++++++++++++++++++++--------------- drivers/acpi/device_pm.c | 56 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 89 insertions(+), 25 deletions(-) -- 2.7.4 diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 12bc5c7..adc84b3 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -714,10 +714,11 @@ static int lpss_suspend_late(struct device *dev) static int acpi_lpss_suspend_late(struct device *dev) { + struct acpi_device *adev = ACPI_COMPANION(dev); int ret; ret = pm_generic_suspend_late(dev); - if (ret) + if (ret || adev->no_direct_complete) return ret; return lpss_suspend_late(dev); @@ -742,13 +743,23 @@ static int lpss_resume_early(struct device *dev) static int acpi_lpss_resume_early(struct device *dev) { - int ret; + struct acpi_device *adev = ACPI_COMPANION(dev); + int ret = 0; - ret = lpss_resume_early(dev); - if (ret) - return ret; + if (!adev->no_direct_complete) + ret = lpss_resume_early(dev); - return pm_generic_resume_early(dev); + return ret ? ret : pm_generic_resume_early(dev); +} +#else +static inline int lpss_suspend_late(struct device *dev) +{ + return 0; +} + +static inline int lpss_resume_early(struct device *dev) +{ + return 0; } #endif /* CONFIG_PM_SLEEP */ @@ -846,6 +857,9 @@ static int acpi_lpss_runtime_suspend(struct device *dev) if (ret) return ret; + if (!pm_runtime_enabled(dev)) + return lpss_suspend_late(dev); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) acpi_lpss_save_ctx(dev, pdata); @@ -867,21 +881,29 @@ static int acpi_lpss_runtime_resume(struct device *dev) struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); int ret; - /* - * This call is kept first to be in symmetry with - * acpi_lpss_runtime_suspend() one. - */ - if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available()) - lpss_iosf_exit_d3_state(); + if (pm_runtime_enabled(dev)) { + /* + * This call is kept first to be in symmetry with + * acpi_lpss_runtime_suspend() one. + */ + if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && + iosf_mbi_available()) + lpss_iosf_exit_d3_state(); - ret = acpi_dev_runtime_resume(dev); - if (ret) - return ret; + ret = acpi_dev_runtime_resume(dev); + if (ret) + return ret; - acpi_lpss_d3_to_d0_delay(pdata); + acpi_lpss_d3_to_d0_delay(pdata); - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) - acpi_lpss_restore_ctx(dev, pdata); + if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + acpi_lpss_restore_ctx(dev, pdata); + + } else { + ret = lpss_resume_early(dev); + if (ret) + return ret; + } return pm_generic_runtime_resume(dev); } diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 2393a1a..e0324ab 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -859,7 +859,14 @@ EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume); int acpi_subsys_runtime_suspend(struct device *dev) { int ret = pm_generic_runtime_suspend(dev); - return ret ? ret : acpi_dev_runtime_suspend(dev); + + if (ret) + return ret; + + if (!pm_runtime_enabled(dev)) + return acpi_dev_suspend_late(dev); + + return acpi_dev_runtime_suspend(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend); @@ -872,7 +879,17 @@ EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend); */ int acpi_subsys_runtime_resume(struct device *dev) { - int ret = acpi_dev_runtime_resume(dev); + struct acpi_device *adev = ACPI_COMPANION(dev); + int ret = 0; + + if (!adev) + return 0; + + if (!pm_runtime_enabled(dev)) + ret = acpi_dev_resume_early(dev); + else + ret = acpi_dev_runtime_resume(dev); + return ret ? ret : pm_generic_runtime_resume(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume); @@ -1015,13 +1032,21 @@ EXPORT_SYMBOL_GPL(acpi_subsys_prepare); */ void acpi_subsys_complete(struct device *dev) { + struct acpi_device *adev = ACPI_COMPANION(dev); + + if (!adev) + return; + pm_generic_complete(dev); /* * If the device had been runtime-suspended before the system went into * the sleep state it is going out of and it has never been resumed till - * now, resume it in case the firmware powered it up. + * now, resume it in case the firmware powered it up. Also resume it in + * case no_direct_complete is set for the device, to be sure the device + * are managed correctly when firmware has powered it up. */ - if (dev->power.direct_complete && pm_resume_via_firmware()) + if ((dev->power.direct_complete || adev->no_direct_complete) && + pm_resume_via_firmware()) pm_request_resume(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_complete); @@ -1049,8 +1074,17 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend); */ int acpi_subsys_suspend_late(struct device *dev) { - int ret = pm_generic_suspend_late(dev); - return ret ? ret : acpi_dev_suspend_late(dev); + struct acpi_device *adev = ACPI_COMPANION(dev); + int ret; + + if (!adev) + return 0; + + ret = pm_generic_suspend_late(dev); + if (ret || adev->no_direct_complete) + return ret; + + return acpi_dev_suspend_late(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late); @@ -1064,7 +1098,15 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late); */ int acpi_subsys_resume_early(struct device *dev) { - int ret = acpi_dev_resume_early(dev); + struct acpi_device *adev = ACPI_COMPANION(dev); + int ret = 0; + + if (!adev) + return 0; + + if (!adev->no_direct_complete) + ret = acpi_dev_resume_early(dev); + return ret ? ret : pm_generic_resume_early(dev); } EXPORT_SYMBOL_GPL(acpi_subsys_resume_early);