From patchwork Mon Nov 30 15:21:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 57468 Delivered-To: patches@linaro.org Received: by 10.112.155.196 with SMTP id vy4csp1543306lbb; Mon, 30 Nov 2015 07:21:47 -0800 (PST) X-Received: by 10.25.19.100 with SMTP id j97mr25382969lfi.114.1448896907568; Mon, 30 Nov 2015 07:21:47 -0800 (PST) Return-Path: Received: from mail-lf0-x236.google.com (mail-lf0-x236.google.com. [2a00:1450:4010:c07::236]) by mx.google.com with ESMTPS id e20si29145749lfi.75.2015.11.30.07.21.47 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 30 Nov 2015 07:21:47 -0800 (PST) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:4010:c07::236 as permitted sender) client-ip=2a00:1450:4010:c07::236; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:4010:c07::236 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dkim=pass header.i=@linaro-org.20150623.gappssmtp.com Received: by lfs39 with SMTP id 39so197306895lfs.3 for ; Mon, 30 Nov 2015 07:21:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro-org.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=ISge5ldRDAtxXFDA/rDAm1zmsqqDdA08HWW2SFWxV3w=; b=iVbBnbYW9m0pTwiphQ6vOfJ2aiaa5F31NCgLmTPPYup2Duk9Q1Tl4FWHVSNN3IQ5oO hnQBdqk/RLARn8AxjoSUDv6/Q1BWWANGxZSMxcGP6QHQLvK9B+S8bUx3eGlKGoHTNP8G PHj6JFAcOYOxbcKLGrFlEvg7c9MDK7gT7iPUE8HnPaAFRd/OaghH5Y8fHQ50BCq60e/Q PVsIt6NNf61YI8nrP6gQ75SmhDgNbRbJG+OM2ojDxnQWtmNiNjH4GSwE3+6SON/2t3uV qTe2QYJk/Op/MMvMGKQ2cvBICed0dNEIKPEW+d5+8hmIVypQfrDREDvK8t5heWCJ2ZYw hfPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=ISge5ldRDAtxXFDA/rDAm1zmsqqDdA08HWW2SFWxV3w=; b=Kd5cFvZoaa6RKy9j2n4wngjXRrRa7vhc4BFCltrl9qRhS9k5z5a/o2jQfqxWDIFEdO UHmG1W8L2uPePfKL2PANtMy+0SGQ1WCP/N74Jo5wDBtrtduscWmdvEQq0613+MndfA9T bcCOJKPJ1X+G5HIR7vMP73L0uC0MFYQjGzZDTAMfyGhpsmIuxc2U6+2+x5PlicX1AQ/d rfHj8reR/T72QTWIfGx7ekp4hnRj2zushk2cyr7zw8L/izi43Gz/AsX4hXiICka0/g+s OCMnNNIdxBoHcK/h829VFQsxAV/ltb1XqyEHvEsG7Tdaa3Vi+BnKqx5W+NInPOt/W7QH U0Fg== X-Gm-Message-State: ALoCoQkjdbAF2RFK00i1KW8V4ccTKAQ4i9rzhOD8ip7n2Vigk4LsXrnEpBtRfMlhqeOUiWmDDj6b X-Received: by 10.112.63.130 with SMTP id g2mr21241573lbs.28.1448896905466; Mon, 30 Nov 2015 07:21:45 -0800 (PST) Return-Path: Received: from uffe-Latitude-E6430s.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id l67sm7446543lfl.26.2015.11.30.07.21.44 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 30 Nov 2015 07:21:44 -0800 (PST) From: Ulf Hansson To: "Rafael J. Wysocki" , Kevin Hilman , Ulf Hansson , linux-pm@vger.kernel.org Cc: Len Brown , Pavel Machek , Geert Uytterhoeven , Lina Iyer , Cao Minh Hiep , Harunaga Subject: [PATCH v2] PM / Domains: Allow runtime PM callbacks to be re-used during system PM Date: Mon, 30 Nov 2015 16:21:38 +0100 Message-Id: <1448896898-27711-1-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.9.1 A runtime PM centric subsystem/driver may typically use the runtime PM helpers, pm_runtime_force_suspend|resume() in the system PM path. This means the genpd's runtime PM callbacks might be invoked even when runtime PM has been disabled for the device. To properly cope with these and similar scenarios when these helper functions are used, change genpd to skip validating and measuring the device PM QOS latency. This is needed because otherwise genpd may prevent the device to be put into low power state. If this occurs during system PM, it causes the sequence to be aborted as a device's system PM callback returns -EBUSY. Fixes: ba2bbfbf6307 ("PM / Domains: Remove intermediate states from the power off sequence") Reported-by: Cao Minh Hiep Reported-by: Harunaga Signed-off-by: Ulf Hansson --- Changes in v2: - Change variable name and update code to not be limited to only system PM, according to suggestion by Kevin. - Updated comments in code. - Updated change-log. Notes in v2: - Version 1, got tested successfully by Cao Minh Hiep and Harunaga, although because of the changes in V2, another round of tests are needed to add their tested by tags. It was reported [1] to point out a certain commitd causing the regression, but further analyze actually tells that the problem been there longer. So, I decided to point the fixes tag to a commit from where it actually becomes quite simple to address the problem. Earlier than that, is just not worth the effort. [1] https://lkml.org/lkml/2015/11/16/748 --- drivers/base/power/domain.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) -- 1.9.1 diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index e03b1ad..88a759b 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -390,6 +390,7 @@ static int pm_genpd_runtime_suspend(struct device *dev) struct generic_pm_domain *genpd; bool (*stop_ok)(struct device *__dev); struct gpd_timing_data *td = &dev_gpd_data(dev)->td; + bool runtime_pm = pm_runtime_enabled(dev); ktime_t time_start; s64 elapsed_ns; int ret; @@ -400,12 +401,19 @@ static int pm_genpd_runtime_suspend(struct device *dev) if (IS_ERR(genpd)) return -EINVAL; + /* + * A runtime PM centric subsystem/driver may re-use the runtime PM + * callbacks for other purposes than runtime PM. In those scenarios + * runtime PM is disabled. Under these circumstances, we shall skip + * validating/measuring the PM QoS latency. + */ stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL; - if (stop_ok && !stop_ok(dev)) + if (runtime_pm && stop_ok && !stop_ok(dev)) return -EBUSY; /* Measure suspend latency. */ - time_start = ktime_get(); + if (runtime_pm) + time_start = ktime_get(); ret = genpd_save_dev(genpd, dev); if (ret) @@ -418,13 +426,15 @@ static int pm_genpd_runtime_suspend(struct device *dev) } /* Update suspend latency value if the measured time exceeds it. */ - elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); - if (elapsed_ns > td->suspend_latency_ns) { - td->suspend_latency_ns = elapsed_ns; - dev_dbg(dev, "suspend latency exceeded, %lld ns\n", - elapsed_ns); - genpd->max_off_time_changed = true; - td->constraint_changed = true; + if (runtime_pm) { + elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); + if (elapsed_ns > td->suspend_latency_ns) { + td->suspend_latency_ns = elapsed_ns; + dev_dbg(dev, "suspend latency exceeded, %lld ns\n", + elapsed_ns); + genpd->max_off_time_changed = true; + td->constraint_changed = true; + } } /* @@ -453,6 +463,7 @@ static int pm_genpd_runtime_resume(struct device *dev) { struct generic_pm_domain *genpd; struct gpd_timing_data *td = &dev_gpd_data(dev)->td; + bool runtime_pm = pm_runtime_enabled(dev); ktime_t time_start; s64 elapsed_ns; int ret; @@ -479,14 +490,14 @@ static int pm_genpd_runtime_resume(struct device *dev) out: /* Measure resume latency. */ - if (timed) + if (timed && runtime_pm) time_start = ktime_get(); genpd_start_dev(genpd, dev); genpd_restore_dev(genpd, dev); /* Update resume latency value if the measured time exceeds it. */ - if (timed) { + if (timed && runtime_pm) { elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); if (elapsed_ns > td->resume_latency_ns) { td->resume_latency_ns = elapsed_ns;