aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/power/main.c3
-rw-r--r--drivers/cpufreq/cpufreq.c43
-rw-r--r--include/linux/cpufreq.h8
3 files changed, 54 insertions, 0 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 9f098a82cf04..10c3510d72a9 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -29,6 +29,7 @@
29#include <linux/async.h> 29#include <linux/async.h>
30#include <linux/suspend.h> 30#include <linux/suspend.h>
31#include <trace/events/power.h> 31#include <trace/events/power.h>
32#include <linux/cpufreq.h>
32#include <linux/cpuidle.h> 33#include <linux/cpuidle.h>
33#include "../base.h" 34#include "../base.h"
34#include "power.h" 35#include "power.h"
@@ -473,6 +474,7 @@ static void dpm_resume_noirq(pm_message_t state)
473 dpm_show_time(starttime, state, "noirq"); 474 dpm_show_time(starttime, state, "noirq");
474 resume_device_irqs(); 475 resume_device_irqs();
475 cpuidle_resume(); 476 cpuidle_resume();
477 cpufreq_resume();
476} 478}
477 479
478/** 480/**
@@ -885,6 +887,7 @@ static int dpm_suspend_noirq(pm_message_t state)
885 ktime_t starttime = ktime_get(); 887 ktime_t starttime = ktime_get();
886 int error = 0; 888 int error = 0;
887 889
890 cpufreq_suspend();
888 cpuidle_pause(); 891 cpuidle_pause();
889 suspend_device_irqs(); 892 suspend_device_irqs();
890 mutex_lock(&dpm_list_mtx); 893 mutex_lock(&dpm_list_mtx);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 02d534da22dd..606224a8abc2 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -26,6 +26,7 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/mutex.h> 27#include <linux/mutex.h>
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/suspend.h>
29#include <linux/syscore_ops.h> 30#include <linux/syscore_ops.h>
30#include <linux/tick.h> 31#include <linux/tick.h>
31#include <trace/events/power.h> 32#include <trace/events/power.h>
@@ -47,6 +48,9 @@ static LIST_HEAD(cpufreq_policy_list);
47static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); 48static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
48#endif 49#endif
49 50
51/* Flag to suspend/resume CPUFreq governors */
52static bool cpufreq_suspended;
53
50static inline bool has_target(void) 54static inline bool has_target(void)
51{ 55{
52 return cpufreq_driver->target_index || cpufreq_driver->target; 56 return cpufreq_driver->target_index || cpufreq_driver->target;
@@ -1462,6 +1466,41 @@ static struct subsys_interface cpufreq_interface = {
1462 .remove_dev = cpufreq_remove_dev, 1466 .remove_dev = cpufreq_remove_dev,
1463}; 1467};
1464 1468
1469void cpufreq_suspend(void)
1470{
1471 struct cpufreq_policy *policy;
1472
1473 if (!has_target())
1474 return;
1475
1476 pr_debug("%s: Suspending Governors\n", __func__);
1477
1478 list_for_each_entry(policy, &cpufreq_policy_list, policy_list)
1479 if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
1480 pr_err("%s: Failed to stop governor for policy: %p\n",
1481 __func__, policy);
1482
1483 cpufreq_suspended = true;
1484}
1485
1486void cpufreq_resume(void)
1487{
1488 struct cpufreq_policy *policy;
1489
1490 if (!has_target())
1491 return;
1492
1493 pr_debug("%s: Resuming Governors\n", __func__);
1494
1495 cpufreq_suspended = false;
1496
1497 list_for_each_entry(policy, &cpufreq_policy_list, policy_list)
1498 if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
1499 || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
1500 pr_err("%s: Failed to start governor for policy: %p\n",
1501 __func__, policy);
1502}
1503
1465/** 1504/**
1466 * cpufreq_bp_suspend - Prepare the boot CPU for system suspend. 1505 * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
1467 * 1506 *
@@ -1764,6 +1803,10 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
1764 struct cpufreq_governor *gov = NULL; 1803 struct cpufreq_governor *gov = NULL;
1765#endif 1804#endif
1766 1805
1806 /* Don't start any governor operations if we are entering suspend */
1807 if (cpufreq_suspended)
1808 return 0;
1809
1767 if (policy->governor->max_transition_latency && 1810 if (policy->governor->max_transition_latency &&
1768 policy->cpuinfo.transition_latency > 1811 policy->cpuinfo.transition_latency >
1769 policy->governor->max_transition_latency) { 1812 policy->governor->max_transition_latency) {
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 5bd6ab9b0c27..91716658e9a1 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -272,6 +272,14 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
272 policy->cpuinfo.max_freq); 272 policy->cpuinfo.max_freq);
273} 273}
274 274
275#ifdef CONFIG_CPU_FREQ
276void cpufreq_suspend(void);
277void cpufreq_resume(void);
278#else
279static inline void cpufreq_suspend(void) {}
280static inline void cpufreq_resume(void) {}
281#endif
282
275/********************************************************************* 283/*********************************************************************
276 * CPUFREQ NOTIFIER INTERFACE * 284 * CPUFREQ NOTIFIER INTERFACE *
277 *********************************************************************/ 285 *********************************************************************/