Skip to content

Commit f685901

Browse files
vireshkEduardo Valentin
authored and
Eduardo Valentin
committed
thermal: cpu_cooling: Store frequencies in descending order
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>
1 parent b9f8b41 commit f685901

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

drivers/thermal/cpu_cooling.c

+40-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct cpufreq_cooling_device {
6565
unsigned int cpufreq_state;
6666
unsigned int cpufreq_val;
6767
unsigned int max_level;
68+
unsigned int *freq_table; /* In descending order */
6869
struct cpumask allowed_cpus;
6970
struct list_head node;
7071
};
@@ -352,6 +353,20 @@ static struct notifier_block thermal_cpufreq_notifier_block = {
352353
.notifier_call = cpufreq_thermal_notifier,
353354
};
354355

356+
static unsigned int find_next_max(struct cpufreq_frequency_table *table,
357+
unsigned int prev_max)
358+
{
359+
struct cpufreq_frequency_table *pos;
360+
unsigned int max = 0;
361+
362+
cpufreq_for_each_valid_entry(pos, table) {
363+
if (pos->frequency > max && pos->frequency < prev_max)
364+
max = pos->frequency;
365+
}
366+
367+
return max;
368+
}
369+
355370
/**
356371
* __cpufreq_cooling_register - helper function to create cpufreq cooling device
357372
* @np: a valid struct device_node to the cooling device device tree node
@@ -374,6 +389,7 @@ __cpufreq_cooling_register(struct device_node *np,
374389
struct cpufreq_cooling_device *cpufreq_dev;
375390
char dev_name[THERMAL_NAME_LENGTH];
376391
struct cpufreq_frequency_table *pos, *table;
392+
unsigned int freq, i;
377393
int ret;
378394

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

416+
cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
417+
cpufreq_dev->max_level, GFP_KERNEL);
418+
if (!cpufreq_dev->freq_table) {
419+
return ERR_PTR(-ENOMEM);
420+
cool_dev = ERR_PTR(-ENOMEM);
421+
goto free_cdev;
422+
}
423+
400424
/* max_level is an index, not a counter */
401425
cpufreq_dev->max_level--;
402426

@@ -405,7 +429,7 @@ __cpufreq_cooling_register(struct device_node *np,
405429
ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
406430
if (ret) {
407431
cool_dev = ERR_PTR(ret);
408-
goto free_cdev;
432+
goto free_table;
409433
}
410434

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

443+
/* Fill freq-table in descending order of frequencies */
444+
for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) {
445+
freq = find_next_max(table, freq);
446+
cpufreq_dev->freq_table[i] = freq;
447+
448+
/* Warn for duplicate entries */
449+
if (!freq)
450+
pr_warn("%s: table has duplicate entries\n", __func__);
451+
else
452+
pr_debug("%s: freq:%u KHz\n", __func__, freq);
453+
}
454+
419455
cpufreq_dev->cool_dev = cool_dev;
420456

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

433469
remove_idr:
434470
release_idr(&cpufreq_idr, cpufreq_dev->id);
471+
free_table:
472+
kfree(cpufreq_dev->freq_table);
435473
free_cdev:
436474
kfree(cpufreq_dev);
437475

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

506544
thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
507545
release_idr(&cpufreq_idr, cpufreq_dev->id);
546+
kfree(cpufreq_dev->freq_table);
508547
kfree(cpufreq_dev);
509548
}
510549
EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister);

0 commit comments

Comments
 (0)