diff options
Diffstat (limited to 'drivers/thermal/cpu_cooling.c')
-rw-r--r-- | drivers/thermal/cpu_cooling.c | 56 |
1 files changed, 49 insertions, 7 deletions
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 87d87ac1c8a0..632fa8c1260b 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -103,6 +103,7 @@ struct cpufreq_cooling_device { int dyn_power_table_entries; struct device *cpu_dev; get_static_t plat_get_static_power; + struct cpu_cooling_ops *plat_ops; }; static DEFINE_IDR(cpufreq_idr); static DEFINE_MUTEX(cooling_cpufreq_lock); @@ -506,8 +507,13 @@ static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state) { struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; + unsigned int cpu = cpumask_any(&cpufreq_device->allowed_cpus); - *state = cpufreq_device->cpufreq_state; + if (cpufreq_device->plat_ops + && cpufreq_device->plat_ops->get_cur_state) + cpufreq_device->plat_ops->get_cur_state(cpu, state); + else + *state = cpufreq_device->cpufreq_state; return 0; } @@ -541,7 +547,17 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, cpufreq_device->cpufreq_state = state; cpufreq_device->clipped_freq = clip_freq; - cpufreq_update_policy(cpu); + /* Check if the device has a platform mitigation function that + * can handle the CPU freq mitigation, if not, notify cpufreq + * framework. + */ + if (cpufreq_device->plat_ops) { + if (cpufreq_device->plat_ops->ceil_limit) + cpufreq_device->plat_ops->ceil_limit(cpu, + clip_freq); + } else { + cpufreq_update_policy(cpu); + } return 0; } @@ -775,6 +791,9 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table, * @capacitance: dynamic power coefficient for these cpus * @plat_static_func: function to calculate the static power consumed by these * cpus (optional) + * @plat_mitig_func: function that does the mitigation by changing the + * frequencies (Optional). By default, cpufreq framweork will + * be notified of the new limits. * * This interface function registers the cpufreq cooling device with the name * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq @@ -787,7 +806,8 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table, static struct thermal_cooling_device * __cpufreq_cooling_register(struct device_node *np, const struct cpumask *clip_cpus, u32 capacitance, - get_static_t plat_static_func) + get_static_t plat_static_func, + struct cpu_cooling_ops *plat_ops) { struct thermal_cooling_device *cool_dev; struct cpufreq_cooling_device *cpufreq_dev; @@ -853,6 +873,8 @@ __cpufreq_cooling_register(struct device_node *np, } } + cpufreq_dev->plat_ops = plat_ops; + ret = get_idr(&cpufreq_idr, &cpufreq_dev->id); if (ret) { cool_dev = ERR_PTR(ret); @@ -926,7 +948,7 @@ free_cdev: struct thermal_cooling_device * cpufreq_cooling_register(const struct cpumask *clip_cpus) { - return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL); + return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL, NULL); } EXPORT_SYMBOL_GPL(cpufreq_cooling_register); @@ -950,7 +972,7 @@ of_cpufreq_cooling_register(struct device_node *np, if (!np) return ERR_PTR(-EINVAL); - return __cpufreq_cooling_register(np, clip_cpus, 0, NULL); + return __cpufreq_cooling_register(np, clip_cpus, 0, NULL, NULL); } EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register); @@ -980,11 +1002,31 @@ cpufreq_power_cooling_register(const struct cpumask *clip_cpus, u32 capacitance, get_static_t plat_static_func) { return __cpufreq_cooling_register(NULL, clip_cpus, capacitance, - plat_static_func); + plat_static_func, NULL); } EXPORT_SYMBOL(cpufreq_power_cooling_register); /** + * cpufreq_platform_cooling_register() - create cpufreq cooling device with + * additional platform specific mitigation function. + * + * @clip_cpus: cpumask of cpus where the frequency constraints will happen + * @plat_ops: the platform mitigation functions that will be called insted of + * cpufreq, if provided. + * + * Return: a valid struct thermal_cooling_device pointer on success, + * on failure, it returns a corresponding ERR_PTR(). + */ +struct thermal_cooling_device * +cpufreq_platform_cooling_register(const struct cpumask *clip_cpus, + struct cpu_cooling_ops *plat_ops) +{ + return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL, + plat_ops); +} +EXPORT_SYMBOL(cpufreq_platform_cooling_register); + +/** * of_cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions * @np: a valid struct device_node to the cooling device device tree node * @clip_cpus: cpumask of cpus where the frequency constraints will happen @@ -1017,7 +1059,7 @@ of_cpufreq_power_cooling_register(struct device_node *np, return ERR_PTR(-EINVAL); return __cpufreq_cooling_register(np, clip_cpus, capacitance, - plat_static_func); + plat_static_func, NULL); } EXPORT_SYMBOL(of_cpufreq_power_cooling_register); |