All of lore.kernel.org
 help / color / mirror / Atom feed
From: Viresh Kumar <viresh.kumar@linaro.org>
To: rjw@rjwysocki.net
Cc: linaro-kernel@lists.linaro.org, cpufreq@vger.kernel.org,
	linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org,
	nm@ti.com, swarren@wwwdotorg.org, kgene.kim@samsung.com,
	jinchoi@broadcom.com, tianyu.lan@intel.com,
	sebastian.capella@linaro.org, jhbird.choi@samsung.com,
	Viresh Kumar <viresh.kumar@linaro.org>
Subject: [PATCH V5 3/7] cpufreq: call driver's suspend/resume for each policy
Date: Thu, 13 Feb 2014 12:20:18 +0530	[thread overview]
Message-ID: <de4feac78b9a20fa3f2b7472c690336b2fc567ce.1392273723.git.viresh.kumar@linaro.org> (raw)
In-Reply-To: <cover.1392273722.git.viresh.kumar@linaro.org>
In-Reply-To: <cover.1392273722.git.viresh.kumar@linaro.org>

Earlier cpufreq suspend/resume callbacks into drivers were getting called only
for the boot CPU, as by the time callbacks were called non-boot CPUs were
already removed. Because we might still need driver specific actions on
suspend/resume, its better to use earlier infrastructure from the early
suspend/late resume calls.

In effect, we call suspend/resume for each policy. The resume part also takes
care of synchronising frequency for boot CPU, which might turn out be different
than what cpufreq core believes.

Hence, the earlier syscore infrastructure is getting removed now.

Tested-by: Lan Tianyu <tianyu.lan@intel.com>
Tested-by: Nishanth Menon <nm@ti.com>
Tested-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq.c | 112 +++++++++++++---------------------------------
 1 file changed, 32 insertions(+), 80 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index cb23858..87a4b96 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -27,7 +27,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
-#include <linux/syscore_ops.h>
 #include <linux/tick.h>
 #include <trace/events/power.h>
 
@@ -1580,6 +1579,14 @@ static struct subsys_interface cpufreq_interface = {
 	.remove_dev	= cpufreq_remove_dev,
 };
 
+/**
+ * cpufreq_suspend() - Suspend CPUFreq governors
+ *
+ * Called during system wide Suspend/Hibernate cycles for suspending governors
+ * as some platforms can't change frequency after this point in suspend cycle.
+ * Because some of the devices (like: i2c, regulators, etc) they use for
+ * changing frequency are suspended quickly after this point.
+ */
 void cpufreq_suspend(void)
 {
 	struct cpufreq_policy *policy;
@@ -1589,14 +1596,25 @@ void cpufreq_suspend(void)
 
 	pr_debug("%s: Suspending Governors\n", __func__);
 
-	list_for_each_entry(policy, &cpufreq_policy_list, policy_list)
+	list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
 		if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
 			pr_err("%s: Failed to stop governor for policy: %p\n",
 				__func__, policy);
+		else if (cpufreq_driver->suspend
+		    && cpufreq_driver->suspend(policy))
+			pr_err("%s: Failed to suspend driver: %p\n", __func__,
+				policy);
+	}
 
 	cpufreq_suspended = true;
 }
 
+/**
+ * cpufreq_resume() - Resume CPUFreq governors
+ *
+ * Called during system wide Suspend/Hibernate cycle for resuming governors that
+ * are suspended with cpufreq_suspend().
+ */
 void cpufreq_resume(void)
 {
 	struct cpufreq_policy *policy;
@@ -1608,91 +1626,26 @@ void cpufreq_resume(void)
 
 	cpufreq_suspended = false;
 
-	list_for_each_entry(policy, &cpufreq_policy_list, policy_list)
+	list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
 		if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
 		    || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
 			pr_err("%s: Failed to start governor for policy: %p\n",
 				__func__, policy);
-}
-
-/**
- * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
- *
- * This function is only executed for the boot processor.  The other CPUs
- * have been put offline by means of CPU hotplug.
- */
-static int cpufreq_bp_suspend(void)
-{
-	int ret = 0;
-
-	int cpu = smp_processor_id();
-	struct cpufreq_policy *policy;
-
-	pr_debug("suspending cpu %u\n", cpu);
-
-	/* If there's no policy for the boot CPU, we have nothing to do. */
-	policy = cpufreq_cpu_get(cpu);
-	if (!policy)
-		return 0;
-
-	if (cpufreq_driver->suspend) {
-		ret = cpufreq_driver->suspend(policy);
-		if (ret)
-			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
-					"step on CPU %u\n", policy->cpu);
-	}
-
-	cpufreq_cpu_put(policy);
-	return ret;
-}
-
-/**
- * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
- *
- *	1.) resume CPUfreq hardware support (cpufreq_driver->resume())
- *	2.) schedule call cpufreq_update_policy() ASAP as interrupts are
- *	    restored. It will verify that the current freq is in sync with
- *	    what we believe it to be. This is a bit later than when it
- *	    should be, but nonethteless it's better than calling
- *	    cpufreq_driver->get() here which might re-enable interrupts...
- *
- * This function is only executed for the boot CPU.  The other CPUs have not
- * been turned on yet.
- */
-static void cpufreq_bp_resume(void)
-{
-	int ret = 0;
+		else if (cpufreq_driver->resume
+		    && cpufreq_driver->resume(policy))
+			pr_err("%s: Failed to resume driver: %p\n", __func__,
+				policy);
 
-	int cpu = smp_processor_id();
-	struct cpufreq_policy *policy;
-
-	pr_debug("resuming cpu %u\n", cpu);
-
-	/* If there's no policy for the boot CPU, we have nothing to do. */
-	policy = cpufreq_cpu_get(cpu);
-	if (!policy)
-		return;
-
-	if (cpufreq_driver->resume) {
-		ret = cpufreq_driver->resume(policy);
-		if (ret) {
-			printk(KERN_ERR "cpufreq: resume failed in ->resume "
-					"step on CPU %u\n", policy->cpu);
-			goto fail;
-		}
+		/*
+		 * schedule call cpufreq_update_policy() for boot CPU, i.e. last
+		 * policy in list. It will verify that the current freq is in
+		 * sync with what we believe it to be.
+		 */
+		if (list_is_last(&policy->policy_list, &cpufreq_policy_list))
+			schedule_work(&policy->update);
 	}
-
-	schedule_work(&policy->update);
-
-fail:
-	cpufreq_cpu_put(policy);
 }
 
-static struct syscore_ops cpufreq_syscore_ops = {
-	.suspend	= cpufreq_bp_suspend,
-	.resume		= cpufreq_bp_resume,
-};
-
 /**
  *	cpufreq_get_current_driver - return current driver's name
  *
@@ -2458,7 +2411,6 @@ static int __init cpufreq_core_init(void)
 
 	cpufreq_global_kobject = kobject_create();
 	BUG_ON(!cpufreq_global_kobject);
-	register_syscore_ops(&cpufreq_syscore_ops);
 
 	return 0;
 }
-- 
1.7.12.rc2.18.g61b472e


  parent reply	other threads:[~2014-02-13  6:51 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-13  6:50 [PATCH V5 0/7] cpufreq: suspend early/resume late: dpm_{suspend|resume}() Viresh Kumar
2014-02-13  6:50 ` [PATCH V5 1/7] cpufreq: suspend governors on system suspend/hibernate Viresh Kumar
2014-02-13  6:50 ` [PATCH V5 2/7] cpufreq: suspend governors from dpm_{suspend|resume}() Viresh Kumar
2014-02-13  6:50 ` Viresh Kumar [this message]
2014-02-13  6:50 ` [PATCH V5 4/7] cpufreq: Implement cpufreq_generic_suspend() Viresh Kumar
2014-02-13  6:50 ` [PATCH V5 5/7] cpufreq: exynos: Use cpufreq_generic_suspend() Viresh Kumar
2014-02-13  6:50 ` [PATCH V5 6/7] cpufreq: s5pv210: " Viresh Kumar
2014-02-13  6:50 ` [PATCH V5 7/7] cpufreq: Tegra: " Viresh Kumar
2014-02-14 19:42 ` [PATCH V5 0/7] cpufreq: suspend early/resume late: dpm_{suspend|resume}() Stephen Warren
2014-02-14 20:22   ` Stephen Warren
2014-02-17  6:02     ` Viresh Kumar
2014-02-18 20:31       ` Stephen Warren
2014-02-14 22:23   ` Rafael J. Wysocki
2014-02-15  0:03     ` Stephen Warren
2014-02-17  9:20       ` Viresh Kumar
2014-02-18 20:18         ` Stephen Warren
2014-02-19  4:15           ` Viresh Kumar
2014-02-19 17:26             ` Stephen Warren
2014-02-20  1:49               ` Linaro
2014-02-20  1:50                 ` Linaro
2014-02-20 17:40                   ` Stephen Warren
2014-02-24  6:43                     ` Viresh Kumar
2014-02-24 17:17                       ` Stephen Warren
2014-02-17  6:08   ` Viresh Kumar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=de4feac78b9a20fa3f2b7472c690336b2fc567ce.1392273723.git.viresh.kumar@linaro.org \
    --to=viresh.kumar@linaro.org \
    --cc=cpufreq@vger.kernel.org \
    --cc=jhbird.choi@samsung.com \
    --cc=jinchoi@broadcom.com \
    --cc=kgene.kim@samsung.com \
    --cc=linaro-kernel@lists.linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=nm@ti.com \
    --cc=rjw@rjwysocki.net \
    --cc=sebastian.capella@linaro.org \
    --cc=swarren@wwwdotorg.org \
    --cc=tianyu.lan@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.