aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/thermal/cpu_cooling.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 7687922cb02e..cb5a4b914187 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -65,6 +65,7 @@ struct cpufreq_cooling_device {
65 unsigned int cpufreq_state; 65 unsigned int cpufreq_state;
66 unsigned int cpufreq_val; 66 unsigned int cpufreq_val;
67 unsigned int max_level; 67 unsigned int max_level;
68 unsigned int *freq_table; /* In descending order */
68 struct cpumask allowed_cpus; 69 struct cpumask allowed_cpus;
69 struct list_head node; 70 struct list_head node;
70}; 71};
@@ -352,6 +353,20 @@ static struct notifier_block thermal_cpufreq_notifier_block = {
352 .notifier_call = cpufreq_thermal_notifier, 353 .notifier_call = cpufreq_thermal_notifier,
353}; 354};
354 355
356static 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
355/** 370/**
356 * __cpufreq_cooling_register - helper function to create cpufreq cooling device 371 * __cpufreq_cooling_register - helper function to create cpufreq cooling device
357 * @np: a valid struct device_node to the cooling device device tree node 372 * @np: a valid struct device_node to the cooling device device tree node
@@ -374,6 +389,7 @@ __cpufreq_cooling_register(struct device_node *np,
374 struct cpufreq_cooling_device *cpufreq_dev; 389 struct cpufreq_cooling_device *cpufreq_dev;
375 char dev_name[THERMAL_NAME_LENGTH]; 390 char dev_name[THERMAL_NAME_LENGTH];
376 struct cpufreq_frequency_table *pos, *table; 391 struct cpufreq_frequency_table *pos, *table;
392 unsigned int freq, i;
377 int ret; 393 int ret;
378 394
379 table = cpufreq_frequency_get_table(cpumask_first(clip_cpus)); 395 table = cpufreq_frequency_get_table(cpumask_first(clip_cpus));
@@ -397,6 +413,14 @@ __cpufreq_cooling_register(struct device_node *np,
397 cpufreq_for_each_valid_entry(pos, table) 413 cpufreq_for_each_valid_entry(pos, table)
398 cpufreq_dev->max_level++; 414 cpufreq_dev->max_level++;
399 415
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
400 /* max_level is an index, not a counter */ 424 /* max_level is an index, not a counter */
401 cpufreq_dev->max_level--; 425 cpufreq_dev->max_level--;
402 426
@@ -405,7 +429,7 @@ __cpufreq_cooling_register(struct device_node *np,
405 ret = get_idr(&cpufreq_idr, &cpufreq_dev->id); 429 ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
406 if (ret) { 430 if (ret) {
407 cool_dev = ERR_PTR(ret); 431 cool_dev = ERR_PTR(ret);
408 goto free_cdev; 432 goto free_table;
409 } 433 }
410 434
411 snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d", 435 snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
@@ -416,6 +440,18 @@ __cpufreq_cooling_register(struct device_node *np,
416 if (IS_ERR(cool_dev)) 440 if (IS_ERR(cool_dev))
417 goto remove_idr; 441 goto remove_idr;
418 442
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
419 cpufreq_dev->cool_dev = cool_dev; 455 cpufreq_dev->cool_dev = cool_dev;
420 456
421 mutex_lock(&cooling_cpufreq_lock); 457 mutex_lock(&cooling_cpufreq_lock);
@@ -432,6 +468,8 @@ __cpufreq_cooling_register(struct device_node *np,
432 468
433remove_idr: 469remove_idr:
434 release_idr(&cpufreq_idr, cpufreq_dev->id); 470 release_idr(&cpufreq_idr, cpufreq_dev->id);
471free_table:
472 kfree(cpufreq_dev->freq_table);
435free_cdev: 473free_cdev:
436 kfree(cpufreq_dev); 474 kfree(cpufreq_dev);
437 475
@@ -505,6 +543,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
505 543
506 thermal_cooling_device_unregister(cpufreq_dev->cool_dev); 544 thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
507 release_idr(&cpufreq_idr, cpufreq_dev->id); 545 release_idr(&cpufreq_idr, cpufreq_dev->id);
546 kfree(cpufreq_dev->freq_table);
508 kfree(cpufreq_dev); 547 kfree(cpufreq_dev);
509} 548}
510EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister); 549EXPORT_SYMBOL_GPL(cpufreq_cooling_unregister);