From 02103dc49ea34d75e0affde50a9da93c533b8f53 Mon Sep 17 00:00:00 2001 From: Kishore Sri venkata Ganesh Bolisetty Date: Thu, 30 Jul 2020 08:50:58 -0700 Subject: [PATCH] soc: qcom: msm_perf: fix invalid usage of dev freq qos apis msm_perf is attempting to add freq qos requests without waiting for policy create notifications. This may cause corruption at latter point of time when it attempts to trigger freq qos update requests. The changes registers for policy create notifications and defers the add requests until dev freq is up. Change-Id: Idee4268ded948062e627cc4dcdf85ceaf48e5ce7 Signed-off-by: Kishore Sri venkata Ganesh Bolisetty --- drivers/soc/qcom/msm_performance.c | 115 +++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index 1c98ac89ee3f..74ffdcce6dcb 100644 --- a/drivers/soc/qcom/msm_performance.c +++ b/drivers/soc/qcom/msm_performance.c @@ -59,6 +59,68 @@ static unsigned int curr_cap[CLUSTER_MAX]; static cpumask_var_t limit_mask_min; static cpumask_var_t limit_mask_max; +static bool ready_for_freq_updates; + +static int freq_qos_request_init(void) +{ + unsigned int cpu; + int ret; + + struct cpufreq_policy *policy; + struct freq_qos_request *req; + + for_each_present_cpu(cpu) { + policy = cpufreq_cpu_get(cpu); + if (!policy) { + pr_err("%s: Failed to get cpufreq policy for cpu%d\n", + __func__, cpu); + ret = -EAGAIN; + goto cleanup; + } + + per_cpu(msm_perf_cpu_stats, cpu).min = 0; + req = &per_cpu(qos_req_min, cpu); + ret = freq_qos_add_request(&policy->constraints, req, + FREQ_QOS_MIN, policy->min); + if (ret < 0) { + pr_err("%s: Failed to add min freq constraint (%d)\n", + __func__, ret); + cpufreq_cpu_put(policy); + goto cleanup; + } + + per_cpu(msm_perf_cpu_stats, cpu).max = UINT_MAX; + req = &per_cpu(qos_req_max, cpu); + ret = freq_qos_add_request(&policy->constraints, req, + FREQ_QOS_MAX, policy->max); + if (ret < 0) { + pr_err("%s: Failed to add max freq constraint (%d)\n", + __func__, ret); + cpufreq_cpu_put(policy); + goto cleanup; + } + + cpufreq_cpu_put(policy); + } + return 0; + +cleanup: + for_each_present_cpu(cpu) { + req = &per_cpu(qos_req_min, cpu); + if (req) + freq_qos_remove_request(req); + + + req = &per_cpu(qos_req_max, cpu); + if (req) + freq_qos_remove_request(req); + + per_cpu(msm_perf_cpu_stats, cpu).min = 0; + per_cpu(msm_perf_cpu_stats, cpu).max = UINT_MAX; + } + return ret; +} + /*******************************sysfs start************************************/ static int set_cpu_min_freq(const char *buf, const struct kernel_param *kp) { @@ -68,6 +130,17 @@ static int set_cpu_min_freq(const char *buf, const struct kernel_param *kp) struct cpu_status *i_cpu_stats; struct cpufreq_policy policy; struct freq_qos_request *req; + int ret = 0; + + if (!ready_for_freq_updates) { + ret = freq_qos_request_init(); + if (ret) { + pr_err("%s: Failed to init qos requests policy for ret=%d\n", + __func__, ret); + return ret; + } + ready_for_freq_updates = true; + } while ((cp = strpbrk(cp + 1, " :"))) ntokens++; @@ -108,7 +181,7 @@ static int set_cpu_min_freq(const char *buf, const struct kernel_param *kp) continue; if (cpu_online(i) && (policy.min != i_cpu_stats->min)) { - req = &per_cpu(qos_req_min, cpu); + req = &per_cpu(qos_req_min, i); if (freq_qos_update_request(req, i_cpu_stats->min) < 0) break; } @@ -148,7 +221,17 @@ static int set_cpu_max_freq(const char *buf, const struct kernel_param *kp) struct cpu_status *i_cpu_stats; struct cpufreq_policy policy; struct freq_qos_request *req; + int ret = 0; + if (!ready_for_freq_updates) { + ret = freq_qos_request_init(); + if (ret) { + pr_err("%s: Failed to init qos requests policy for ret=%d\n", + __func__, ret); + return ret; + } + ready_for_freq_updates = true; + } while ((cp = strpbrk(cp + 1, " :"))) ntokens++; @@ -181,7 +264,7 @@ static int set_cpu_max_freq(const char *buf, const struct kernel_param *kp) continue; if (cpu_online(i) && (policy.max != i_cpu_stats->max)) { - req = &per_cpu(qos_req_max, cpu); + req = &per_cpu(qos_req_max, i); if (freq_qos_update_request(req, i_cpu_stats->max) < 0) break; } @@ -474,35 +557,7 @@ module_param_cb(core_ctl_register, ¶m_ops_cc_register, static int __init msm_performance_init(void) { - unsigned int cpu; int ret; - - struct cpufreq_policy *policy; - struct freq_qos_request *req; - - for_each_present_cpu(cpu) { - per_cpu(msm_perf_cpu_stats, cpu).max = UINT_MAX; - req = &per_cpu(qos_req_min, cpu); - policy = cpufreq_cpu_get(cpu); - if (!policy) - continue; - ret = freq_qos_add_request(&policy->constraints, req, - FREQ_QOS_MIN, policy->min); - if (ret < 0) { - pr_err("%s: Failed to add min freq constraint (%d)\n", - __func__, ret); - return ret; - } - req = &per_cpu(qos_req_max, cpu); - ret = freq_qos_add_request(&policy->constraints, req, - FREQ_QOS_MAX, policy->max); - if (ret < 0) { - pr_err("%s: Failed to add max freq constraint (%d)\n", - __func__, ret); - return ret; - } - } - if (!alloc_cpumask_var(&limit_mask_min, GFP_KERNEL)) return -ENOMEM;