ANDROID: GKI: drivers: cpu_cooling: allow platform freq mitigation
Allow platform drivers to register with CPU cooling with their frequency mitigation functions. This allows the platform drivers to provide the callbacks to get the current ceil limit and to set the floor and ceil limits for the cpu. Change-Id: I47960b002bf1bce1cd588de2892de46793a95562 Signed-off-by: Lina Iyer <ilina@codeaurora.org> (cherry picked from commit 986fde1710c194bede83bf62eb542e6f05af3886) Signed-off-by: Mark Salyzyn <salyzyn@google.com> Bug: 154153737
This commit is contained in:
parent
7560c37851
commit
e92e4035e0
2 changed files with 69 additions and 4 deletions
|
@ -32,6 +32,7 @@
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/cpu_cooling.h>
|
#include <linux/cpu_cooling.h>
|
||||||
#include <linux/energy_model.h>
|
#include <linux/energy_model.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
|
||||||
#include <trace/events/thermal.h>
|
#include <trace/events/thermal.h>
|
||||||
|
|
||||||
|
@ -91,6 +92,7 @@ struct cpufreq_cooling_device {
|
||||||
struct cpufreq_policy *policy;
|
struct cpufreq_policy *policy;
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
struct time_in_idle *idle_time;
|
struct time_in_idle *idle_time;
|
||||||
|
struct cpu_cooling_ops *plat_ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_IDA(cpufreq_ida);
|
static DEFINE_IDA(cpufreq_ida);
|
||||||
|
@ -342,7 +344,16 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
|
||||||
cpufreq_cdev->cpufreq_state = state;
|
cpufreq_cdev->cpufreq_state = state;
|
||||||
cpufreq_cdev->clipped_freq = clip_freq;
|
cpufreq_cdev->clipped_freq = clip_freq;
|
||||||
|
|
||||||
cpufreq_update_policy(cpufreq_cdev->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_cdev->plat_ops &&
|
||||||
|
cpufreq_cdev->plat_ops->ceil_limit)
|
||||||
|
cpufreq_cdev->plat_ops->ceil_limit(cpufreq_cdev->policy->cpu,
|
||||||
|
clip_freq);
|
||||||
|
else
|
||||||
|
cpufreq_update_policy(cpufreq_cdev->policy->cpu);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -524,6 +535,9 @@ static struct notifier_block thermal_cpufreq_notifier_block = {
|
||||||
* @policy: cpufreq policy
|
* @policy: cpufreq policy
|
||||||
* Normally this should be same as cpufreq policy->related_cpus.
|
* Normally this should be same as cpufreq policy->related_cpus.
|
||||||
* @try_model: true if a power model should be used
|
* @try_model: true if a power model should be used
|
||||||
|
* @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
|
* This interface function registers the cpufreq cooling device with the name
|
||||||
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
|
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
|
||||||
|
@ -535,7 +549,8 @@ static struct notifier_block thermal_cpufreq_notifier_block = {
|
||||||
*/
|
*/
|
||||||
static struct thermal_cooling_device *
|
static struct thermal_cooling_device *
|
||||||
__cpufreq_cooling_register(struct device_node *np,
|
__cpufreq_cooling_register(struct device_node *np,
|
||||||
struct cpufreq_policy *policy, bool try_model)
|
struct cpufreq_policy *policy, bool try_model,
|
||||||
|
struct cpu_cooling_ops *plat_ops)
|
||||||
{
|
{
|
||||||
struct thermal_cooling_device *cdev;
|
struct thermal_cooling_device *cdev;
|
||||||
struct cpufreq_cooling_device *cpufreq_cdev;
|
struct cpufreq_cooling_device *cpufreq_cdev;
|
||||||
|
@ -589,6 +604,8 @@ __cpufreq_cooling_register(struct device_node *np,
|
||||||
#endif
|
#endif
|
||||||
cooling_ops = &cpufreq_cooling_ops;
|
cooling_ops = &cpufreq_cooling_ops;
|
||||||
|
|
||||||
|
cpufreq_cdev->plat_ops = plat_ops;
|
||||||
|
|
||||||
ret = ida_simple_get(&cpufreq_ida, 0, 0, GFP_KERNEL);
|
ret = ida_simple_get(&cpufreq_ida, 0, 0, GFP_KERNEL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cdev = ERR_PTR(ret);
|
cdev = ERR_PTR(ret);
|
||||||
|
@ -642,7 +659,7 @@ __cpufreq_cooling_register(struct device_node *np,
|
||||||
struct thermal_cooling_device *
|
struct thermal_cooling_device *
|
||||||
cpufreq_cooling_register(struct cpufreq_policy *policy)
|
cpufreq_cooling_register(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
return __cpufreq_cooling_register(NULL, policy, false);
|
return __cpufreq_cooling_register(NULL, policy, false, NULL);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
|
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
|
||||||
|
|
||||||
|
@ -678,7 +695,7 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (of_find_property(np, "#cooling-cells", NULL)) {
|
if (of_find_property(np, "#cooling-cells", NULL)) {
|
||||||
cdev = __cpufreq_cooling_register(np, policy, true);
|
cdev = __cpufreq_cooling_register(np, policy, true, NULL);
|
||||||
if (IS_ERR(cdev)) {
|
if (IS_ERR(cdev)) {
|
||||||
pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n",
|
pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n",
|
||||||
policy->cpu, PTR_ERR(cdev));
|
policy->cpu, PTR_ERR(cdev));
|
||||||
|
@ -691,6 +708,37 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
|
EXPORT_SYMBOL_GPL(of_cpufreq_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(struct cpufreq_policy *policy,
|
||||||
|
struct cpu_cooling_ops *plat_ops)
|
||||||
|
{
|
||||||
|
struct device_node *cpu_node;
|
||||||
|
struct thermal_cooling_device *cdev = NULL;
|
||||||
|
|
||||||
|
cpu_node = of_cpu_device_node_get(policy->cpu);
|
||||||
|
if (!cpu_node) {
|
||||||
|
pr_err("No cpu node\n");
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
cdev = __cpufreq_cooling_register(cpu_node, policy, false,
|
||||||
|
plat_ops);
|
||||||
|
|
||||||
|
of_node_put(cpu_node);
|
||||||
|
return cdev;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(cpufreq_platform_cooling_register);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
|
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
|
||||||
* @cdev: thermal cooling device pointer.
|
* @cdev: thermal cooling device pointer.
|
||||||
|
|
|
@ -30,6 +30,12 @@
|
||||||
|
|
||||||
struct cpufreq_policy;
|
struct cpufreq_policy;
|
||||||
|
|
||||||
|
typedef int (*plat_mitig_t)(int cpu, u32 clip_freq);
|
||||||
|
|
||||||
|
struct cpu_cooling_ops {
|
||||||
|
plat_mitig_t ceil_limit, floor_limit;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_THERMAL
|
#ifdef CONFIG_CPU_THERMAL
|
||||||
/**
|
/**
|
||||||
* cpufreq_cooling_register - function to create cpufreq cooling device.
|
* cpufreq_cooling_register - function to create cpufreq cooling device.
|
||||||
|
@ -38,6 +44,10 @@ struct cpufreq_policy;
|
||||||
struct thermal_cooling_device *
|
struct thermal_cooling_device *
|
||||||
cpufreq_cooling_register(struct cpufreq_policy *policy);
|
cpufreq_cooling_register(struct cpufreq_policy *policy);
|
||||||
|
|
||||||
|
struct thermal_cooling_device *
|
||||||
|
cpufreq_platform_cooling_register(struct cpufreq_policy *policy,
|
||||||
|
struct cpu_cooling_ops *ops);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
|
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
|
||||||
* @cdev: thermal cooling device pointer.
|
* @cdev: thermal cooling device pointer.
|
||||||
|
@ -51,6 +61,13 @@ cpufreq_cooling_register(struct cpufreq_policy *policy)
|
||||||
return ERR_PTR(-ENOSYS);
|
return ERR_PTR(-ENOSYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct thermal_cooling_device *
|
||||||
|
cpufreq_platform_cooling_register(struct cpufreq_policy *policy,
|
||||||
|
struct cpu_cooling_ops *ops)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue