aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-03-27 11:58:57 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-31 19:11:34 -0400
commit7bd353a995d9049262661d85811d6109140582a3 (patch)
tree65535a5142ec5063547bc5b77f8ff03e6979816b
parent0d1857a1b987ef874aeb4b99c9c385fa5645bf61 (diff)
cpufreq: Add per policy governor-init/exit infrastructure
Currently, there can't be multiple instances of single governor_type. If we have a multi-package system, where we have multiple instances of struct policy (per package), we can't have multiple instances of same governor. i.e. We can't have multiple instances of ondemand governor for multiple packages. Governors directory in sysfs is created at /sys/devices/system/cpu/cpufreq/ governor-name/. Which again reflects that there can be only one instance of a governor_type in the system. This is a bottleneck for multicluster system, where we want different packages to use same governor type, but with different tunables. This patch is inclined towards providing this infrastructure. Because we are required to allocate governor's resources dynamically now, we must do it at policy creation and end. And so got CPUFREQ_GOV_POLICY_INIT/EXIT. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/cpufreq.c21
-rw-r--r--include/linux/cpufreq.h9
2 files changed, 24 insertions, 6 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index c5996fe7250e..08df7a196116 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1070,6 +1070,8 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
1070 1070
1071 /* If cpu is last user of policy, free policy */ 1071 /* If cpu is last user of policy, free policy */
1072 if (cpus == 1) { 1072 if (cpus == 1) {
1073 __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
1074
1073 lock_policy_rwsem_read(cpu); 1075 lock_policy_rwsem_read(cpu);
1074 kobj = &data->kobj; 1076 kobj = &data->kobj;
1075 cmp = &data->kobj_unregister; 1077 cmp = &data->kobj_unregister;
@@ -1651,7 +1653,7 @@ EXPORT_SYMBOL(cpufreq_get_policy);
1651static int __cpufreq_set_policy(struct cpufreq_policy *data, 1653static int __cpufreq_set_policy(struct cpufreq_policy *data,
1652 struct cpufreq_policy *policy) 1654 struct cpufreq_policy *policy)
1653{ 1655{
1654 int ret = 0; 1656 int ret = 0, failed = 1;
1655 1657
1656 pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, 1658 pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
1657 policy->min, policy->max); 1659 policy->min, policy->max);
@@ -1705,18 +1707,31 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
1705 pr_debug("governor switch\n"); 1707 pr_debug("governor switch\n");
1706 1708
1707 /* end old governor */ 1709 /* end old governor */
1708 if (data->governor) 1710 if (data->governor) {
1709 __cpufreq_governor(data, CPUFREQ_GOV_STOP); 1711 __cpufreq_governor(data, CPUFREQ_GOV_STOP);
1712 __cpufreq_governor(data,
1713 CPUFREQ_GOV_POLICY_EXIT);
1714 }
1710 1715
1711 /* start new governor */ 1716 /* start new governor */
1712 data->governor = policy->governor; 1717 data->governor = policy->governor;
1713 if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { 1718 if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
1719 if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
1720 failed = 0;
1721 else
1722 __cpufreq_governor(data,
1723 CPUFREQ_GOV_POLICY_EXIT);
1724 }
1725
1726 if (failed) {
1714 /* new governor failed, so re-start old one */ 1727 /* new governor failed, so re-start old one */
1715 pr_debug("starting governor %s failed\n", 1728 pr_debug("starting governor %s failed\n",
1716 data->governor->name); 1729 data->governor->name);
1717 if (old_gov) { 1730 if (old_gov) {
1718 data->governor = old_gov; 1731 data->governor = old_gov;
1719 __cpufreq_governor(data, 1732 __cpufreq_governor(data,
1733 CPUFREQ_GOV_POLICY_INIT);
1734 __cpufreq_governor(data,
1720 CPUFREQ_GOV_START); 1735 CPUFREQ_GOV_START);
1721 } 1736 }
1722 ret = -EINVAL; 1737 ret = -EINVAL;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index a22944ca0526..b7393b56f552 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -106,6 +106,7 @@ struct cpufreq_policy {
106 * governors are used */ 106 * governors are used */
107 unsigned int policy; /* see above */ 107 unsigned int policy; /* see above */
108 struct cpufreq_governor *governor; /* see below */ 108 struct cpufreq_governor *governor; /* see below */
109 void *governor_data;
109 110
110 struct work_struct update; /* if update_policy() needs to be 111 struct work_struct update; /* if update_policy() needs to be
111 * called, but you're in IRQ context */ 112 * called, but you're in IRQ context */
@@ -178,9 +179,11 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu
178 * CPUFREQ GOVERNORS * 179 * CPUFREQ GOVERNORS *
179 *********************************************************************/ 180 *********************************************************************/
180 181
181#define CPUFREQ_GOV_START 1 182#define CPUFREQ_GOV_START 1
182#define CPUFREQ_GOV_STOP 2 183#define CPUFREQ_GOV_STOP 2
183#define CPUFREQ_GOV_LIMITS 3 184#define CPUFREQ_GOV_LIMITS 3
185#define CPUFREQ_GOV_POLICY_INIT 4
186#define CPUFREQ_GOV_POLICY_EXIT 5
184 187
185struct cpufreq_governor { 188struct cpufreq_governor {
186 char name[CPUFREQ_NAME_LEN]; 189 char name[CPUFREQ_NAME_LEN];