From: Mark Brown <broonie@linaro.org>
Date: Mon, 9 Mar 2015 12:26:45 +0000 (+0000)
Subject: cpufreq: Revert "cpufreq: suspend governors on system suspend/hibernate"
X-Git-Tag: firefly_0821_release~3680^2~19^2~2^2
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=db295c89378fa7c9cfffd1ed08b9c77d2d1dd9ea;p=firefly-linux-kernel-4.4.55.git

cpufreq: Revert "cpufreq: suspend governors on system suspend/hibernate"

This reverts commit adb665056afe23db0687c1d1a208806c108add08.

The commit has too many hidden dependencies to be sensibly backported.

Signed-off-by: Mark Brown <broonie@linaro.org>
---

diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 220ec3a3ca75..5a9b6569dd74 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -28,8 +28,6 @@
 #include <linux/sched.h>
 #include <linux/async.h>
 #include <linux/suspend.h>
-#include <trace/events/power.h>
-#include <linux/cpufreq.h>
 #include <linux/cpuidle.h>
 #include "../base.h"
 #include "power.h"
@@ -715,8 +713,6 @@ void dpm_resume(pm_message_t state)
 	mutex_unlock(&dpm_list_mtx);
 	async_synchronize_full();
 	dpm_show_time(starttime, state, NULL);
-
-	cpufreq_resume();
 }
 
 /**
@@ -1181,8 +1177,6 @@ int dpm_suspend(pm_message_t state)
 
 	might_sleep();
 
-	cpufreq_suspend();
-
 	mutex_lock(&dpm_list_mtx);
 	pm_transition = state;
 	async_error = 0;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d444bfe83f13..2d53f47d1747 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -31,8 +31,6 @@
 #include <linux/completion.h>
 #include <linux/mutex.h>
 #include <linux/syscore_ops.h>
-#include <linux/suspend.h>
-#include <linux/tick.h>
 
 #include <trace/events/power.h>
 
@@ -49,14 +47,6 @@ static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
 #endif
 static DEFINE_RWLOCK(cpufreq_driver_lock);
 
-/* Flag to suspend/resume CPUFreq governors */
-static bool cpufreq_suspended;
-
-static inline bool has_target(void)
-{
-	return cpufreq_driver->target;
-}
-
 /*
  * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
  * all cpufreq/hotplug/workqueue/etc related lock issues.
@@ -1283,90 +1273,83 @@ static struct subsys_interface cpufreq_interface = {
 
 
 /**
- * cpufreq_suspend() - Suspend CPUFreq governors
+ * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
  *
- * 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.
+ * This function is only executed for the boot processor.  The other CPUs
+ * have been put offline by means of CPU hotplug.
  */
-void cpufreq_suspend(void)
+static int cpufreq_bp_suspend(void)
 {
-	struct cpufreq_policy *policy;
-	int cpu;
-
-	if (!cpufreq_driver)
-		return;
-
-	if (!has_target())
-		return;
+	int ret = 0;
 
-	pr_debug("%s: Suspending Governors\n", __func__);
+	int cpu = smp_processor_id();
+	struct cpufreq_policy *cpu_policy;
 
-	for_each_possible_cpu(cpu) {
-		if (!cpu_online(cpu))
-			continue;
+	pr_debug("suspending cpu %u\n", cpu);
 
-		policy = cpufreq_cpu_get(cpu);
+	/* If there's no policy for the boot CPU, we have nothing to do. */
+	cpu_policy = cpufreq_cpu_get(cpu);
+	if (!cpu_policy)
+		return 0;
 
-		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);
+	if (cpufreq_driver->suspend) {
+		ret = cpufreq_driver->suspend(cpu_policy);
+		if (ret)
+			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
+					"step on CPU %u\n", cpu_policy->cpu);
 	}
 
-	cpufreq_suspended = true;
+	cpufreq_cpu_put(cpu_policy);
+	return ret;
 }
 
 /**
- * cpufreq_resume() - Resume CPUFreq governors
+ * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
  *
- * Called during system wide Suspend/Hibernate cycle for resuming governors that
- * are suspended with cpufreq_suspend().
+ *	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.
  */
-void cpufreq_resume(void)
+static void cpufreq_bp_resume(void)
 {
-	struct cpufreq_policy *policy;
-	int cpu;
+	int ret = 0;
 
-	if (!cpufreq_driver)
-		return;
+	int cpu = smp_processor_id();
+	struct cpufreq_policy *cpu_policy;
+
+	pr_debug("resuming cpu %u\n", cpu);
 
-	if (!has_target())
+	/* If there's no policy for the boot CPU, we have nothing to do. */
+	cpu_policy = cpufreq_cpu_get(cpu);
+	if (!cpu_policy)
 		return;
 
-	pr_debug("%s: Resuming Governors\n", __func__);
+	if (cpufreq_driver->resume) {
+		ret = cpufreq_driver->resume(cpu_policy);
+		if (ret) {
+			printk(KERN_ERR "cpufreq: resume failed in ->resume "
+					"step on CPU %u\n", cpu_policy->cpu);
+			goto fail;
+		}
+	}
 
-	cpufreq_suspended = false;
+	schedule_work(&cpu_policy->update);
 
-	for_each_possible_cpu(cpu) {
-		if (!cpu_online(cpu))
-			continue;
-
-		policy = cpufreq_cpu_get(cpu);
-
-		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);
-		else if (cpufreq_driver->resume
-		    && cpufreq_driver->resume(policy))
-			pr_err("%s: Failed to resume driver: %p\n", __func__,
-				policy);
-
-		/*
-		 * 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 (cpu == 0)
-			schedule_work(&policy->update);
-	}
+fail:
+	cpufreq_cpu_put(cpu_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
  *
@@ -1559,10 +1542,6 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
 	struct cpufreq_governor *gov = NULL;
 #endif
 
-	/* Don't start any governor operations if we are entering suspend */
-	if (cpufreq_suspended)
-		return 0;
-
 	if (policy->governor->max_transition_latency &&
 	    policy->cpuinfo.transition_latency >
 	    policy->governor->max_transition_latency) {
@@ -1995,6 +1974,7 @@ static int __init cpufreq_core_init(void)
 
 	cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj);
 	BUG_ON(!cpufreq_global_kobject);
+	register_syscore_ops(&cpufreq_syscore_ops);
 
 	return 0;
 }
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 00b0e0a9fca3..037d36ae63e5 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -306,18 +306,6 @@ struct freq_attr {
 static struct freq_attr _name =			\
 __ATTR(_name, 0444, show_##_name, NULL)
 
-#ifdef CONFIG_CPU_FREQ
-void cpufreq_suspend(void);
-void cpufreq_resume(void);
-#else
-static inline void cpufreq_suspend(void) {}
-static inline void cpufreq_resume(void) {}
-#endif
-
-/*********************************************************************
- *                     CPUFREQ NOTIFIER INTERFACE                    *
- *********************************************************************/
-
 #define cpufreq_freq_attr_ro_perm(_name, _perm)	\
 static struct freq_attr _name =			\
 __ATTR(_name, _perm, show_##_name, NULL)