aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-11-26 22:39:42 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-11-28 08:47:31 -0500
commit5a87182aa21d6d5d306840feab9321818dd3e2a3 (patch)
tree86ead8ebc52067f57ec2f78271fa5dbe9c58e066 /drivers/cpufreq/cpufreq.c
parent3d3c6f54bccf0a621682d17e25cf22895a0c6e5a (diff)
cpufreq: suspend governors on system suspend/hibernate
This patch adds cpufreq suspend/resume calls to dpm_{suspend|resume}_noirq() for handling suspend/resume of cpufreq governors. Lan Tianyu (Intel) & Jinhyuk Choi (Broadcom) found anr issue where tunables configuration for clusters/sockets with non-boot CPUs was getting lost after suspend/resume, as we were notifying governors with CPUFREQ_GOV_POLICY_EXIT on removal of the last cpu for that policy and so deallocating memory for tunables. This is fixed by this patch as we don't allow any operation on governors after device suspend and before device resume now. Reported-and-tested-by: Lan Tianyu <tianyu.lan@intel.com> Reported-by: Jinhyuk Choi <jinchoi@broadcom.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> [rjw: Changelog, minor cleanups] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r--drivers/cpufreq/cpufreq.c43
1 files changed, 43 insertions, 0 deletions
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) {