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

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

cpufreq: governor: New data type for management part of dbs_data



In addition to fields representing governor tunables, struct dbs_data
contains some fields needed for the management of objects of that
type.  As it turns out, that part of struct dbs_data may be shared
with (future) governors that won't use the common code used by
"ondemand" and "conservative", so move it to a separate struct type
and modify the code using struct dbs_data to follow.

Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent 0bed612b
Loading
Loading
Loading
Loading
+15 −10
Original line number Diff line number Diff line
@@ -129,9 +129,10 @@ static struct notifier_block cs_cpufreq_notifier_block = {
/************************** sysfs interface ************************/
static struct dbs_governor cs_dbs_gov;

static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
					  const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	unsigned int input;
	int ret;
	ret = sscanf(buf, "%u", &input);
@@ -143,9 +144,10 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
	return count;
}

static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
		size_t count)
static ssize_t store_up_threshold(struct gov_attr_set *attr_set,
				  const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
	unsigned int input;
	int ret;
@@ -158,9 +160,10 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
	return count;
}

static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
		size_t count)
static ssize_t store_down_threshold(struct gov_attr_set *attr_set,
				    const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
	unsigned int input;
	int ret;
@@ -175,9 +178,10 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
	return count;
}

static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
static ssize_t store_ignore_nice_load(struct gov_attr_set *attr_set,
				      const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	unsigned int input;
	int ret;

@@ -199,9 +203,10 @@ static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
	return count;
}

static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf,
static ssize_t store_freq_step(struct gov_attr_set *attr_set, const char *buf,
			       size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
	unsigned int input;
	int ret;
+55 −35
Original line number Diff line number Diff line
@@ -43,9 +43,10 @@ static DEFINE_MUTEX(gov_dbs_data_mutex);
 * This must be called with dbs_data->mutex held, otherwise traversing
 * policy_dbs_list isn't safe.
 */
ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf,
			    size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	struct policy_dbs_info *policy_dbs;
	unsigned int rate;
	int ret;
@@ -59,7 +60,7 @@ ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
	 * We are operating under dbs_data->mutex and so the list and its
	 * entries can't be freed concurrently.
	 */
	list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
	list_for_each_entry(policy_dbs, &attr_set->policy_list, list) {
		mutex_lock(&policy_dbs->timer_mutex);
		/*
		 * On 32-bit architectures this may race with the
@@ -96,7 +97,7 @@ void gov_update_cpu_data(struct dbs_data *dbs_data)
{
	struct policy_dbs_info *policy_dbs;

	list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
	list_for_each_entry(policy_dbs, &dbs_data->attr_set.policy_list, list) {
		unsigned int j;

		for_each_cpu(j, policy_dbs->policy->cpus) {
@@ -111,9 +112,9 @@ void gov_update_cpu_data(struct dbs_data *dbs_data)
}
EXPORT_SYMBOL_GPL(gov_update_cpu_data);

static inline struct dbs_data *to_dbs_data(struct kobject *kobj)
static inline struct gov_attr_set *to_gov_attr_set(struct kobject *kobj)
{
	return container_of(kobj, struct dbs_data, kobj);
	return container_of(kobj, struct gov_attr_set, kobj);
}

static inline struct governor_attr *to_gov_attr(struct attribute *attr)
@@ -124,25 +125,24 @@ static inline struct governor_attr *to_gov_attr(struct attribute *attr)
static ssize_t governor_show(struct kobject *kobj, struct attribute *attr,
			     char *buf)
{
	struct dbs_data *dbs_data = to_dbs_data(kobj);
	struct governor_attr *gattr = to_gov_attr(attr);

	return gattr->show(dbs_data, buf);
	return gattr->show(to_gov_attr_set(kobj), buf);
}

static ssize_t governor_store(struct kobject *kobj, struct attribute *attr,
			      const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(kobj);
	struct gov_attr_set *attr_set = to_gov_attr_set(kobj);
	struct governor_attr *gattr = to_gov_attr(attr);
	int ret = -EBUSY;

	mutex_lock(&dbs_data->mutex);
	mutex_lock(&attr_set->update_lock);

	if (dbs_data->usage_count)
		ret = gattr->store(dbs_data, buf, count);
	if (attr_set->usage_count)
		ret = gattr->store(attr_set, buf, count);

	mutex_unlock(&dbs_data->mutex);
	mutex_unlock(&attr_set->update_lock);

	return ret;
}
@@ -425,6 +425,41 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
	gov->free(policy_dbs);
}

static void gov_attr_set_init(struct gov_attr_set *attr_set,
			      struct list_head *list_node)
{
	INIT_LIST_HEAD(&attr_set->policy_list);
	mutex_init(&attr_set->update_lock);
	attr_set->usage_count = 1;
	list_add(list_node, &attr_set->policy_list);
}

static void gov_attr_set_get(struct gov_attr_set *attr_set,
			     struct list_head *list_node)
{
	mutex_lock(&attr_set->update_lock);
	attr_set->usage_count++;
	list_add(list_node, &attr_set->policy_list);
	mutex_unlock(&attr_set->update_lock);
}

static unsigned int gov_attr_set_put(struct gov_attr_set *attr_set,
				     struct list_head *list_node)
{
	unsigned int count;

	mutex_lock(&attr_set->update_lock);
	list_del(list_node);
	count = --attr_set->usage_count;
	mutex_unlock(&attr_set->update_lock);
	if (count)
		return count;

	kobject_put(&attr_set->kobj);
	mutex_destroy(&attr_set->update_lock);
	return 0;
}

static int cpufreq_governor_init(struct cpufreq_policy *policy)
{
	struct dbs_governor *gov = dbs_governor_of(policy);
@@ -453,10 +488,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
		policy_dbs->dbs_data = dbs_data;
		policy->governor_data = policy_dbs;

		mutex_lock(&dbs_data->mutex);
		dbs_data->usage_count++;
		list_add(&policy_dbs->list, &dbs_data->policy_dbs_list);
		mutex_unlock(&dbs_data->mutex);
		gov_attr_set_get(&dbs_data->attr_set, &policy_dbs->list);
		goto out;
	}

@@ -466,8 +498,7 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
		goto free_policy_dbs_info;
	}

	INIT_LIST_HEAD(&dbs_data->policy_dbs_list);
	mutex_init(&dbs_data->mutex);
	gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list);

	ret = gov->init(dbs_data, !policy->governor->initialized);
	if (ret)
@@ -487,14 +518,11 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy)
	if (!have_governor_per_policy())
		gov->gdbs_data = dbs_data;

	policy->governor_data = policy_dbs;

	policy_dbs->dbs_data = dbs_data;
	dbs_data->usage_count = 1;
	list_add(&policy_dbs->list, &dbs_data->policy_dbs_list);
	policy->governor_data = policy_dbs;

	gov->kobj_type.sysfs_ops = &governor_sysfs_ops;
	ret = kobject_init_and_add(&dbs_data->kobj, &gov->kobj_type,
	ret = kobject_init_and_add(&dbs_data->attr_set.kobj, &gov->kobj_type,
				   get_governor_parent_kobj(policy),
				   "%s", gov->gov.name);
	if (!ret)
@@ -523,29 +551,21 @@ static int cpufreq_governor_exit(struct cpufreq_policy *policy)
	struct dbs_governor *gov = dbs_governor_of(policy);
	struct policy_dbs_info *policy_dbs = policy->governor_data;
	struct dbs_data *dbs_data = policy_dbs->dbs_data;
	int count;
	unsigned int count;

	/* Protect gov->gdbs_data against concurrent updates. */
	mutex_lock(&gov_dbs_data_mutex);

	mutex_lock(&dbs_data->mutex);
	list_del(&policy_dbs->list);
	count = --dbs_data->usage_count;
	mutex_unlock(&dbs_data->mutex);

	if (!count) {
		kobject_put(&dbs_data->kobj);
	count = gov_attr_set_put(&dbs_data->attr_set, &policy_dbs->list);

	policy->governor_data = NULL;

	if (!count) {
		if (!have_governor_per_policy())
			gov->gdbs_data = NULL;

		gov->exit(dbs_data, policy->governor->initialized == 1);
		mutex_destroy(&dbs_data->mutex);
		kfree(dbs_data);
	} else {
		policy->governor_data = NULL;
	}

	free_policy_dbs_info(policy_dbs, gov);
+20 −15
Original line number Diff line number Diff line
@@ -41,6 +41,13 @@
/* Ondemand Sampling types */
enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};

struct gov_attr_set {
	struct kobject kobj;
	struct list_head policy_list;
	struct mutex update_lock;
	int usage_count;
};

/*
 * Abbreviations:
 * dbs: used as a shortform for demand based switching It helps to keep variable
@@ -52,7 +59,7 @@ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};

/* Governor demand based switching data (per-policy or global). */
struct dbs_data {
	int usage_count;
	struct gov_attr_set attr_set;
	void *tuners;
	unsigned int min_sampling_rate;
	unsigned int ignore_nice_load;
@@ -60,37 +67,35 @@ struct dbs_data {
	unsigned int sampling_down_factor;
	unsigned int up_threshold;
	unsigned int io_is_busy;

	struct kobject kobj;
	struct list_head policy_dbs_list;
	/*
	 * Protect concurrent updates to governor tunables from sysfs,
	 * policy_dbs_list and usage_count.
	 */
	struct mutex mutex;
};

static inline struct dbs_data *to_dbs_data(struct gov_attr_set *attr_set)
{
	return container_of(attr_set, struct dbs_data, attr_set);
}

/* Governor's specific attributes */
struct dbs_data;
struct governor_attr {
	struct attribute attr;
	ssize_t (*show)(struct dbs_data *dbs_data, char *buf);
	ssize_t (*store)(struct dbs_data *dbs_data, const char *buf,
	ssize_t (*show)(struct gov_attr_set *attr_set, char *buf);
	ssize_t (*store)(struct gov_attr_set *attr_set, const char *buf,
			 size_t count);
};

#define gov_show_one(_gov, file_name)					\
static ssize_t show_##file_name						\
(struct dbs_data *dbs_data, char *buf)					\
(struct gov_attr_set *attr_set, char *buf)				\
{									\
	struct dbs_data *dbs_data = to_dbs_data(attr_set);		\
	struct _gov##_dbs_tuners *tuners = dbs_data->tuners;		\
	return sprintf(buf, "%u\n", tuners->file_name);			\
}

#define gov_show_one_common(file_name)					\
static ssize_t show_##file_name						\
(struct dbs_data *dbs_data, char *buf)					\
(struct gov_attr_set *attr_set, char *buf)				\
{									\
	struct dbs_data *dbs_data = to_dbs_data(attr_set);		\
	return sprintf(buf, "%u\n", dbs_data->file_name);		\
}

@@ -184,7 +189,7 @@ void od_register_powersave_bias_handler(unsigned int (*f)
		(struct cpufreq_policy *, unsigned int, unsigned int),
		unsigned int powersave_bias);
void od_unregister_powersave_bias_handler(void);
ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf,
			    size_t count);
void gov_update_cpu_data(struct dbs_data *dbs_data);
#endif /* _CPUFREQ_GOVERNOR_H */
+17 −12
Original line number Diff line number Diff line
@@ -207,9 +207,10 @@ static unsigned int od_dbs_timer(struct cpufreq_policy *policy)
/************************** sysfs interface ************************/
static struct dbs_governor od_dbs_gov;

static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf,
static ssize_t store_io_is_busy(struct gov_attr_set *attr_set, const char *buf,
				size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	unsigned int input;
	int ret;

@@ -224,9 +225,10 @@ static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf,
	return count;
}

static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
		size_t count)
static ssize_t store_up_threshold(struct gov_attr_set *attr_set,
				  const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	unsigned int input;
	int ret;
	ret = sscanf(buf, "%u", &input);
@@ -240,9 +242,10 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
	return count;
}

static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
					  const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	struct policy_dbs_info *policy_dbs;
	unsigned int input;
	int ret;
@@ -254,7 +257,7 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
	dbs_data->sampling_down_factor = input;

	/* Reset down sampling multiplier in case it was active */
	list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
	list_for_each_entry(policy_dbs, &attr_set->policy_list, list) {
		/*
		 * Doing this without locking might lead to using different
		 * rate_mult values in od_update() and od_dbs_timer().
@@ -267,9 +270,10 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
	return count;
}

static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
static ssize_t store_ignore_nice_load(struct gov_attr_set *attr_set,
				      const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	unsigned int input;
	int ret;

@@ -291,9 +295,10 @@ static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
	return count;
}

static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf,
		size_t count)
static ssize_t store_powersave_bias(struct gov_attr_set *attr_set,
				    const char *buf, size_t count)
{
	struct dbs_data *dbs_data = to_dbs_data(attr_set);
	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
	struct policy_dbs_info *policy_dbs;
	unsigned int input;
@@ -308,7 +313,7 @@ static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf,

	od_tuners->powersave_bias = input;

	list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list)
	list_for_each_entry(policy_dbs, &attr_set->policy_list, list)
		ondemand_powersave_bias_init(policy_dbs->policy);

	return count;