cpufreq: governor: New data type for management part of dbs_data
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 22 Mar 2016 01:47:51 +0000 (02:47 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 1 Apr 2016 23:09:00 +0000 (01:09 +0200)
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: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_ondemand.c

index bf4913f6453b1b26f0b71485ba59896bd4f62fe0..316df247e00da306a8e4c3bb4c90aa1507a85147 100644 (file)
@@ -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,
-               const char *buf, size_t count)
+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,
-               const char *buf, size_t count)
+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,
-               size_t count)
+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;
index 3a0312f46027a859c7197da32976cc56ac74c436..6a565e248ad3c300f7d04c556bd34d6c54253e0c 100644 (file)
@@ -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);
+       count = gov_attr_set_put(&dbs_data->attr_set, &policy_dbs->list);
 
-       if (!count) {
-               kobject_put(&dbs_data->kobj);
-
-               policy->governor_data = NULL;
+       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);
index 61ff82fe0613296678532621847e5cd42361ad33..f4ad431130b8e248a53ed7e4211319ca50cae71a 100644 (file)
 /* 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 */
index acd80272ded67b46ad651cb0eceb92bdf71e26d7..300163430516766d56b842d8d12dc33175eee66b 100644 (file)
@@ -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,
-               size_t count)
+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,
-               const char *buf, size_t count)
+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,
-               const char *buf, size_t count)
+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;