aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/opp/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/power/opp/cpu.c')
-rw-r--r--drivers/base/power/opp/cpu.c66
1 files changed, 15 insertions, 51 deletions
diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c
index 8c3434bdb26d..2d87bc1adf38 100644
--- a/drivers/base/power/opp/cpu.c
+++ b/drivers/base/power/opp/cpu.c
@@ -42,11 +42,6 @@
42 * 42 *
43 * WARNING: It is important for the callers to ensure refreshing their copy of 43 * WARNING: It is important for the callers to ensure refreshing their copy of
44 * the table if any of the mentioned functions have been invoked in the interim. 44 * the table if any of the mentioned functions have been invoked in the interim.
45 *
46 * Locking: The internal opp_table and opp structures are RCU protected.
47 * Since we just use the regular accessor functions to access the internal data
48 * structures, we use RCU read lock inside this function. As a result, users of
49 * this function DONOT need to use explicit locks for invoking.
50 */ 45 */
51int dev_pm_opp_init_cpufreq_table(struct device *dev, 46int dev_pm_opp_init_cpufreq_table(struct device *dev,
52 struct cpufreq_frequency_table **table) 47 struct cpufreq_frequency_table **table)
@@ -56,19 +51,13 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
56 int i, max_opps, ret = 0; 51 int i, max_opps, ret = 0;
57 unsigned long rate; 52 unsigned long rate;
58 53
59 rcu_read_lock();
60
61 max_opps = dev_pm_opp_get_opp_count(dev); 54 max_opps = dev_pm_opp_get_opp_count(dev);
62 if (max_opps <= 0) { 55 if (max_opps <= 0)
63 ret = max_opps ? max_opps : -ENODATA; 56 return max_opps ? max_opps : -ENODATA;
64 goto out;
65 }
66 57
67 freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC); 58 freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC);
68 if (!freq_table) { 59 if (!freq_table)
69 ret = -ENOMEM; 60 return -ENOMEM;
70 goto out;
71 }
72 61
73 for (i = 0, rate = 0; i < max_opps; i++, rate++) { 62 for (i = 0, rate = 0; i < max_opps; i++, rate++) {
74 /* find next rate */ 63 /* find next rate */
@@ -83,6 +72,8 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
83 /* Is Boost/turbo opp ? */ 72 /* Is Boost/turbo opp ? */
84 if (dev_pm_opp_is_turbo(opp)) 73 if (dev_pm_opp_is_turbo(opp))
85 freq_table[i].flags = CPUFREQ_BOOST_FREQ; 74 freq_table[i].flags = CPUFREQ_BOOST_FREQ;
75
76 dev_pm_opp_put(opp);
86 } 77 }
87 78
88 freq_table[i].driver_data = i; 79 freq_table[i].driver_data = i;
@@ -91,7 +82,6 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
91 *table = &freq_table[0]; 82 *table = &freq_table[0];
92 83
93out: 84out:
94 rcu_read_unlock();
95 if (ret) 85 if (ret)
96 kfree(freq_table); 86 kfree(freq_table);
97 87
@@ -147,12 +137,6 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of)
147 * This removes the OPP tables for CPUs present in the @cpumask. 137 * This removes the OPP tables for CPUs present in the @cpumask.
148 * This should be used to remove all the OPPs entries associated with 138 * This should be used to remove all the OPPs entries associated with
149 * the cpus in @cpumask. 139 * the cpus in @cpumask.
150 *
151 * Locking: The internal opp_table and opp structures are RCU protected.
152 * Hence this function internally uses RCU updater strategy with mutex locks
153 * to keep the integrity of the internal data structures. Callers should ensure
154 * that this function is *NOT* called under RCU protection or in contexts where
155 * mutex cannot be locked.
156 */ 140 */
157void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask) 141void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask)
158{ 142{
@@ -169,12 +153,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_cpumask_remove_table);
169 * @cpumask. 153 * @cpumask.
170 * 154 *
171 * Returns -ENODEV if OPP table isn't already present. 155 * Returns -ENODEV if OPP table isn't already present.
172 *
173 * Locking: The internal opp_table and opp structures are RCU protected.
174 * Hence this function internally uses RCU updater strategy with mutex locks
175 * to keep the integrity of the internal data structures. Callers should ensure
176 * that this function is *NOT* called under RCU protection or in contexts where
177 * mutex cannot be locked.
178 */ 156 */
179int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, 157int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
180 const struct cpumask *cpumask) 158 const struct cpumask *cpumask)
@@ -184,13 +162,9 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
184 struct device *dev; 162 struct device *dev;
185 int cpu, ret = 0; 163 int cpu, ret = 0;
186 164
187 mutex_lock(&opp_table_lock);
188
189 opp_table = _find_opp_table(cpu_dev); 165 opp_table = _find_opp_table(cpu_dev);
190 if (IS_ERR(opp_table)) { 166 if (IS_ERR(opp_table))
191 ret = PTR_ERR(opp_table); 167 return PTR_ERR(opp_table);
192 goto unlock;
193 }
194 168
195 for_each_cpu(cpu, cpumask) { 169 for_each_cpu(cpu, cpumask) {
196 if (cpu == cpu_dev->id) 170 if (cpu == cpu_dev->id)
@@ -213,8 +187,8 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
213 /* Mark opp-table as multiple CPUs are sharing it now */ 187 /* Mark opp-table as multiple CPUs are sharing it now */
214 opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED; 188 opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
215 } 189 }
216unlock: 190
217 mutex_unlock(&opp_table_lock); 191 dev_pm_opp_put_opp_table(opp_table);
218 192
219 return ret; 193 return ret;
220} 194}
@@ -229,12 +203,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus);
229 * 203 *
230 * Returns -ENODEV if OPP table isn't already present and -EINVAL if the OPP 204 * Returns -ENODEV if OPP table isn't already present and -EINVAL if the OPP
231 * table's status is access-unknown. 205 * table's status is access-unknown.
232 *
233 * Locking: The internal opp_table and opp structures are RCU protected.
234 * Hence this function internally uses RCU updater strategy with mutex locks
235 * to keep the integrity of the internal data structures. Callers should ensure
236 * that this function is *NOT* called under RCU protection or in contexts where
237 * mutex cannot be locked.
238 */ 206 */
239int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) 207int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
240{ 208{
@@ -242,17 +210,13 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
242 struct opp_table *opp_table; 210 struct opp_table *opp_table;
243 int ret = 0; 211 int ret = 0;
244 212
245 mutex_lock(&opp_table_lock);
246
247 opp_table = _find_opp_table(cpu_dev); 213 opp_table = _find_opp_table(cpu_dev);
248 if (IS_ERR(opp_table)) { 214 if (IS_ERR(opp_table))
249 ret = PTR_ERR(opp_table); 215 return PTR_ERR(opp_table);
250 goto unlock;
251 }
252 216
253 if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) { 217 if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) {
254 ret = -EINVAL; 218 ret = -EINVAL;
255 goto unlock; 219 goto put_opp_table;
256 } 220 }
257 221
258 cpumask_clear(cpumask); 222 cpumask_clear(cpumask);
@@ -264,8 +228,8 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
264 cpumask_set_cpu(cpu_dev->id, cpumask); 228 cpumask_set_cpu(cpu_dev->id, cpumask);
265 } 229 }
266 230
267unlock: 231put_opp_table:
268 mutex_unlock(&opp_table_lock); 232 dev_pm_opp_put_opp_table(opp_table);
269 233
270 return ret; 234 return ret;
271} 235}