Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e788892b authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

cpufreq: governor: Get rid of governor events



The design of the cpufreq governor API is not very straightforward,
as struct cpufreq_governor provides only one callback to be invoked
from different code paths for different purposes.  The purpose it is
invoked for is determined by its second "event" argument, causing it
to act as a "callback multiplexer" of sorts.

Unfortunately, that leads to extra complexity in governors, some of
which implement the ->governor() callback as a switch statement
that simply checks the event argument and invokes a separate function
to handle that specific event.

That extra complexity can be eliminated by replacing the all-purpose
->governor() callback with a family of callbacks to carry out specific
governor operations: initialization and exit, start and stop and policy
limits updates.  That also turns out to reduce the code size too, so
do it.

Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent a92604b4
Loading
Loading
Loading
Loading
+34 −38
Original line number Diff line number Diff line
@@ -85,27 +85,21 @@ static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
	cancel_delayed_work_sync(&info->work);
}

static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
static int spu_gov_start(struct cpufreq_policy *policy)
{
	unsigned int cpu = policy->cpu;
	struct spu_gov_info_struct *info, *affected_info;
	struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
	struct spu_gov_info_struct *affected_info;
	int i;
	int ret = 0;

	info = &per_cpu(spu_gov_info, cpu);

	switch (event) {
	case CPUFREQ_GOV_START:
	if (!cpu_online(cpu)) {
		printk(KERN_ERR "cpu %d is not online\n", cpu);
			ret = -EINVAL;
			break;
		return -EINVAL;
	}

	if (!policy->cur) {
		printk(KERN_ERR "no cpu specified in policy\n");
			ret = -EINVAL;
			break;
		return -EINVAL;
	}

	/* initialize spu_gov_info for all affected cpus */
@@ -119,9 +113,15 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
	/* setup timer */
	spu_gov_init_work(info);

		break;
	return 0;
}

static void spu_gov_stop(struct cpufreq_policy *policy)
{
	unsigned int cpu = policy->cpu;
	struct spu_gov_info_struct *info = &per_cpu(spu_gov_info, cpu);
	int i;

	case CPUFREQ_GOV_STOP:
	/* cancel timer */
	spu_gov_cancel_work(info);

@@ -130,16 +130,12 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
		info = &per_cpu(spu_gov_info, i);
		info->policy = NULL;
	}

		break;
	}

	return ret;
}

static struct cpufreq_governor spu_governor = {
	.name = "spudemand",
	.governor = spu_gov_govern,
	.start = spu_gov_start,
	.stop = spu_gov_stop,
	.owner = THIS_MODULE,
};

+20 −11
Original line number Diff line number Diff line
@@ -2023,11 +2023,13 @@ static int cpufreq_init_governor(struct cpufreq_policy *policy)

	pr_debug("%s: for CPU %u\n", __func__, policy->cpu);

	ret = policy->governor->governor(policy, CPUFREQ_GOV_POLICY_INIT);
	if (policy->governor->init) {
		ret = policy->governor->init(policy);
		if (ret) {
			module_put(policy->governor->owner);
			return ret;
		}
	}

	policy->governor->initialized++;
	return 0;
@@ -2040,7 +2042,8 @@ static void cpufreq_exit_governor(struct cpufreq_policy *policy)

	pr_debug("%s: for CPU %u\n", __func__, policy->cpu);

	policy->governor->governor(policy, CPUFREQ_GOV_POLICY_EXIT);
	if (policy->governor->exit)
		policy->governor->exit(policy);

	policy->governor->initialized--;
	module_put(policy->governor->owner);
@@ -2061,11 +2064,15 @@ static int cpufreq_start_governor(struct cpufreq_policy *policy)
	if (cpufreq_driver->get && !cpufreq_driver->setpolicy)
		cpufreq_update_current_freq(policy);

	ret = policy->governor->governor(policy, CPUFREQ_GOV_START);
	if (policy->governor->start) {
		ret = policy->governor->start(policy);
		if (ret)
			return ret;
	}

	if (policy->governor->limits)
		policy->governor->limits(policy);

	policy->governor->governor(policy, CPUFREQ_GOV_LIMITS);
	return 0;
}

@@ -2076,7 +2083,8 @@ static void cpufreq_stop_governor(struct cpufreq_policy *policy)

	pr_debug("%s: for CPU %u\n", __func__, policy->cpu);

	policy->governor->governor(policy, CPUFREQ_GOV_STOP);
	if (policy->governor->stop)
		policy->governor->stop(policy);
}

static void cpufreq_governor_limits(struct cpufreq_policy *policy)
@@ -2086,7 +2094,8 @@ static void cpufreq_governor_limits(struct cpufreq_policy *policy)

	pr_debug("%s: for CPU %u\n", __func__, policy->cpu);

	policy->governor->governor(policy, CPUFREQ_GOV_LIMITS);
	if (policy->governor->limits)
		policy->governor->limits(policy);
}

int cpufreq_register_governor(struct cpufreq_governor *governor)
+1 −6
Original line number Diff line number Diff line
@@ -313,12 +313,7 @@ static void cs_start(struct cpufreq_policy *policy)
}

static struct dbs_governor cs_dbs_gov = {
	.gov = {
		.name = "conservative",
		.governor = cpufreq_governor_dbs,
		.max_transition_latency = TRANSITION_LATENCY_LIMIT,
		.owner = THIS_MODULE,
	},
	.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
	.kobj_type = { .default_attrs = cs_attributes },
	.gov_dbs_timer = cs_dbs_timer,
	.alloc = cs_alloc,
+10 −29
Original line number Diff line number Diff line
@@ -389,7 +389,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
	gov->free(policy_dbs);
}

static int cpufreq_governor_init(struct cpufreq_policy *policy)
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
{
	struct dbs_governor *gov = dbs_governor_of(policy);
	struct dbs_data *dbs_data;
@@ -474,8 +474,9 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
	mutex_unlock(&gov_dbs_data_mutex);
	return ret;
}
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_init);

static int cpufreq_governor_exit(struct cpufreq_policy *policy)
void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy)
{
	struct dbs_governor *gov = dbs_governor_of(policy);
	struct policy_dbs_info *policy_dbs = policy->governor_data;
@@ -500,10 +501,10 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy)
	free_policy_dbs_info(policy_dbs, gov);

	mutex_unlock(&gov_dbs_data_mutex);
	return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_exit);

static int cpufreq_governor_start(struct cpufreq_policy *policy)
int cpufreq_dbs_governor_start(struct cpufreq_policy *policy)
{
	struct dbs_governor *gov = dbs_governor_of(policy);
	struct policy_dbs_info *policy_dbs = policy->governor_data;
@@ -539,14 +540,15 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy)
	gov_set_update_util(policy_dbs, sampling_rate);
	return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_start);

static int cpufreq_governor_stop(struct cpufreq_policy *policy)
void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy)
{
	gov_cancel_work(policy);
	return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);

static int cpufreq_governor_limits(struct cpufreq_policy *policy)
void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
{
	struct policy_dbs_info *policy_dbs = policy->governor_data;

@@ -560,26 +562,5 @@ static int cpufreq_governor_limits(struct cpufreq_policy *policy)
	gov_update_sample_delay(policy_dbs, 0);

	mutex_unlock(&policy_dbs->timer_mutex);

	return 0;
}

int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
{
	if (event == CPUFREQ_GOV_POLICY_INIT) {
		return cpufreq_governor_init(policy);
	} else if (policy->governor_data) {
		switch (event) {
		case CPUFREQ_GOV_POLICY_EXIT:
			return cpufreq_governor_exit(policy);
		case CPUFREQ_GOV_START:
			return cpufreq_governor_start(policy);
		case CPUFREQ_GOV_STOP:
			return cpufreq_governor_stop(policy);
		case CPUFREQ_GOV_LIMITS:
			return cpufreq_governor_limits(policy);
		}
	}
	return -EINVAL;
}
EXPORT_SYMBOL_GPL(cpufreq_governor_dbs);
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
+19 −1
Original line number Diff line number Diff line
@@ -148,6 +148,25 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
	return container_of(policy->governor, struct dbs_governor, gov);
}

/* Governor callback routines */
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
void cpufreq_dbs_governor_stop(struct cpufreq_policy *policy);
void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy);

#define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_)			\
	{								\
		.name = _name_,						\
		.max_transition_latency	= TRANSITION_LATENCY_LIMIT,	\
		.owner = THIS_MODULE,					\
		.init = cpufreq_dbs_governor_init,			\
		.exit = cpufreq_dbs_governor_exit,			\
		.start = cpufreq_dbs_governor_start,			\
		.stop = cpufreq_dbs_governor_stop,			\
		.limits = cpufreq_dbs_governor_limits,			\
	}

/* Governor specific operations */
struct od_ops {
	unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
@@ -155,7 +174,6 @@ struct od_ops {
};

unsigned int dbs_update(struct cpufreq_policy *policy);
int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event);
void od_register_powersave_bias_handler(unsigned int (*f)
		(struct cpufreq_policy *, unsigned int, unsigned int),
		unsigned int powersave_bias);
Loading