|
@@ -26,6 +26,7 @@
|
|
|
#include <linux/module.h>
|
|
|
#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>
|
|
@@ -47,6 +48,9 @@ static LIST_HEAD(cpufreq_policy_list);
|
|
|
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
|
|
|
#endif
|
|
|
|
|
|
+/* Flag to suspend/resume CPUFreq governors */
|
|
|
+static bool cpufreq_suspended;
|
|
|
+
|
|
|
static inline bool has_target(void)
|
|
|
{
|
|
|
return cpufreq_driver->target_index || cpufreq_driver->target;
|
|
@@ -1462,6 +1466,41 @@ static struct subsys_interface cpufreq_interface = {
|
|
|
.remove_dev = cpufreq_remove_dev,
|
|
|
};
|
|
|
|
|
|
+void cpufreq_suspend(void)
|
|
|
+{
|
|
|
+ struct cpufreq_policy *policy;
|
|
|
+
|
|
|
+ if (!has_target())
|
|
|
+ return;
|
|
|
+
|
|
|
+ pr_debug("%s: Suspending Governors\n", __func__);
|
|
|
+
|
|
|
+ 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);
|
|
|
+
|
|
|
+ cpufreq_suspended = true;
|
|
|
+}
|
|
|
+
|
|
|
+void cpufreq_resume(void)
|
|
|
+{
|
|
|
+ struct cpufreq_policy *policy;
|
|
|
+
|
|
|
+ if (!has_target())
|
|
|
+ return;
|
|
|
+
|
|
|
+ pr_debug("%s: Resuming Governors\n", __func__);
|
|
|
+
|
|
|
+ cpufreq_suspended = false;
|
|
|
+
|
|
|
+ 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.
|
|
|
*
|
|
@@ -1764,6 +1803,10 @@ 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) {
|
|
@@ -2076,9 +2119,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
|
|
|
dev = get_cpu_device(cpu);
|
|
|
if (dev) {
|
|
|
|
|
|
- if (action & CPU_TASKS_FROZEN)
|
|
|
- frozen = true;
|
|
|
-
|
|
|
switch (action & ~CPU_TASKS_FROZEN) {
|
|
|
case CPU_ONLINE:
|
|
|
__cpufreq_add_dev(dev, NULL, frozen);
|