1 |
From 4cdf0376b2c4f74eea87889f190c536e9835cc48 Mon Sep 17 00:00:00 2001 |
2 |
From: Viresh Kumar <viresh.kumar@linaro.org> |
3 |
Date: Wed, 3 Oct 2018 15:35:21 +0530 |
4 |
Subject: [PATCH 036/145] cpufreq: dt: Try freeing static OPPs only if we have |
5 |
added them |
6 |
|
7 |
[ Upstream commit 51c99dd2c06b234575661fa1e0a1dea6c3ef566f ] |
8 |
|
9 |
We can not call dev_pm_opp_of_cpumask_remove_table() freely anymore |
10 |
since the latest OPP core updates as that uses reference counting to |
11 |
free resources. There are cases where no static OPPs are added (using |
12 |
DT) for a platform and trying to remove the OPP table may end up |
13 |
decrementing refcount which is already zero and hence generating |
14 |
warnings. |
15 |
|
16 |
Lets track if we were able to add static OPPs or not and then only |
17 |
remove the table based on that. Some reshuffling of code is also done to |
18 |
do that. |
19 |
|
20 |
Reported-by: Niklas Cassel <niklas.cassel@linaro.org> |
21 |
Tested-by: Niklas Cassel <niklas.cassel@linaro.org> |
22 |
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> |
23 |
Signed-off-by: Sasha Levin <sashal@kernel.org> |
24 |
--- |
25 |
drivers/cpufreq/cpufreq-dt.c | 34 +++++++++++++++++++--------------- |
26 |
1 file changed, 19 insertions(+), 15 deletions(-) |
27 |
|
28 |
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c |
29 |
index 0a9ebf00be46..e58bfcb1169e 100644 |
30 |
--- a/drivers/cpufreq/cpufreq-dt.c |
31 |
+++ b/drivers/cpufreq/cpufreq-dt.c |
32 |
@@ -32,6 +32,7 @@ struct private_data { |
33 |
struct device *cpu_dev; |
34 |
struct thermal_cooling_device *cdev; |
35 |
const char *reg_name; |
36 |
+ bool have_static_opps; |
37 |
}; |
38 |
|
39 |
static struct freq_attr *cpufreq_dt_attr[] = { |
40 |
@@ -204,6 +205,15 @@ static int cpufreq_init(struct cpufreq_policy *policy) |
41 |
} |
42 |
} |
43 |
|
44 |
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
45 |
+ if (!priv) { |
46 |
+ ret = -ENOMEM; |
47 |
+ goto out_put_regulator; |
48 |
+ } |
49 |
+ |
50 |
+ priv->reg_name = name; |
51 |
+ priv->opp_table = opp_table; |
52 |
+ |
53 |
/* |
54 |
* Initialize OPP tables for all policy->cpus. They will be shared by |
55 |
* all CPUs which have marked their CPUs shared with OPP bindings. |
56 |
@@ -214,7 +224,8 @@ static int cpufreq_init(struct cpufreq_policy *policy) |
57 |
* |
58 |
* OPPs might be populated at runtime, don't check for error here |
59 |
*/ |
60 |
- dev_pm_opp_of_cpumask_add_table(policy->cpus); |
61 |
+ if (!dev_pm_opp_of_cpumask_add_table(policy->cpus)) |
62 |
+ priv->have_static_opps = true; |
63 |
|
64 |
/* |
65 |
* But we need OPP table to function so if it is not there let's |
66 |
@@ -240,19 +251,10 @@ static int cpufreq_init(struct cpufreq_policy *policy) |
67 |
__func__, ret); |
68 |
} |
69 |
|
70 |
- priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
71 |
- if (!priv) { |
72 |
- ret = -ENOMEM; |
73 |
- goto out_free_opp; |
74 |
- } |
75 |
- |
76 |
- priv->reg_name = name; |
77 |
- priv->opp_table = opp_table; |
78 |
- |
79 |
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); |
80 |
if (ret) { |
81 |
dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); |
82 |
- goto out_free_priv; |
83 |
+ goto out_free_opp; |
84 |
} |
85 |
|
86 |
priv->cpu_dev = cpu_dev; |
87 |
@@ -282,10 +284,11 @@ static int cpufreq_init(struct cpufreq_policy *policy) |
88 |
|
89 |
out_free_cpufreq_table: |
90 |
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); |
91 |
-out_free_priv: |
92 |
- kfree(priv); |
93 |
out_free_opp: |
94 |
- dev_pm_opp_of_cpumask_remove_table(policy->cpus); |
95 |
+ if (priv->have_static_opps) |
96 |
+ dev_pm_opp_of_cpumask_remove_table(policy->cpus); |
97 |
+ kfree(priv); |
98 |
+out_put_regulator: |
99 |
if (name) |
100 |
dev_pm_opp_put_regulators(opp_table); |
101 |
out_put_clk: |
102 |
@@ -300,7 +303,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy) |
103 |
|
104 |
cpufreq_cooling_unregister(priv->cdev); |
105 |
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); |
106 |
- dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); |
107 |
+ if (priv->have_static_opps) |
108 |
+ dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); |
109 |
if (priv->reg_name) |
110 |
dev_pm_opp_put_regulators(priv->opp_table); |
111 |
|
112 |
-- |
113 |
2.19.1 |
114 |
|