summaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/qcom-cpufreq-hw.c
diff options
context:
space:
mode:
authorBjorn Andersson <bjorn.andersson@linaro.org>2022-01-27 19:25:54 -0800
committerViresh Kumar <viresh.kumar@linaro.org>2022-02-09 13:18:49 +0530
commitef8ee1cb8fc8976a68f5e89cd5f7b6f7de80c66f (patch)
tree005a02244cc4753b973132bf86610628fd200d33 /drivers/cpufreq/qcom-cpufreq-hw.c
parent4f774c4a65bf3987d1a95c966e884f38c8a942af (diff)
downloadlinux-ef8ee1cb8fc8976a68f5e89cd5f7b6f7de80c66f.tar.gz
linux-ef8ee1cb8fc8976a68f5e89cd5f7b6f7de80c66f.tar.bz2
linux-ef8ee1cb8fc8976a68f5e89cd5f7b6f7de80c66f.zip
cpufreq: qcom-hw: Delay enabling throttle_irq
In the event that the SoC is under thermal pressure while booting it's possible for the dcvs notification to happen inbetween the cpufreq framework calling init and it actually updating the policy's related_cpus cpumask. Prior to the introduction of the thermal pressure update helper an empty cpumask would simply result in the thermal pressure of no cpus being updated, but the new code will attempt to dereference an invalid per_cpu variable. Avoid this problem by using the newly reintroduced "ready" callback, to postpone enabling the IRQ until the related_cpus cpumask is filled in. Fixes: 0258cb19c77d ("cpufreq: qcom-cpufreq-hw: Use new thermal pressure update function") Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Diffstat (limited to 'drivers/cpufreq/qcom-cpufreq-hw.c')
-rw-r--r--drivers/cpufreq/qcom-cpufreq-hw.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 05f3d7876e44..effbb680b453 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -388,7 +388,7 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
snprintf(data->irq_name, sizeof(data->irq_name), "dcvsh-irq-%u", policy->cpu);
ret = request_threaded_irq(data->throttle_irq, NULL, qcom_lmh_dcvs_handle_irq,
- IRQF_ONESHOT, data->irq_name, data);
+ IRQF_ONESHOT | IRQF_NO_AUTOEN, data->irq_name, data);
if (ret) {
dev_err(&pdev->dev, "Error registering %s: %d\n", data->irq_name, ret);
return 0;
@@ -542,6 +542,14 @@ static int qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
+static void qcom_cpufreq_ready(struct cpufreq_policy *policy)
+{
+ struct qcom_cpufreq_data *data = policy->driver_data;
+
+ if (data->throttle_irq >= 0)
+ enable_irq(data->throttle_irq);
+}
+
static struct freq_attr *qcom_cpufreq_hw_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
&cpufreq_freq_attr_scaling_boost_freqs,
@@ -561,6 +569,7 @@ static struct cpufreq_driver cpufreq_qcom_hw_driver = {
.fast_switch = qcom_cpufreq_hw_fast_switch,
.name = "qcom-cpufreq-hw",
.attr = qcom_cpufreq_hw_attr,
+ .ready = qcom_cpufreq_ready,
};
static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev)