From c95ca544325f40f55858e02526d0bd6a1740480d Mon Sep 17 00:00:00 2001 Message-Id: From: Viresh Kumar Date: Tue, 26 Mar 2013 23:20:18 +0530 Subject: [PATCH] fixup! cpufreq: governor: Implement per policy instances of governors --- drivers/cpufreq/cpufreq.c | 13 +++++++ drivers/cpufreq/cpufreq_governor.c | 74 +++++++++++++++++++++++++++----------- include/linux/cpufreq.h | 2 ++ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 8f2a603..3c79025 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -136,6 +136,11 @@ struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) return cpufreq_global_kobject; } +bool have_multiple_policies(void) +{ + return cpufreq_driver->have_multiple_policies; +} + static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) { struct cpufreq_policy *data; @@ -1561,6 +1566,13 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, policy->cpu, event); ret = policy->governor->governor(policy, event); + if (!ret) { + if (event == CPUFREQ_GOV_POLICY_INIT) + policy->governor->initialized++; + else if (event == CPUFREQ_GOV_POLICY_EXIT) + policy->governor->initialized--; + } + /* we keep one module reference alive for each CPU governed by this CPU */ if ((event != CPUFREQ_GOV_START) || ret) @@ -1584,6 +1596,7 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) mutex_lock(&cpufreq_governor_mutex); + governor->initialized = 0; err = -EBUSY; if (__find_governor(governor->name) == NULL) { err = 0; diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 41e5e56..f29feb4 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -29,6 +29,9 @@ #include "cpufreq_governor.h" +/* Common data for platforms that don't need governor instance per policy */ +struct dbs_data *gdbs_data; + static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) { u64 idle_time; @@ -216,10 +219,9 @@ static void set_sampling_rate(struct dbs_data *dbs_data, int cpufreq_governor_dbs(struct cpufreq_policy *policy, struct common_dbs_data *cdata, unsigned int event) { - struct dbs_data *dbs_data = policy->governor_data; + struct dbs_data *dbs_data; struct od_cpu_dbs_info_s *od_dbs_info = NULL; struct cs_cpu_dbs_info_s *cs_dbs_info = NULL; - struct cs_ops *cs_ops = NULL; struct od_ops *od_ops = NULL; struct od_dbs_tuners *od_tuners = NULL; struct cs_dbs_tuners *cs_tuners = NULL; @@ -228,11 +230,22 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, int io_busy = 0; int rc; + if (have_multiple_policies()) + dbs_data = policy->governor_data; + else + dbs_data = gdbs_data; + WARN_ON(!dbs_data && (event != CPUFREQ_GOV_POLICY_INIT)); switch (event) { case CPUFREQ_GOV_POLICY_INIT: - WARN_ON(dbs_data); + if (have_multiple_policies()) { + WARN_ON(dbs_data); + } else if (dbs_data) { + policy->governor_data = dbs_data; + return 0; + } + dbs_data = kzalloc(sizeof(*dbs_data), GFP_KERNEL); if (!dbs_data) { pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__); @@ -246,6 +259,15 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, kfree(dbs_data); return rc; } + + rc = sysfs_create_group(get_governor_parent_kobj(policy), + dbs_data->cdata->attr_group); + if (rc) { + cdata->exit(dbs_data); + kfree(dbs_data); + return rc; + } + policy->governor_data = dbs_data; /* policy latency is in nS. Convert it to uS first */ @@ -258,10 +280,36 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, MIN_LATENCY_MULTIPLIER * latency); set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate, latency * LATENCY_MULTIPLIER)); + + if (dbs_data->cdata->governor == GOV_CONSERVATIVE) { + struct cs_ops *cs_ops = dbs_data->cdata->gov_ops; + + cpufreq_register_notifier(cs_ops->notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + + if (!have_multiple_policies()) + gdbs_data = dbs_data; + return 0; case CPUFREQ_GOV_POLICY_EXIT: - cdata->exit(dbs_data); - kfree(dbs_data); + if ((policy->governor->initialized == 1) || + have_multiple_policies()) { + sysfs_remove_group(get_governor_parent_kobj(policy), + dbs_data->cdata->attr_group); + + if (dbs_data->cdata->governor == GOV_CONSERVATIVE) { + struct cs_ops *cs_ops = dbs_data->cdata->gov_ops; + + cpufreq_register_notifier(cs_ops->notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + } + + cdata->exit(dbs_data); + kfree(dbs_data); + gdbs_data = NULL; + } + policy->governor_data = NULL; return 0; } @@ -273,7 +321,6 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, cs_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); sampling_rate = cs_tuners->sampling_rate; ignore_nice = cs_tuners->ignore_nice; - cs_ops = dbs_data->cdata->gov_ops; } else { od_tuners = dbs_data->tuners; od_dbs_info = dbs_data->cdata->get_cpu_dbs_info_s(cpu); @@ -307,13 +354,6 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_data->cdata->gov_dbs_timer); } - rc = sysfs_create_group(get_governor_parent_kobj(policy), - dbs_data->cdata->attr_group); - if (rc) { - mutex_unlock(&dbs_data->mutex); - return rc; - } - /* * conservative does not implement micro like ondemand * governor, thus we are bound to jiffes/HZ @@ -322,9 +362,6 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, cs_dbs_info->down_skip = 0; cs_dbs_info->enable = 1; cs_dbs_info->requested_freq = policy->cur; - - cpufreq_register_notifier(cs_ops->notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); } else { od_dbs_info->rate_mult = 1; od_dbs_info->sample_type = OD_NORMAL_SAMPLE; @@ -349,11 +386,6 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_data->mutex); mutex_destroy(&cpu_cdbs->timer_mutex); - sysfs_remove_group(get_governor_parent_kobj(policy), - dbs_data->cdata->attr_group); - if (dbs_data->cdata->governor == GOV_CONSERVATIVE) - cpufreq_unregister_notifier(cs_ops->notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); mutex_unlock(&dbs_data->mutex); break; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 8fe9b10..f253a3e 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -187,6 +187,7 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu struct cpufreq_governor { char name[CPUFREQ_NAME_LEN]; + int initialized; int (*governor) (struct cpufreq_policy *policy, unsigned int event); ssize_t (*show_setspeed) (struct cpufreq_policy *policy, @@ -323,6 +324,7 @@ const char *cpufreq_get_current_driver(void); int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); int cpufreq_update_policy(unsigned int cpu); struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); +bool have_multiple_policies(void); #ifdef CONFIG_CPU_FREQ /* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */ -- 1.7.12.rc2.18.g61b472e