aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2014-03-03 22:00:26 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-03-06 09:04:12 -0500
commit2f0aea9363609433b38ab13f0f86f38372668c68 (patch)
tree459115b73ec6e5ece6ee73a711fa95dac8a98da0 /drivers/cpufreq/cpufreq.c
parent6e2c89d16d987e6e11c531b039a42d3f5f1d7c32 (diff)
cpufreq: suspend governors on system suspend/hibernate
This patch adds cpufreq suspend/resume calls to dpm_{suspend|resume}() for handling suspend/resume of cpufreq governors. Lan Tianyu (Intel) & Jinhyuk Choi (Broadcom) found an issue where the tunables configuration for clusters/sockets with non-boot CPUs was lost after system suspend/resume, as we were notifying governors with CPUFREQ_GOV_POLICY_EXIT on removal of the last CPU for that policy which caused the tunables memory to be freed. This is fixed by preventing any governor operations from being carried out between the device suspend and device resume stages of system suspend and resume, respectively. We could have added these callbacks at dpm_{suspend|resume}_noirq() level, but there is an additional problem that the majority of I/O devices is already suspended at that point and if cpufreq drivers want to change the frequency before suspending, then that not be possible on some platforms (which depend on peripherals like i2c, regulators, etc). 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] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r--drivers/cpufreq/cpufreq.c111
1 files changed, 56 insertions, 55 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 2de2f1ddd95f..289a407a9207 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -26,7 +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/syscore_ops.h> 29#include <linux/suspend.h>
30#include <linux/tick.h> 30#include <linux/tick.h>
31#include <trace/events/power.h> 31#include <trace/events/power.h>
32 32
@@ -45,6 +45,9 @@ static LIST_HEAD(cpufreq_policy_list);
45/* This one keeps track of the previously set governor of a removed CPU */ 45/* This one keeps track of the previously set governor of a removed CPU */
46static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); 46static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
47 47
48/* Flag to suspend/resume CPUFreq governors */
49static bool cpufreq_suspended;
50
48static inline bool has_target(void) 51static inline bool has_target(void)
49{ 52{
50 return cpufreq_driver->target_index || cpufreq_driver->target; 53 return cpufreq_driver->target_index || cpufreq_driver->target;
@@ -1565,82 +1568,77 @@ static struct subsys_interface cpufreq_interface = {
1565}; 1568};
1566 1569
1567/** 1570/**
1568 * cpufreq_bp_suspend - Prepare the boot CPU for system suspend. 1571 * cpufreq_suspend() - Suspend CPUFreq governors
1569 * 1572 *
1570 * This function is only executed for the boot processor. The other CPUs 1573 * Called during system wide Suspend/Hibernate cycles for suspending governors
1571 * have been put offline by means of CPU hotplug. 1574 * as some platforms can't change frequency after this point in suspend cycle.
1575 * Because some of the devices (like: i2c, regulators, etc) they use for
1576 * changing frequency are suspended quickly after this point.
1572 */ 1577 */
1573static int cpufreq_bp_suspend(void) 1578void cpufreq_suspend(void)
1574{ 1579{
1575 int ret = 0;
1576
1577 int cpu = smp_processor_id();
1578 struct cpufreq_policy *policy; 1580 struct cpufreq_policy *policy;
1579 1581
1580 pr_debug("suspending cpu %u\n", cpu); 1582 if (!cpufreq_driver)
1583 return;
1581 1584
1582 /* If there's no policy for the boot CPU, we have nothing to do. */ 1585 if (!has_target())
1583 policy = cpufreq_cpu_get(cpu); 1586 return;
1584 if (!policy)
1585 return 0;
1586 1587
1587 if (cpufreq_driver->suspend) { 1588 pr_debug("%s: Suspending Governors\n", __func__);
1588 ret = cpufreq_driver->suspend(policy); 1589
1589 if (ret) 1590 list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
1590 printk(KERN_ERR "cpufreq: suspend failed in ->suspend " 1591 if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
1591 "step on CPU %u\n", policy->cpu); 1592 pr_err("%s: Failed to stop governor for policy: %p\n",
1593 __func__, policy);
1594 else if (cpufreq_driver->suspend
1595 && cpufreq_driver->suspend(policy))
1596 pr_err("%s: Failed to suspend driver: %p\n", __func__,
1597 policy);
1592 } 1598 }
1593 1599
1594 cpufreq_cpu_put(policy); 1600 cpufreq_suspended = true;
1595 return ret;
1596} 1601}
1597 1602
1598/** 1603/**
1599 * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU. 1604 * cpufreq_resume() - Resume CPUFreq governors
1600 * 1605 *
1601 * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) 1606 * Called during system wide Suspend/Hibernate cycle for resuming governors that
1602 * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are 1607 * are suspended with cpufreq_suspend().
1603 * restored. It will verify that the current freq is in sync with
1604 * what we believe it to be. This is a bit later than when it
1605 * should be, but nonethteless it's better than calling
1606 * cpufreq_driver->get() here which might re-enable interrupts...
1607 *
1608 * This function is only executed for the boot CPU. The other CPUs have not
1609 * been turned on yet.
1610 */ 1608 */
1611static void cpufreq_bp_resume(void) 1609void cpufreq_resume(void)
1612{ 1610{
1613 int ret = 0;
1614
1615 int cpu = smp_processor_id();
1616 struct cpufreq_policy *policy; 1611 struct cpufreq_policy *policy;
1617 1612
1618 pr_debug("resuming cpu %u\n", cpu); 1613 if (!cpufreq_driver)
1614 return;
1619 1615
1620 /* If there's no policy for the boot CPU, we have nothing to do. */ 1616 if (!has_target())
1621 policy = cpufreq_cpu_get(cpu);
1622 if (!policy)
1623 return; 1617 return;
1624 1618
1625 if (cpufreq_driver->resume) { 1619 pr_debug("%s: Resuming Governors\n", __func__);
1626 ret = cpufreq_driver->resume(policy);
1627 if (ret) {
1628 printk(KERN_ERR "cpufreq: resume failed in ->resume "
1629 "step on CPU %u\n", policy->cpu);
1630 goto fail;
1631 }
1632 }
1633 1620
1634 schedule_work(&policy->update); 1621 cpufreq_suspended = false;
1635 1622
1636fail: 1623 list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
1637 cpufreq_cpu_put(policy); 1624 if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
1638} 1625 || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
1626 pr_err("%s: Failed to start governor for policy: %p\n",
1627 __func__, policy);
1628 else if (cpufreq_driver->resume
1629 && cpufreq_driver->resume(policy))
1630 pr_err("%s: Failed to resume driver: %p\n", __func__,
1631 policy);
1639 1632
1640static struct syscore_ops cpufreq_syscore_ops = { 1633 /*
1641 .suspend = cpufreq_bp_suspend, 1634 * schedule call cpufreq_update_policy() for boot CPU, i.e. last
1642 .resume = cpufreq_bp_resume, 1635 * policy in list. It will verify that the current freq is in
1643}; 1636 * sync with what we believe it to be.
1637 */
1638 if (list_is_last(&policy->policy_list, &cpufreq_policy_list))
1639 schedule_work(&policy->update);
1640 }
1641}
1644 1642
1645/** 1643/**
1646 * cpufreq_get_current_driver - return current driver's name 1644 * cpufreq_get_current_driver - return current driver's name
@@ -1857,6 +1855,10 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
1857 struct cpufreq_governor *gov = NULL; 1855 struct cpufreq_governor *gov = NULL;
1858#endif 1856#endif
1859 1857
1858 /* Don't start any governor operations if we are entering suspend */
1859 if (cpufreq_suspended)
1860 return 0;
1861
1860 if (policy->governor->max_transition_latency && 1862 if (policy->governor->max_transition_latency &&
1861 policy->cpuinfo.transition_latency > 1863 policy->cpuinfo.transition_latency >
1862 policy->governor->max_transition_latency) { 1864 policy->governor->max_transition_latency) {
@@ -2392,7 +2394,6 @@ static int __init cpufreq_core_init(void)
2392 2394
2393 cpufreq_global_kobject = kobject_create(); 2395 cpufreq_global_kobject = kobject_create();
2394 BUG_ON(!cpufreq_global_kobject); 2396 BUG_ON(!cpufreq_global_kobject);
2395 register_syscore_ops(&cpufreq_syscore_ops);
2396 2397
2397 return 0; 2398 return 0;
2398} 2399}