From patchwork Sat Mar 1 10:56:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 25568 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f72.google.com (mail-pb0-f72.google.com [209.85.160.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 36D54206A6 for ; Sat, 1 Mar 2014 10:56:24 +0000 (UTC) Received: by mail-pb0-f72.google.com with SMTP id jt11sf4752133pbb.7 for ; Sat, 01 Mar 2014 02:56:24 -0800 (PST) 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:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=BdoKykRjd8FzbqPP5e/oujN6Wqrfxd5q3sqbBgy23o4=; b=XzTEmTG2svl38qQnIFugATHydQ2+oSez2zrIz6HcDyn+zjqnKQEk67qHPhlb+hYnx0 iVgLrddn9n9YL0cROkb5E2Ma7kwkCVABg4C5j/0AVyIt6sVnZcOuwYNqOdcRm54TDgL7 WSKyBUgJClCnWdKqT+4HYqhJxsJu2lu6R1KYMkLDR/Lvr2WVl++lEES5Rk88Cbdnbyz2 0ReeYfAoSCoNi4Fdy2uu/LlyuXKB0MEUZtwKDKFb9EDl3LlFiF81jj/06lgsPFeByPZc +RTrzLoH3TBH1FrhPJuF2pUKQWjB3mxJ0JaW9/kG4HNUZuUS5q3HKsi59+6x4Z05EXMJ RpVg== X-Gm-Message-State: ALoCoQn7ExsR0b7MQbbp1ufeD/OuCDMM6sUfmZL89Z9amAOvurvVEdJSEgjJgDLLT5JWh2p6izTh X-Received: by 10.66.6.1 with SMTP id w1mr3434973paw.6.1393671384201; Sat, 01 Mar 2014 02:56:24 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.43.246 with SMTP id e109ls1459469qga.89.gmail; Sat, 01 Mar 2014 02:56:24 -0800 (PST) X-Received: by 10.52.104.68 with SMTP id gc4mr16825842vdb.2.1393671384039; Sat, 01 Mar 2014 02:56:24 -0800 (PST) Received: from mail-vc0-f173.google.com (mail-vc0-f173.google.com [209.85.220.173]) by mx.google.com with ESMTPS id wz4si1640406vdc.72.2014.03.01.02.56.24 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 01 Mar 2014 02:56:24 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.173 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.173; Received: by mail-vc0-f173.google.com with SMTP id ld13so1816317vcb.18 for ; Sat, 01 Mar 2014 02:56:23 -0800 (PST) X-Received: by 10.52.29.113 with SMTP id j17mr17008304vdh.22.1393671383919; Sat, 01 Mar 2014 02:56:23 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.130.193 with SMTP id u1csp114206vcs; Sat, 1 Mar 2014 02:56:23 -0800 (PST) X-Received: by 10.112.204.104 with SMTP id kx8mr14453864lbc.12.1393671382484; Sat, 01 Mar 2014 02:56:22 -0800 (PST) Received: from mail-la0-f50.google.com (mail-la0-f50.google.com [209.85.215.50]) by mx.google.com with ESMTPS id jn5si7882230lbc.126.2014.03.01.02.56.21 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 01 Mar 2014 02:56:22 -0800 (PST) Received-SPF: neutral (google.com: 209.85.215.50 is neither permitted nor denied by best guess record for domain of ulf.hansson@linaro.org) client-ip=209.85.215.50; Received: by mail-la0-f50.google.com with SMTP id y1so3372554lam.23 for ; Sat, 01 Mar 2014 02:56:21 -0800 (PST) X-Received: by 10.152.21.4 with SMTP id r4mr1126183lae.51.1393671381777; Sat, 01 Mar 2014 02:56:21 -0800 (PST) Received: from linaro-ulf.lan (90-231-160-185-no158.tbcn.telia.com. [90.231.160.185]) by mx.google.com with ESMTPSA id qf1sm4532484lbc.8.2014.03.01.02.56.18 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 01 Mar 2014 02:56:21 -0800 (PST) From: Ulf Hansson To: "Rafael J. Wysocki" , Len Brown , Pavel Machek , linux-pm@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Kevin Hilman , Alan Stern , Greg Kroah-Hartman , Mark Brown , Russell King , Linus Walleij , Wolfram Sang , Alessandro Rubini , Josh Cartwright , Ulf Hansson Subject: [PATCH V3 2/8] PM / Sleep / Runtime: Add pm_runtime_suspend|resume_force functions Date: Sat, 1 Mar 2014 11:56:05 +0100 Message-Id: <1393671371-2398-3-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1393671371-2398-1-git-send-email-ulf.hansson@linaro.org> References: <1393671371-2398-1-git-send-email-ulf.hansson@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ulf.hansson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.173 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , This patch provides two new runtime PM helper functions which intend to be used from system suspend/resume callbacks, to make sure devices are put into low power state during system suspend and brought back to full power at system resume. The prerequisite is to have all levels of a device's runtime PM callbacks to be defined through the SET_PM_RUNTIME_PM_OPS macro, which means these are available for CONFIG_PM. By using the new runtime PM helper functions especially the two scenarios below will be addressed. 1) The PM core prevents .runtime_suspend callbacks from being invoked during system suspend. That means even for a runtime PM centric subsystem and driver, the device needs to be put into low power state from a system suspend callback. Otherwise it may very well be left in full power state (runtime resumed) while the system is suspended. By using the new helper functions, we make sure to walk the hierarchy of a device's power domain, subsystem and driver. 2) Subsystems and drivers need to cope with all the combinations of CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME. The two new helper functions smothly addresses this. Cc: Kevin Hilman Cc: Alan Stern Cc: Greg Kroah-Hartman Cc: Mark Brown Cc: Russell King Cc: Linus Walleij Cc: Wolfram Sang Cc: Alessandro Rubini Signed-off-by: Ulf Hansson Acked-by: Kevin Hilman --- Changes in v3: Use rpm_get_suspend|resume_cb() instead of the macro. Changes in v2: Adopt to version 2 of the RPM_GET_CALLBACK macro. --- drivers/base/power/Makefile | 3 +- drivers/base/power/runtime.c | 84 ++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_runtime.h | 4 ++ 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 2e58ebb..1cb8544 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,6 +1,5 @@ -obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o +obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o runtime.o obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o -obj-$(CONFIG_PM_RUNTIME) += runtime.o obj-$(CONFIG_PM_TRACE_RTC) += trace.o obj-$(CONFIG_PM_OPP) += opp.o obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index ac495b1..4776cf5 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -44,6 +44,7 @@ static int (*rpm_get_resume_cb(struct device *dev))(struct device *) return RPM_GET_CALLBACK(dev, runtime_resume); } +#ifdef CONFIG_PM_RUNTIME static int (*rpm_get_idle_cb(struct device *dev))(struct device *) { return RPM_GET_CALLBACK(dev, runtime_idle); @@ -1401,3 +1402,86 @@ void pm_runtime_remove(struct device *dev) if (dev->power.irq_safe && dev->parent) pm_runtime_put(dev->parent); } +#endif + +/** + * pm_runtime_force_suspend - Force a device into suspend state if needed. + * @dev: Device to suspend. + * + * Disable runtime PM so we safely can check the device's runtime PM status and + * if it is active, invoke it's .runtime_suspend callback to bring it into + * suspend state. Keep runtime PM disabled to preserve the state unless we + * encounter errors. + * + * Typically this function may be invoked from a system suspend callback to make + * sure the device is put into low power state. + */ +int pm_runtime_force_suspend(struct device *dev) +{ + int (*callback)(struct device *); + int ret = 0; + + pm_runtime_disable(dev); + + /* + * Note that pm_runtime_status_suspended() returns false while + * !CONFIG_PM_RUNTIME, which means the device will be put into low + * power state. + */ + if (pm_runtime_status_suspended(dev)) + return 0; + + callback = rpm_get_suspend_cb(dev); + + if (!callback) { + ret = -ENOSYS; + goto err; + } + + ret = callback(dev); + if (ret) + goto err; + + pm_runtime_set_suspended(dev); + return 0; +err: + pm_runtime_enable(dev); + return ret; +} +EXPORT_SYMBOL_GPL(pm_runtime_force_suspend); + +/** + * pm_runtime_force_resume - Force a device into resume state. + * @dev: Device to resume. + * + * Prior invoking this function we expect the user to have brought the device + * into low power state by a call to pm_runtime_force_suspend(). Here we reverse + * those actions and brings the device into full power. We update the runtime PM + * status and re-enables runtime PM. + * + * Typically this function may be invoked from a system resume callback to make + * sure the device is put into full power state. + */ +int pm_runtime_force_resume(struct device *dev) +{ + int (*callback)(struct device *); + int ret = 0; + + callback = rpm_get_resume_cb(dev); + + if (!callback) { + ret = -ENOSYS; + goto out; + } + + ret = callback(dev); + if (ret) + goto out; + + pm_runtime_set_active(dev); + pm_runtime_mark_last_busy(dev); +out: + pm_runtime_enable(dev); + return ret; +} +EXPORT_SYMBOL_GPL(pm_runtime_force_resume); diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 16c9a62..2a5897a 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -26,9 +26,13 @@ #ifdef CONFIG_PM extern int pm_generic_runtime_suspend(struct device *dev); extern int pm_generic_runtime_resume(struct device *dev); +extern int pm_runtime_force_suspend(struct device *dev); +extern int pm_runtime_force_resume(struct device *dev); #else static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } +static inline int pm_runtime_force_suspend(struct device *dev) { return 0; } +static inline int pm_runtime_force_resume(struct device *dev) { return 0; } #endif #ifdef CONFIG_PM_RUNTIME