提交 7bd353a9 编写于 作者: V Viresh Kumar 提交者: Rafael J. Wysocki

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: NViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
上级 0d1857a1
...@@ -1070,6 +1070,8 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif ...@@ -1070,6 +1070,8 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif
/* If cpu is last user of policy, free policy */ /* If cpu is last user of policy, free policy */
if (cpus == 1) { if (cpus == 1) {
__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
lock_policy_rwsem_read(cpu); lock_policy_rwsem_read(cpu);
kobj = &data->kobj; kobj = &data->kobj;
cmp = &data->kobj_unregister; cmp = &data->kobj_unregister;
...@@ -1651,7 +1653,7 @@ EXPORT_SYMBOL(cpufreq_get_policy); ...@@ -1651,7 +1653,7 @@ EXPORT_SYMBOL(cpufreq_get_policy);
static int __cpufreq_set_policy(struct cpufreq_policy *data, static int __cpufreq_set_policy(struct cpufreq_policy *data,
struct cpufreq_policy *policy) struct cpufreq_policy *policy)
{ {
int ret = 0; int ret = 0, failed = 1;
pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
policy->min, policy->max); policy->min, policy->max);
...@@ -1705,17 +1707,30 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, ...@@ -1705,17 +1707,30 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
pr_debug("governor switch\n"); pr_debug("governor switch\n");
/* end old governor */ /* end old governor */
if (data->governor) if (data->governor) {
__cpufreq_governor(data, CPUFREQ_GOV_STOP); __cpufreq_governor(data, CPUFREQ_GOV_STOP);
__cpufreq_governor(data,
CPUFREQ_GOV_POLICY_EXIT);
}
/* start new governor */ /* start new governor */
data->governor = policy->governor; data->governor = policy->governor;
if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) {
if (!__cpufreq_governor(data, CPUFREQ_GOV_START))
failed = 0;
else
__cpufreq_governor(data,
CPUFREQ_GOV_POLICY_EXIT);
}
if (failed) {
/* new governor failed, so re-start old one */ /* new governor failed, so re-start old one */
pr_debug("starting governor %s failed\n", pr_debug("starting governor %s failed\n",
data->governor->name); data->governor->name);
if (old_gov) { if (old_gov) {
data->governor = old_gov; data->governor = old_gov;
__cpufreq_governor(data,
CPUFREQ_GOV_POLICY_INIT);
__cpufreq_governor(data, __cpufreq_governor(data,
CPUFREQ_GOV_START); CPUFREQ_GOV_START);
} }
......
...@@ -106,6 +106,7 @@ struct cpufreq_policy { ...@@ -106,6 +106,7 @@ struct cpufreq_policy {
* governors are used */ * governors are used */
unsigned int policy; /* see above */ unsigned int policy; /* see above */
struct cpufreq_governor *governor; /* see below */ struct cpufreq_governor *governor; /* see below */
void *governor_data;
struct work_struct update; /* if update_policy() needs to be struct work_struct update; /* if update_policy() needs to be
* called, but you're in IRQ context */ * called, but you're in IRQ context */
...@@ -181,6 +182,8 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu ...@@ -181,6 +182,8 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu
#define CPUFREQ_GOV_START 1 #define CPUFREQ_GOV_START 1
#define CPUFREQ_GOV_STOP 2 #define CPUFREQ_GOV_STOP 2
#define CPUFREQ_GOV_LIMITS 3 #define CPUFREQ_GOV_LIMITS 3
#define CPUFREQ_GOV_POLICY_INIT 4
#define CPUFREQ_GOV_POLICY_EXIT 5
struct cpufreq_governor { struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN]; char name[CPUFREQ_NAME_LEN];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册