Skip to content

Commit

Permalink
thermal: cpu_cooling: Store frequencies in descending order
Browse files Browse the repository at this point in the history
CPUFreq framework *doesn't* guarantee that frequencies present in cpufreq table
will be in ascending or descending order. But cpu_cooling somehow assumes that.

Probably because most of current users are creating this list from DT, which is
done with the help of OPP layer. And OPP layer creates the list in ascending
order of frequencies.

But cpu_cooling can be used for other platforms too, which don't have
frequencies arranged in any order.

This patch tries to fix this issue by creating another list of valid frequencies
in descending order. Care is also taken to throw warnings for duplicate entries.

Later patches would use it to simplify code.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
  • Loading branch information
Viresh Kumar authored and Eduardo Valentin committed Dec 8, 2014
1 parent b9f8b41 commit f685901
Showing 1 changed file with 40 additions and 1 deletion.
41 changes: 40 additions & 1 deletion drivers/thermal/cpu_cooling.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct cpufreq_cooling_device {
unsigned int cpufreq_state;
unsigned int cpufreq_val;
unsigned int max_level;
unsigned int *freq_table; /* In descending order */
struct cpumask allowed_cpus;
struct list_head node;
};
Expand Down Expand Up @@ -352,6 +353,20 @@ static struct notifier_block thermal_cpufreq_notifier_block = {
.notifier_call = cpufreq_thermal_notifier,
};

static unsigned int find_next_max(struct cpufreq_frequency_table *table,
unsigned int prev_max)
{
struct cpufreq_frequency_table *pos;
unsigned int max = 0;

cpufreq_for_each_valid_entry(pos, table) {
if (pos->frequency > max && pos->frequency < prev_max)
max = pos->frequency;
}

return max;
}

/**
* __cpufreq_cooling_register - helper function to create cpufreq cooling device
* @np: a valid struct device_node to the cooling device device tree node
Expand All @@ -374,6 +389,7 @@ __cpufreq_cooling_register(struct device_node *np,
struct cpufreq_cooling_device *cpufreq_dev;
char dev_name[THERMAL_NAME_LENGTH];
struct cpufreq_frequency_table *pos, *table;
unsigned int freq, i;
int ret;

table = cpufreq_frequency_get_table(cpumask_first(clip_cpus));
Expand All @@ -397,6 +413,14 @@ __cpufreq_cooling_register(struct device_node *np,
cpufreq_for_each_valid_entry(pos, table)
cpufreq_dev->max_level++;

cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
cpufreq_dev->max_level, GFP_KERNEL);
if (!cpufreq_dev->freq_table) {
return ERR_PTR(-ENOMEM);
cool_dev = ERR_PTR(-ENOMEM);
goto free_cdev;
}

/* max_level is an index, not a counter */
cpufreq_dev->max_level--;

Expand All @@ -405,7 +429,7 @@ __cpufreq_cooling_register(struct device_node *np,
ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
if (ret) {
cool_dev = ERR_PTR(ret);
goto free_cdev;
goto free_table;
}

snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
Expand All @@ -416,6 +440,18 @@ __cpufreq_cooling_register(struct device_node *np,
if (IS_ERR(cool_dev))
goto remove_idr;

/* Fill freq-table in descending order of frequencies */
for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) {
freq = find_next_max(table, freq);
cpufreq_dev->freq_table[i] = freq;

/* Warn for duplicate entries */
if (!freq)
pr_warn("%s: table has duplicate entries\n", __func__);
else
pr_debug("%s: freq:%u KHz\n", __func__, freq);
}

cpufreq_dev->cool_dev = cool_dev;

mutex_lock(&cooling_cpufreq_lock);
Expand All @@ -432,6 +468,8 @@ __cpufreq_cooling_register(struct device_node *np,

remove_idr:
release_idr(&cpufreq_idr, cpufreq_dev->id);
free_table:
kfree(cpufreq_dev->freq_table);
free_cdev:
kfree(cpufreq_dev);

Expand Down Expand Up @@ -505,6 +543,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)

thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
release_idr(&cpufreq_idr, cpufreq_dev->id);
kfree(cpufreq_dev->freq_table);
kfree(cpufreq_dev);
}
EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister);

0 comments on commit f685901

Please sign in to comment.