cpufreq: governors: Fix CPUFREQ_GOV_POLICY_{INIT|EXIT} notifiers
There are two types of INIT/EXIT activities that we need to do for governors: - Done only once per governor (doesn't depend how many instances of the governor there are). eg: cpufreq_register_notifier() for conservative governor. - Done per governor instance, eg: sysfs_{create|remove}_group(). There were some corner cases where current code isn't able to handle them separately and so failing for some test cases. We use two separate variables now for keeping track of above two requirements. - governor->initialized for first one - dbs_data->usage_count for per governor instance Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
2b80f3138e
commit
a97c98addd
|
@ -255,6 +255,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||||
if (have_governor_per_policy()) {
|
if (have_governor_per_policy()) {
|
||||||
WARN_ON(dbs_data);
|
WARN_ON(dbs_data);
|
||||||
} else if (dbs_data) {
|
} else if (dbs_data) {
|
||||||
|
dbs_data->usage_count++;
|
||||||
policy->governor_data = dbs_data;
|
policy->governor_data = dbs_data;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -266,6 +267,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||||
}
|
}
|
||||||
|
|
||||||
dbs_data->cdata = cdata;
|
dbs_data->cdata = cdata;
|
||||||
|
dbs_data->usage_count = 1;
|
||||||
rc = cdata->init(dbs_data);
|
rc = cdata->init(dbs_data);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("%s: POLICY_INIT: init() failed\n", __func__);
|
pr_err("%s: POLICY_INIT: init() failed\n", __func__);
|
||||||
|
@ -294,7 +296,8 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||||
set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
|
set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
|
||||||
latency * LATENCY_MULTIPLIER));
|
latency * LATENCY_MULTIPLIER));
|
||||||
|
|
||||||
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
|
if ((cdata->governor == GOV_CONSERVATIVE) &&
|
||||||
|
(!policy->governor->initialized)) {
|
||||||
struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
|
struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
|
||||||
|
|
||||||
cpufreq_register_notifier(cs_ops->notifier_block,
|
cpufreq_register_notifier(cs_ops->notifier_block,
|
||||||
|
@ -306,12 +309,12 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case CPUFREQ_GOV_POLICY_EXIT:
|
case CPUFREQ_GOV_POLICY_EXIT:
|
||||||
if ((policy->governor->initialized == 1) ||
|
if (!--dbs_data->usage_count) {
|
||||||
have_governor_per_policy()) {
|
|
||||||
sysfs_remove_group(get_governor_parent_kobj(policy),
|
sysfs_remove_group(get_governor_parent_kobj(policy),
|
||||||
get_sysfs_attr(dbs_data));
|
get_sysfs_attr(dbs_data));
|
||||||
|
|
||||||
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
|
if ((dbs_data->cdata->governor == GOV_CONSERVATIVE) &&
|
||||||
|
(policy->governor->initialized == 1)) {
|
||||||
struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
|
struct cs_ops *cs_ops = dbs_data->cdata->gov_ops;
|
||||||
|
|
||||||
cpufreq_unregister_notifier(cs_ops->notifier_block,
|
cpufreq_unregister_notifier(cs_ops->notifier_block,
|
||||||
|
|
|
@ -211,6 +211,7 @@ struct common_dbs_data {
|
||||||
struct dbs_data {
|
struct dbs_data {
|
||||||
struct common_dbs_data *cdata;
|
struct common_dbs_data *cdata;
|
||||||
unsigned int min_sampling_rate;
|
unsigned int min_sampling_rate;
|
||||||
|
int usage_count;
|
||||||
void *tuners;
|
void *tuners;
|
||||||
|
|
||||||
/* dbs_mutex protects dbs_enable in governor start/stop */
|
/* dbs_mutex protects dbs_enable in governor start/stop */
|
||||||
|
|
Loading…
Reference in New Issue